diff options
Diffstat (limited to 'src/ui/edit.cpp')
-rw-r--r-- | src/ui/edit.cpp | 6632 |
1 files changed, 3316 insertions, 3316 deletions
diff --git a/src/ui/edit.cpp b/src/ui/edit.cpp index 56e6dd8..2988798 100644 --- a/src/ui/edit.cpp +++ b/src/ui/edit.cpp @@ -1,3316 +1,3316 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// edit.cpp
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <windows.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "ui/scroll.h"
-#include "old/text.h"
-#include "ui/edit.h"
-
-
-const float MARGX = (5.0f/640.0f);
-const float MARGY = (5.0f/480.0f);
-const float MARGYS = (4.0f/480.0f);
-const float MARGY1 = (1.0f/480.0f);
-const float DELAY_DBCLICK = 0.3f; // time limit for double-click
-const float DELAY_SCROLL = 0.1f; // time limit for scroll
-const float BIG_FONT = 1.6f; // expansion for \b;
-
-
-
-
-// Indicates whether a character is a space.
-
-bool IsSpace(int character)
-{
- return ( character == ' ' ||
- character == '\t' ||
- character == '\n' );
-}
-
-// Indicates whether a character is part of a word.
-
-bool IsWord(int character)
-{
- char c;
-
- c = tolower(RetNoAccent(character));
-
- return ( (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '_' );
-}
-
-// Indicates whether a character is a word separator.
-
-bool IsSep(int character)
-{
- if ( IsSpace(character) ) return false;
- return !IsWord(character);
-}
-
-
-
-// Object's constructor.
-
-CEdit::CEdit(CInstanceManager* iMan) : CControl(iMan)
-{
- Math::Point pos;
- int i;
-
- m_maxChar = 100;
- m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
- m_format = 0;
- m_len = 0;
-
- m_fontType = FONT_COURIER;
- m_scroll = 0;
- m_bEdit = true;
- m_bHilite = true;
- m_bInsideScroll = true;
- m_bCapture = false;
- m_bDisplaySpec = false;
- m_bSoluce = false;
- m_bGeneric = false;
- m_bAutoIndent = false;
- m_cursor1 = 0;
- m_cursor2 = 0;
- m_column = 0;
- m_imageTotal = 0;
-
- HyperFlush();
-
- for ( i=0 ; i<EDITUNDOMAX ; i++ )
- {
- m_undo[i].text = 0;
- }
- m_bUndoForce = true;
- m_undoOper = OPERUNDO_SPEC;
-}
-
-// Object's destructor.
-
-CEdit::~CEdit()
-{
- int i;
-
- FreeImage();
-
- for ( i=0 ; i<EDITUNDOMAX ; i++ )
- {
- delete m_undo[i].text;
- }
-
- delete m_text;
- delete m_format;
- delete m_scroll;
-}
-
-
-// Creates a new editable line.
-
-bool CEdit::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CScroll* pc;
- Math::Point start, end;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- m_len = 0;
- m_lineFirst = 0;
- m_time = 0.0f;
- m_timeBlink = 0.0f;
- m_timeLastClick = 0.0f;
- m_timeLastScroll = 0.0f;
-
- m_bMulti = false;
- MoveAdjust();
- if ( m_lineVisible <= 1 )
- {
- m_bMulti = false;
- }
- else
- {
- m_bMulti = true;
- MoveAdjust(); // readjusts multi-line mode
- m_scroll = new CScroll(m_iMan);
- pc = (CScroll*)m_scroll;
- pc->Create(pos, dim, -1, EVENT_NULL);
- MoveAdjust();
- }
-
- return true;
-}
-
-
-void CEdit::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
- MoveAdjust();
-}
-
-void CEdit::SetDim(Math::Point dim)
-{
- CControl::SetDim(dim);
- MoveAdjust();
-}
-
-void CEdit::MoveAdjust()
-{
- Math::Point pos, dim;
- float height;
-
- m_lineDescent = m_engine->RetText()->RetDescent(m_fontSize, m_fontType);
- m_lineAscent = m_engine->RetText()->RetAscent(m_fontSize, m_fontType);
- m_lineHeight = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
-
- height = m_dim.y-(m_bMulti?MARGY*2.0f:MARGY1);
- m_lineVisible = (int)(height/m_lineHeight);
-
- if ( m_scroll != 0 )
- {
- if ( m_bInsideScroll )
- {
- pos.x = m_pos.x+m_dim.x-MARGX-SCROLL_WIDTH;
- pos.y = m_pos.y+MARGYS;
- dim.x = SCROLL_WIDTH;
- dim.y = m_dim.y-MARGYS*2.0f;
- }
- else
- {
- pos.x = m_pos.x+m_dim.x-SCROLL_WIDTH;
- pos.y = m_pos.y;
- dim.x = SCROLL_WIDTH;
- dim.y = m_dim.y;
- }
- m_scroll->SetPos(pos);
- m_scroll->SetDim(dim);
- }
-
- Justif();
-
- if ( m_lineFirst > m_lineTotal-m_lineVisible )
- {
- m_lineFirst = m_lineTotal-m_lineVisible;
- if ( m_lineFirst < 0 ) m_lineFirst = 0;
- }
-
- pos.x = m_pos.x+m_dim.x-(m_bMulti?SCROLL_WIDTH:0.0f);
- pos.y = m_pos.y;
- GlintCreate(pos, false, false);
-}
-
-
-// Management of an event.
-
-bool CEdit::EventProcess(const Event &event)
-{
- bool bShift, bControl;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) )
- {
- Scroll(m_lineFirst-3, true);
- return true;
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) )
- {
- Scroll(m_lineFirst+3, true);
- return true;
- }
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- m_time += event.rTime;
- m_timeBlink += event.rTime;
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- if ( Detect(event.pos) &&
- event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
- {
- if ( m_bEdit )
- {
- m_engine->SetMouseType(D3DMOUSEEDIT);
- }
- else
- {
- if ( IsLinkPos(event.pos) )
- {
- m_engine->SetMouseType(D3DMOUSEHAND);
- }
- else
- {
- m_engine->SetMouseType(D3DMOUSENORM);
- }
- }
- }
- }
-
- if ( m_scroll != 0 && !m_bGeneric )
- {
- m_scroll->EventProcess(event);
-
- if ( event.event == m_scroll->RetEventMsg() )
- {
- Scroll();
- return true;
- }
- }
-
- if ( event.event == EVENT_KEYDOWN && m_bFocus )
- {
- bShift = (event.keyState&KS_SHIFT);
- bControl = (event.keyState&KS_CONTROL);
-
- if ( (event.param == 'X' && !bShift && bControl) ||
- (event.param == VK_DELETE && bShift && !bControl) )
- {
- Cut();
- return true;
- }
- if ( (event.param == 'C' && !bShift && bControl) ||
- (event.param == VK_INSERT && !bShift && bControl) )
- {
- Copy();
- return true;
- }
- if ( (event.param == 'V' && !bShift && bControl) ||
- (event.param == VK_INSERT && bShift && !bControl) )
- {
- Paste();
- return true;
- }
-
- if ( event.param == 'A' && !bShift && bControl )
- {
- SetCursor(999999, 0);
- return true;
- }
-
- if ( event.param == 'O' && !bShift && bControl )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_STUDIO_OPEN);
- m_event->AddEvent(newEvent);
- }
- if ( event.param == 'S' && !bShift && bControl )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_STUDIO_SAVE);
- m_event->AddEvent(newEvent);
- }
-
- if ( event.param == 'Z' && !bShift && bControl )
- {
- Undo();
- return true;
- }
-
- if ( event.param == 'U' && !bShift && bControl )
- {
- if ( MinMaj(false) ) return true;
- }
- if ( event.param == 'U' && bShift && bControl )
- {
- if ( MinMaj(true) ) return true;
- }
-
- if ( event.param == VK_TAB && !bShift && !bControl && !m_bAutoIndent )
- {
- if ( Shift(false) ) return true;
- }
- if ( event.param == VK_TAB && bShift && !bControl && !m_bAutoIndent )
- {
- if ( Shift(true) ) return true;
- }
-
- if ( m_bEdit )
- {
- if ( event.param == VK_LEFT )
- {
- MoveChar(-1, bControl, bShift);
- return true;
- }
- if ( event.param == VK_RIGHT )
- {
- MoveChar(1, bControl, bShift);
- return true;
- }
- if ( event.param == VK_UP )
- {
- MoveLine(-1, bControl, bShift);
- return true;
- }
- if ( event.param == VK_DOWN )
- {
- MoveLine(1, bControl, bShift);
- return true;
- }
-
- if ( event.param == VK_PRIOR ) // PageUp ?
- {
- MoveLine(-(m_lineVisible-1), bControl, bShift);
- return true;
- }
- if ( event.param == VK_NEXT ) // PageDown ?
- {
- MoveLine(m_lineVisible-1, bControl, bShift);
- return true;
- }
- }
- else
- {
- if ( event.param == VK_LEFT ||
- event.param == VK_UP )
- {
- Scroll(m_lineFirst-1, true);
- return true;
- }
- if ( event.param == VK_RIGHT ||
- event.param == VK_DOWN )
- {
- Scroll(m_lineFirst+1, true);
- return true;
- }
-
- if ( event.param == VK_PRIOR ) // PageUp ?
- {
- Scroll(m_lineFirst-(m_lineVisible-1), true);
- return true;
- }
- if ( event.param == VK_NEXT ) // PageDown ?
- {
- Scroll(m_lineFirst+(m_lineVisible-1), true);
- return true;
- }
- }
-
- if ( event.param == VK_HOME )
- {
- MoveHome(bControl, bShift);
- return true;
- }
- if ( event.param == VK_END )
- {
- MoveEnd(bControl, bShift);
- return true;
- }
-
- if ( event.param == VK_BACK ) // backspace ( <- ) ?
- {
- Delete(-1);
- SendModifEvent();
- return true;
- }
- if ( event.param == VK_DELETE )
- {
- Delete(1);
- SendModifEvent();
- return true;
- }
-
- if ( event.param == VK_RETURN )
- {
- Insert('\n');
- SendModifEvent();
- return true;
- }
- if ( event.param == VK_TAB )
- {
- Insert('\t');
- SendModifEvent();
- return true;
- }
- }
-
- if ( event.event == EVENT_CHAR && m_bFocus )
- {
- if ( event.param >= ' ' && event.param <= 255 )
- {
- Insert((char)event.param);
- SendModifEvent();
- return true;
- }
- }
-
- if ( event.event == EVENT_FOCUS )
- {
- if ( event.param == m_eventMsg )
- {
- m_bFocus = true;
- }
- else
- {
- m_bFocus = false;
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- m_mouseFirstPos = event.pos;
- m_mouseLastPos = event.pos;
- if ( Detect(event.pos) )
- {
- if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
- {
- MouseClick(event.pos);
- if ( m_bEdit || m_bHilite ) m_bCapture = true;
- }
- m_bFocus = true;
- }
- else
- {
- m_bFocus = false;
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- m_mouseLastPos = event.pos;
- MouseMove(event.pos);
- }
-
- if ( event.event == EVENT_FRAME && m_bCapture )
- {
- MouseMove(m_mouseLastPos);
- }
-
- if ( event.event == EVENT_LBUTTONUP )
- {
- if ( Detect(event.pos) )
- {
- if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
- {
- MouseRelease(m_mouseFirstPos);
- }
- }
- if ( m_bCapture )
- {
- if ( m_timeLastClick+DELAY_DBCLICK > m_time ) // double-click ?
- {
- MouseDoubleClick(event.pos);
- }
- m_timeLastClick = m_time;
- m_bCapture = false;
- }
- }
-
- return true;
-}
-
-
-// Sends an event to indicate that the text was modified.
-
-void CEdit::SendModifEvent()
-{
- Event newEvent;
-
- m_event->MakeEvent(newEvent, m_eventMsg);
- m_event->AddEvent(newEvent);
-}
-
-
-// Detects whether the mouse is over a hyperlink character.
-
-bool CEdit::IsLinkPos(Math::Point pos)
-{
- int i;
-
- if ( m_format == 0 ) return false;
-
- i = MouseDetect(pos);
- if ( i == -1 ) return false;
- if ( i >= m_len ) return false;
-
- if ( (m_format[i]&COLOR_MASK) == COLOR_LINK ) return true;
- return false;
-}
-
-
-// Positions the cursor after a double click.
-
-void CEdit::MouseDoubleClick(Math::Point mouse)
-{
- int i, character;
-
- if ( m_bMulti ) // Multi-line?
- {
- i = MouseDetect(mouse);
- if ( i == -1 ) return;
-
- while ( i > 0 )
- {
- character = (unsigned char)m_text[i-1];
- if ( !IsWord(character) ) break;
- i --;
- }
- m_cursor2 = i;
-
- while ( i < m_len )
- {
- character = (unsigned char)m_text[i];
- if ( !IsWord(character) ) break;
- i ++;
- }
- m_cursor1 = i;
- }
- else // single-line?
- {
- m_cursor2 = 0;
- m_cursor1 = m_len; // selects all
- }
-
- m_bUndoForce = true;
-
- Justif();
- ColumnFix();
-}
-
-// Positions the cursor when clicked.
-
-void CEdit::MouseClick(Math::Point mouse)
-{
- int i;
-
- i = MouseDetect(mouse);
- if ( i == -1 ) return;
-
- if ( m_bEdit || m_bHilite )
- {
- m_cursor1 = i;
- m_cursor2 = i;
- m_bUndoForce = true;
- m_timeBlink = 0.0f; // lights the cursor immediately
- ColumnFix();
- }
-}
-
-// Positions the cursor when clicked released.
-
-void CEdit::MouseRelease(Math::Point mouse)
-{
- int i, j, rank;
-
- i = MouseDetect(mouse);
- if ( i == -1 ) return;
-
- if ( !m_bEdit )
- {
- if ( m_format != 0 && i < m_len && m_cursor1 == m_cursor2 &&
- (m_format[i]&COLOR_MASK) == COLOR_LINK )
- {
- rank = -1;
- for ( j=0 ; j<=i ; j++ )
- {
- if ( (j == 0 || (m_format[j-1]&COLOR_MASK) != COLOR_LINK) &&
- (m_format[j+0]&COLOR_MASK) == COLOR_LINK )
- {
- rank ++;
- }
- }
- HyperJump(m_link[rank].name, m_link[rank].marker);
- }
- }
-}
-
-// Positions the cursor after movement.
-
-void CEdit::MouseMove(Math::Point mouse)
-{
- int i;
-
- if ( m_bMulti &&
- m_timeLastScroll+DELAY_SCROLL <= m_time )
- {
- if ( mouse.y > m_pos.y+m_dim.y ) // above?
- {
- Scroll(m_lineFirst-1, false);
- mouse.y = m_pos.y+m_dim.y-MARGY-m_lineHeight/2.0f;
- }
- if ( mouse.y < m_pos.y ) // lower?
- {
- Scroll(m_lineFirst+1, false);
- mouse.y = m_pos.y+m_dim.y-MARGY-m_lineVisible*m_lineHeight+m_lineHeight/2.0f;
- }
- m_timeLastScroll = m_time;
- }
-
- i = MouseDetect(mouse);
- if ( i != -1 )
- {
- m_cursor1 = i;
- m_bUndoForce = true;
- m_timeBlink = 0.0f; // lights the cursor immediately
- ColumnFix();
- }
-}
-
-// Positions the cursor when clicked.
-
-int CEdit::MouseDetect(Math::Point mouse)
-{
- Math::Point pos;
- float indentLength, offset, size;
- int i, len, c;
- bool bTitle;
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- }
-
- pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1);
- for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
- {
- bTitle = ( m_format != 0 && (m_format[m_lineOffset[i]]&TITLE_MASK) == TITLE_BIG );
-
- if ( i >= m_lineFirst+m_lineVisible ) break;
-
- pos.x = m_pos.x+(10.0f/640.0f);
- if ( m_bAutoIndent )
- {
- pos.x += indentLength*m_lineIndent[i];
- }
- offset = mouse.x-pos.x;
-
- if ( bTitle ) pos.y -= m_lineHeight;
-
- if ( mouse.y > pos.y )
- {
- len = m_lineOffset[i+1] - m_lineOffset[i];
-
- if ( m_format == 0 )
- {
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[i],
- len, offset, m_fontSize,
- m_fontStretch, m_fontType);
- }
- else
- {
- size = m_fontSize;
- if ( bTitle ) size *= BIG_FONT;
-
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[i],
- m_format+m_lineOffset[i],
- len, offset, size,
- m_fontStretch);
- }
- return m_lineOffset[i]+c;
- }
-
- if ( bTitle ) i ++;
- pos.y -= m_lineHeight;
- }
- return -1;
-}
-
-
-// Clears all history.
-
-void CEdit::HyperFlush()
-{
- m_historyTotal = 0;
- m_historyCurrent = -1;
-}
-
-// Indicates which is the home page.
-
-void CEdit::HyperHome(char *filename)
-{
- HyperFlush();
- HyperAdd(filename, 0);
-}
-
-// Performs a hyper jump through a link.
-
-void CEdit::HyperJump(char *name, char *marker)
-{
- char filename[100];
- char sMarker[100];
- int i, line, pos;
-
- if ( m_historyCurrent >= 0 )
- {
- m_history[m_historyCurrent].firstLine = m_lineFirst;
- }
-
- strcpy(sMarker, marker);
-
-//? sprintf(filename, "help\\%s.txt", name);
- if ( name[0] == '%' )
- {
- UserDir(filename, name, "");
- strcat(filename, ".txt");
- }
- else
- {
- sprintf(filename, "help\\%s.txt", name);
- }
- if ( ReadText(filename) )
- {
- Justif();
-
- line = 0;
- for ( i=0 ; i<m_markerTotal ; i++ )
- {
- if ( strcmp(sMarker, m_marker[i].name) == 0 )
- {
- pos = m_marker[i].pos;
- for ( i=0 ; i<m_lineTotal ; i++ )
- {
- if ( pos >= m_lineOffset[i] )
- {
- line = i;
- }
- }
- break;
- }
- }
-
- SetFirstLine(line);
- HyperAdd(filename, line);
- }
-}
-
-// Adds text to the history of visited.
-
-bool CEdit::HyperAdd(char *filename, int firstLine)
-{
- if ( m_historyCurrent >= EDITHISTORYMAX-1 ) return false;
-
- m_historyCurrent ++;
- strcpy(m_history[m_historyCurrent].filename, filename);
- m_history[m_historyCurrent].firstLine = firstLine;
-
- m_historyTotal = m_historyCurrent+1;
- return true;
-}
-
-// Indicates whether a button EVENT_HYPER_ * is active or not.
-
-bool CEdit::HyperTest(EventMsg event)
-{
- if ( event == EVENT_HYPER_HOME )
- {
- return ( m_historyCurrent > 0 );
- }
-
- if ( event == EVENT_HYPER_PREV )
- {
- return ( m_historyCurrent > 0 );
- }
-
- if ( event == EVENT_HYPER_NEXT )
- {
- return ( m_historyCurrent < m_historyTotal-1 );
- }
-
- return false;
-}
-
-// Performs the action corresponding to a button EVENT_HYPER_ *.
-
-bool CEdit::HyperGo(EventMsg event)
-{
- if ( !HyperTest(event) ) return false;
-
- m_history[m_historyCurrent].firstLine = m_lineFirst;
-
- if ( event == EVENT_HYPER_HOME )
- {
- m_historyCurrent = 0;
- }
-
- if ( event == EVENT_HYPER_PREV )
- {
- m_historyCurrent --;
- }
-
- if ( event == EVENT_HYPER_NEXT )
- {
- m_historyCurrent ++;
- }
-
- ReadText(m_history[m_historyCurrent].filename);
- Justif();
- SetFirstLine(m_history[m_historyCurrent].firstLine);
- return true;
-}
-
-
-// Draw the editable line.
-
-void CEdit::Draw()
-{
- Math::Point pos, ppos, dim, start, end;
- float size, indentLength;
- int i, j, beg, len, c1, c2, o1, o2, eol, iIndex, line;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- pos.x = m_pos.x;
- pos.y = m_pos.y;
- dim.x = m_dim.x;
- if ( !m_bInsideScroll ) dim.x -= m_bMulti?SCROLL_WIDTH:0.0f;
- dim.y = m_dim.y;
- DrawBack(pos, dim); // background
-
- // Displays all lines.
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( m_bInsideScroll )
- {
- dim.x -= m_bMulti?SCROLL_WIDTH:0.0f + (1.0f/640.0f);
- }
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- }
-
- pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1);
- for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
- {
- if ( i == m_lineFirst && i < m_lineTotal-1 &&
- m_lineOffset[i] == m_lineOffset[i+1] )
- {
- pos.y -= m_lineHeight; // Double jump line \b;
- i ++;
- }
-
- if ( i >= m_lineFirst+m_lineVisible ) break;
-
- pos.x = m_pos.x+(10.0f/640.0f);
- if ( m_bAutoIndent )
- {
- for ( j=0 ; j<m_lineIndent[i] ; j++ )
- {
- char s = '\t'; // line | dotted
- m_engine->RetText()->DrawText(&s, 1, pos, 1.0f, 1, m_fontSize, m_fontStretch, m_fontType, 0);
- pos.x += indentLength;
- }
- }
-
- beg = m_lineOffset[i];
- len = m_lineOffset[i+1] - m_lineOffset[i];
-
- ppos = pos;
- size = m_fontSize;
-
- // Headline \b;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&TITLE_MASK) == TITLE_BIG )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1)-m_lineHeight*(BIG_FONT-1.0f);
- end.y = m_lineHeight*BIG_FONT;
- DrawPart(start, end, 2); // blue gradient background ->
-
- size *= BIG_FONT;
- ppos.y -= m_lineHeight*(BIG_FONT-1.0f);
- }
-
- // As \t;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&TITLE_MASK) == TITLE_NORM )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- DrawPart(start, end, 2); // blue gradient background ->
- }
-
- // Subtitle \s;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&TITLE_MASK) == TITLE_LITTLE )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- DrawPart(start, end, 3); // yellow background gradient ->
- }
-
- // Table \tab;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&COLOR_MASK) == COLOR_TABLE )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- DrawPart(start, end, 11); // fond orange d�grad� ->
- }
-
- // Image \image; ?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&IMAGE_MASK) != 0 )
- {
- line = 1;
- while ( true ) // includes the image slices
- {
- if ( i+line >= m_lineTotal ||
- i+line >= m_lineFirst+m_lineVisible ||
- (m_format[beg+line]&IMAGE_MASK) == 0 ) break;
- line ++;
- }
-
- iIndex = m_text[beg]; // character = index in m_image
- pos.y -= m_lineHeight*(line-1);
- DrawImage(pos, m_image[iIndex].name,
- m_image[iIndex].width*(m_fontSize/SMALLFONT),
- m_image[iIndex].offset, m_image[iIndex].height*line, line);
- pos.y -= m_lineHeight;
- i += line-1;
- continue;
- }
-
- if ( ((m_bEdit && m_bFocus && m_bHilite) ||
- (!m_bEdit && m_bHilite) ) &&
- c1 != c2 && beg <= c2 && beg+len >= c1 ) // selected area?
- {
- o1 = c1; if ( o1 < beg ) o1 = beg;
- o2 = c2; if ( o2 > beg+len ) o2 = beg+len;
-
- if ( m_format == 0 )
- {
- start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, o1-beg, size, m_fontStretch, m_fontType);
- end.x = m_engine->RetText()->RetStringWidth(m_text+o1, o2-o1, size, m_fontStretch, m_fontType);
- }
- else
- {
- start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, m_format+beg, o1-beg, size, m_fontStretch);
- end.x = m_engine->RetText()->RetStringWidth(m_text+o1, m_format+o1, o2-o1, size, m_fontStretch);
- }
-
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- if ( m_format != 0 && (m_format[beg]&TITLE_MASK) == TITLE_BIG ) end.y *= BIG_FONT;
- DrawPart(start, end, 1); // plain yellow background
- }
-
- eol = 16; // >
- if ( len > 0 && m_text[beg+len-1] == '\n' )
- {
- len --; // does not display the '\ n'
- eol = 0; // nothing
- }
- if ( beg+len >= m_len )
- {
- eol = 2; // square (eot)
- }
- if ( !m_bMulti || !m_bDisplaySpec ) eol = 0;
- if ( m_format == 0 )
- {
- m_engine->RetText()->DrawText(m_text+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, m_fontType, eol);
- }
- else
- {
- m_engine->RetText()->DrawText(m_text+beg, m_format+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, eol);
- }
-
- pos.y -= m_lineHeight;
-
- if ( i < m_lineTotal-2 && m_lineOffset[i+1] == m_lineOffset[i+2] )
- {
- pos.y -= m_lineHeight; // double jump line \b;
- i ++;
- }
- }
-
- // Shows the cursor.
- if ( (m_bEdit && m_bFocus && m_bHilite && Math::Mod(m_timeBlink, 1.0f) <= 0.5f) ) // it blinks
- {
- pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1*2.0f);
- for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
- {
- if ( i == m_lineTotal-1 || m_cursor1 < m_lineOffset[i+1] )
- {
- pos.x = m_pos.x+(10.0f/640.0f);
- if ( m_bAutoIndent )
- {
- pos.x += indentLength*m_lineIndent[i];
- }
-
- len = m_cursor1 - m_lineOffset[i];
-
- if ( m_format == 0 )
- {
- m_engine->RetText()->DimText(m_text+m_lineOffset[i], len,
- pos, 1, size,
- m_fontStretch, m_fontType,
- start, end);
- }
- else
- {
- m_engine->RetText()->DimText(m_text+m_lineOffset[i],
- m_format+m_lineOffset[i],
- len, pos, 1, size,
- m_fontStretch,
- start, end);
- }
-
- pos.x = end.x;
- break;
- }
- pos.y -= m_lineHeight;
- }
- pos.x -= 1.0f/640.0f;
- dim.x = 2.0f/640.0f;
- dim.y = m_lineHeight;
- DrawPart(pos, dim, 0); // red
- }
-
- if ( m_scroll != 0 && !m_bGeneric )
- {
- m_scroll->Draw();
- }
-}
-
-// Draw an image part.
-
-void CEdit::DrawImage(Math::Point pos, char *name, float width,
- float offset, float height, int nbLine)
-{
- Math::Point uv1, uv2, dim;
- float dp;
- char filename[100];
-
-//? sprintf(filename, "diagram\\%s.bmp", name);
- UserDir(filename, name, "diagram");
- strcat(filename, ".bmp");
-
- m_engine->SetTexture(filename);
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = 0.0f;
- uv2.x = 1.0f;
- uv1.y = offset;
- uv2.y = offset+height;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- dim.x = width;
- dim.y = m_lineHeight*nbLine;
- DrawIcon(pos, dim, uv1, uv2);
-}
-
-// Draw the background.
-
-void CEdit::DrawBack(Math::Point pos, Math::Point dim)
-{
- Math::Point uv1,uv2, corner;
- float dp;
-
- if ( m_bGeneric ) return;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- if ( m_bMulti )
- {
- uv1.x = 128.0f/256.0f; // light blue
- uv1.y = 64.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 96.0f/256.0f;
- }
- else
- {
- uv1.x = 160.0f/256.0f; // medium blue
- uv1.y = 192.0f/256.0f;
- uv2.x = 192.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- }
- if ( m_icon == 1 )
- {
- uv1.x = 192.0f/256.0f; // orange
- uv1.y = 96.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 128.0f/256.0f;
- }
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- if ( m_bMulti )
- {
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- else
- {
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
-}
-
-// Draws an icon background.
-
-void CEdit::DrawPart(Math::Point pos, Math::Point dim, int icon)
-{
- Math::Point uv1, uv2;
- float dp;
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = (16.0f/256.0f)*(icon%16);
- uv1.y = (240.0f/256.0f);
- uv2.x = (16.0f/256.0f)+uv1.x;
- uv2.y = (16.0f/256.0f)+uv1.y;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(pos, dim, uv1, uv2);
-}
-
-
-// Give the text to edit.
-
-void CEdit::SetText(char *text, bool bNew)
-{
- int i, j, font;
- bool bBOL;
-
- if ( !bNew ) UndoMemorize(OPERUNDO_SPEC);
-
- m_len = strlen(text);
- if ( m_len > m_maxChar ) m_len = m_maxChar;
-
- if ( m_format == 0 )
- {
- if ( m_bAutoIndent )
- {
- j = 0;
- bBOL = true;
- for ( i=0 ; i<m_len ; i++ )
- {
- if ( text[i] == '\t' )
- {
- if ( !bBOL ) m_text[j++] = ' ';
- continue; // removes tabs
- }
- bBOL = ( text[i] == '\n' );
-
- m_text[j++] = text[i];
- }
- m_len = j;
- }
- else
- {
- strncpy(m_text, text, m_len);
- }
- }
- else
- {
- font = m_fontType;
- j = 0;
- bBOL = true;
- for ( i=0 ; i<m_len ; i++ )
- {
- if ( m_bAutoIndent )
- {
- if ( text[i] == '\t' )
- {
- if ( !bBOL )
- {
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
- }
- continue; // removes tabs
- }
- bBOL = ( text[i] == '\n' );
- }
-
- if ( text[i] == '\\' && text[i+2] == ';' )
- {
- if ( text[i+1] == 'n' ) // normal ?
- {
- font &= ~FONT_MASK;
- font |= FONT_COLOBOT;
- i += 2;
- }
- else if ( text[i+1] == 'c' ) // cbot ?
- {
- font &= ~FONT_MASK;
- font |= FONT_COURIER;
- i += 2;
- }
- else if ( text[i+1] == 'b' ) // big title ?
- {
- font &= ~TITLE_MASK;
- font |= TITLE_BIG;
- i += 2;
- }
- else if ( text[i+1] == 't' ) // title ?
- {
- font &= ~TITLE_MASK;
- font |= TITLE_NORM;
- i += 2;
- }
- else if ( text[i+1] == 's' ) // subtitle ?
- {
- font &= ~TITLE_MASK;
- font |= TITLE_LITTLE;
- i += 2;
- }
- }
- else
- {
- m_text[j] = text[i];
- m_format[j] = font;
- j ++;
-
- font &= ~TITLE_MASK; // reset title
- }
- }
- m_len = j;
- }
-
- if ( bNew ) UndoFlush();
-
- m_cursor1 = 0;
- m_cursor2 = 0; // cursor to the beginning
- Justif();
- ColumnFix();
-}
-
-// Returns a pointer to the edited text.
-
-char* CEdit::RetText()
-{
- m_text[m_len] = 0;
- return m_text;
-}
-
-// Returns the edited text.
-
-void CEdit::GetText(char *buffer, int max)
-{
- if ( m_len < max ) max = m_len;
- if ( m_len > max ) max = max-1;
-
- strncpy(buffer, m_text, max);
- buffer[max] = 0;
-}
-
-// Returns the length of the text.
-
-int CEdit::RetTextLength()
-{
- return m_len;
-}
-
-
-
-// Returns a name in a command.
-// \x nom1 nom2 nom3;
-
-void GetNameParam(char *cmd, int rank, char *buffer)
-{
- int i;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( *cmd != ' ' && *cmd != ';' )
- {
- cmd ++;
- }
- if ( *cmd != ';' ) cmd ++;
- }
-
- while ( *cmd != ' ' && *cmd != ';' )
- {
- *buffer++ = *cmd++;
- }
- *buffer = 0;
-}
-
-// Returns a number of a command.
-// \x nom n1 n2;
-
-int RetValueParam(char *cmd, int rank)
-{
- int n, i;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( *cmd != ' ' && *cmd != ';' )
- {
- cmd ++;
- }
- if ( *cmd != ';' ) cmd ++;
- }
-
- sscanf(cmd, "%d", &n);
- return n;
-}
-
-// Frees all images.
-
-void CEdit::FreeImage()
-{
- char filename[100];
- int i;
-
- for ( i=0 ; i<m_imageTotal ; i++ )
- {
-//? sprintf(filename, "diagram\\%s.bmp", m_image[i].name);
- UserDir(filename, m_image[i].name, "diagram");
- strcat(filename, ".bmp");
- m_engine->FreeTexture(filename);
- }
-}
-
-// Reads the texture of an image.
-
-void CEdit::LoadImage(char *name)
-{
- char filename[100];
-
-//? sprintf(filename, "diagram\\%s.bmp", name);
- UserDir(filename, name, "diagram");
- strcat(filename, ".bmp");
- m_engine->LoadTexture(filename);
-}
-
-// Read from a text file.
-
-bool CEdit::ReadText(char *filename, int addSize)
-{
- FILE *file = NULL;
- char *buffer;
- int len, i, j, n, font, iIndex, iLines, iCount, iLink, res;
- char iName[50];
- char text[50];
- float iWidth;
- KeyRank key;
- bool bInSoluce, bBOL;
-
- if ( filename[0] == 0 ) return false;
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
-
- fseek(file, 0, SEEK_END);
- len = ftell(file);
- fseek(file, 0, SEEK_SET);
-
- m_maxChar = len+addSize+100;
- m_len = len;
- m_cursor1 = 0;
- m_cursor2 = 0;
-
- FreeImage();
- delete m_text;
- m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
- buffer = (char*)malloc(sizeof(char)*(m_maxChar+1));
- fread(buffer, 1, len, file);
-
- if ( m_format != 0 )
- {
- delete m_format;
- m_format = (char*)malloc(sizeof(char)*m_maxChar);
- }
-
- fclose(file);
-
- bInSoluce = false;
- font = m_fontType;
- iIndex = 0;
- iLink = 0;
- m_imageTotal = 0;
- m_markerTotal = 0;
- i = j = 0;
- bBOL = true;
- while ( i < m_len )
- {
- if ( m_bAutoIndent )
- {
- if ( buffer[i] == '\t' )
- {
- if ( !bBOL )
- {
- m_text[j] = buffer[i];
- if ( m_format != 0 ) m_format[j] = font;
- j ++;
- }
- i ++;
- continue; // removes the tabs
- }
- bBOL = ( buffer[i] == '\n' || buffer[i] == '\r' );
- }
-
- if ( buffer[i] == '\r' ) // removes \ r
- {
- i ++;
- }
- else if ( m_format != 0 && buffer[i] == '\\' && buffer[i+2] == ';' )
- {
- if ( buffer[i+1] == 'n' ) // normal ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~FONT_MASK;
- font |= FONT_COLOBOT;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 'c' ) // cbot ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~FONT_MASK;
- font |= FONT_COURIER;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 'b' ) // big title ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~TITLE_MASK;
- font |= TITLE_BIG;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 't' ) // title ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~TITLE_MASK;
- font |= TITLE_NORM;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 's' ) // subtitle ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~TITLE_MASK;
- font |= TITLE_LITTLE;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 'l' ) // link ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_LINK;
- }
- i += 3;
- }
- else
- {
- i += 3;
- }
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \u marker name; ?
- buffer[i+1] == 'u' &&
- buffer[i+2] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- if ( iLink < EDITLINKMAX )
- {
- GetNameParam(buffer+i+3, 0, m_link[iLink].name);
- GetNameParam(buffer+i+3, 1, m_link[iLink].marker);
- iLink ++;
- }
- font &= ~COLOR_MASK;
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \m marker; ?
- buffer[i+1] == 'm' &&
- buffer[i+2] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- if ( m_markerTotal < EDITLINKMAX )
- {
- GetNameParam(buffer+i+3, 0, m_marker[m_markerTotal].name);
- m_marker[m_markerTotal].pos = j;
- m_markerTotal ++;
- }
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \image name lx ly; ?
- buffer[i+1] == 'i' &&
- buffer[i+2] == 'm' &&
- buffer[i+3] == 'a' &&
- buffer[i+4] == 'g' &&
- buffer[i+5] == 'e' &&
- buffer[i+6] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
-#if _DEMO
- strcpy(iName, "demo");
-#else
- GetNameParam(buffer+i+7, 0, iName);
-#endif
-//? iWidth = m_lineHeight*RetValueParam(buffer+i+7, 1);
- iWidth = (float)RetValueParam(buffer+i+7, 1);
- iWidth *= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT);
- iLines = RetValueParam(buffer+i+7, 2);
- LoadImage(iName);
-
- // A part of image per line of text.
- for ( iCount=0 ; iCount<iLines ; iCount++ )
- {
- strcpy(m_image[iIndex].name, iName);
- m_image[iIndex].offset = (float)iCount/iLines;
- m_image[iIndex].height = 1.0f/iLines;
- m_image[iIndex].width = iWidth*0.75f;
-
- m_text[j] = (char)(iIndex++); // as an index into m_image
- m_format[j] = (unsigned char)IMAGE_MASK;
- j ++;
- }
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \button; ?
- buffer[i+1] == 'b' &&
- buffer[i+2] == 'u' &&
- buffer[i+3] == 't' &&
- buffer[i+4] == 't' &&
- buffer[i+5] == 'o' &&
- buffer[i+6] == 'n' &&
- buffer[i+7] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- m_text[j] = RetValueParam(buffer+i+8, 0);
- m_format[j] = font|FONT_BUTTON;
- j ++;
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \token; ?
- buffer[i+1] == 't' &&
- buffer[i+2] == 'o' &&
- buffer[i+3] == 'k' &&
- buffer[i+4] == 'e' &&
- buffer[i+5] == 'n' &&
- buffer[i+6] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_TOKEN;
- }
- i += 7;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \type; ?
- buffer[i+1] == 't' &&
- buffer[i+2] == 'y' &&
- buffer[i+3] == 'p' &&
- buffer[i+4] == 'e' &&
- buffer[i+5] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_TYPE;
- }
- i += 6;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \const; ?
- buffer[i+1] == 'c' &&
- buffer[i+2] == 'o' &&
- buffer[i+3] == 'n' &&
- buffer[i+4] == 's' &&
- buffer[i+5] == 't' &&
- buffer[i+6] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_CONST;
- }
- i += 7;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \key; ?
- buffer[i+1] == 'k' &&
- buffer[i+2] == 'e' &&
- buffer[i+3] == 'y' &&
- buffer[i+4] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_KEY;
- }
- i += 5;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \tab; ?
- buffer[i+1] == 't' &&
- buffer[i+2] == 'a' &&
- buffer[i+3] == 'b' &&
- buffer[i+4] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font |= COLOR_TABLE;
- }
- i += 5;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \norm; ?
- buffer[i+1] == 'n' &&
- buffer[i+2] == 'o' &&
- buffer[i+3] == 'r' &&
- buffer[i+4] == 'm' &&
- buffer[i+5] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- }
- i += 6;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \begin soluce; ?
- buffer[i+1] == 'b' &&
- buffer[i+2] == 's' &&
- buffer[i+3] == ';' )
- {
- bInSoluce = true;
- i += 4;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \end soluce; ?
- buffer[i+1] == 'e' &&
- buffer[i+2] == 's' &&
- buffer[i+3] == ';' )
- {
- bInSoluce = false;
- i += 4;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \key name; ?
- buffer[i+1] == 'k' &&
- buffer[i+2] == 'e' &&
- buffer[i+3] == 'y' &&
- buffer[i+4] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- if ( SearchKey(buffer+i+5, key) )
- {
- res = m_engine->RetKey(key, 0);
- if ( res != 0 )
- {
- if ( GetResource(RES_KEY, res, iName) )
- {
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
- n = 0;
- while ( iName[n] != 0 )
- {
- m_text[j] = iName[n++];
- m_format[j] = font;
- j ++;
- }
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
-
- res = m_engine->RetKey(key, 1);
- if ( res != 0 )
- {
- if ( GetResource(RES_KEY, res, iName) )
- {
- GetResource(RES_TEXT, RT_KEY_OR, text);
- n = 0;
- while ( text[n] != 0 )
- {
- m_text[j] = text[n++];
- m_format[j] = font&~COLOR_MASK;
- j ++;
- }
- n = 0;
- while ( iName[n] != 0 )
- {
- m_text[j] = iName[n++];
- m_format[j] = font;
- j ++;
- }
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
- }
- }
- while ( buffer[i++] != ';' );
- continue;
- }
- }
- }
- m_text[j] = '?';
- m_format[j] = font;
- j ++;
- }
- while ( buffer[i++] != ';' );
- }
- else
- {
- if ( m_bSoluce || !bInSoluce )
- {
- m_text[j] = buffer[i];
- if ( m_format != 0 ) m_format[j] = font;
- j ++;
- }
- i ++;
-
- font &= ~TITLE_MASK; // reset title
-
- if ( (font&COLOR_MASK) == COLOR_TABLE )
- {
- font &= ~COLOR_TABLE;
- }
- }
- }
- m_len = j;
- m_imageTotal = iIndex;
-
- delete buffer;
-
- Justif();
- ColumnFix();
- return true;
-}
-
-// Writes all the text in a file.
-
-bool CEdit::WriteText(char *filename)
-{
- FILE* file;
- char buffer[1000+20];
- int i, j, k, n;
- float iDim;
-
- if ( filename[0] == 0 ) return false;
- file = fopen(filename, "wb");
- if ( file == NULL ) return false;
-
- if ( m_bAutoIndent )
- {
- iDim = m_dim.x;
- m_dim.x = 1000.0f; // puts an infinite width!
- Justif();
- }
-
- i = j = k = 0;
- while ( m_text[i] != 0 && i < m_len )
- {
- if ( m_bAutoIndent && i == m_lineOffset[k] )
- {
- for ( n=0 ; n<m_lineIndent[k] ; n++ )
- {
- buffer[j++] = '\t';
- }
- k ++;
- }
-
- buffer[j++] = m_text[i];
-
- if ( m_text[i] == '\n' )
- {
- buffer[j-1] = '\r';
- buffer[j++] = '\n'; // \r\n (0x0D, 0x0A)
- }
-
- if ( j >= 1000-1 )
- {
- fwrite(buffer, 1, j, file);
- j = 0;
- }
-
- i ++;
- }
- if ( j > 0 )
- {
- fwrite(buffer, 1, j, file);
- }
-
- fclose(file);
-
- if ( m_bAutoIndent )
- {
- m_dim.x = iDim; // presents the initial width
- Justif();
- }
-
- return true;
-}
-
-
-// Manage the number of max characters editable.
-
-void CEdit::SetMaxChar(int max)
-{
- m_maxChar = max;
- FreeImage();
- delete m_text;
- m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
-
- if ( m_format != 0 )
- {
- delete m_format;
- m_format = (char*)malloc(sizeof(char)*m_maxChar);
- }
-
- m_len = 0;
- m_cursor1 = 0;
- m_cursor2 = 0;
- Justif();
- UndoFlush();
-}
-
-int CEdit::RetMaxChar()
-{
- return m_maxChar;
-}
-
-
-// Mode management "editable".
-
-void CEdit::SetEditCap(bool bMode)
-{
- m_bEdit = bMode;
-}
-
-bool CEdit::RetEditCap()
-{
- return m_bEdit;
-}
-
-// Mode management "hilitable" (that's the franch).
-
-void CEdit::SetHiliteCap(bool bEnable)
-{
- m_bHilite = bEnable;
-}
-
-bool CEdit::RetHiliteCap()
-{
- return m_bHilite;
-}
-
-// Lift in / out connection.
-
-void CEdit::SetInsideScroll(bool bInside)
-{
- m_bInsideScroll = bInside;
-}
-
-bool CEdit::RetInsideScroll()
-{
- return m_bInsideScroll;
-}
-
-// Specifies whether to display the links showing the solution.
-
-void CEdit::SetSoluceMode(bool bSoluce)
-{
- m_bSoluce = bSoluce;
-}
-
-bool CEdit::RetSoluceMode()
-{
- return m_bSoluce;
-}
-
-// Indicates whether the text is a defile that generic.
-
-void CEdit::SetGenericMode(bool bGeneric)
-{
- m_bGeneric = bGeneric;
-}
-
-bool CEdit::RetGenericMode()
-{
- return m_bGeneric;
-}
-
-
-// Management of automatic indentation mode with {}.
-
-void CEdit::SetAutoIndent(bool bMode)
-{
- m_bAutoIndent = bMode;
-}
-
-bool CEdit::RetAutoIndent()
-{
- return m_bAutoIndent;
-}
-
-
-
-// Moves the cursors.
-
-void CEdit::SetCursor(int cursor1, int cursor2)
-{
- if ( cursor1 > m_len ) cursor1 = m_len;
- if ( cursor2 > m_len ) cursor2 = m_len;
-
- m_cursor1 = cursor1;
- m_cursor2 = cursor2;
- m_bUndoForce = true;
- ColumnFix();
-}
-
-// Returns the sliders.
-
-void CEdit::GetCursor(int &cursor1, int &cursor2)
-{
- cursor1 = m_cursor1;
- cursor2 = m_cursor2;
-}
-
-
-// Displayed line modifies the first.
-
-void CEdit::SetFirstLine(int rank)
-{
- Scroll(rank, true);
-}
-
-// Returns the first displayed line.
-
-int CEdit::RetFirstLine()
-{
- if ( m_historyTotal > 0 )
- {
- if ( m_historyCurrent == 0 )
- {
- return m_lineFirst;
- }
- else
- {
- return m_history[0].firstLine;
- }
- }
- return m_lineFirst;
-}
-
-
-// Shows the selected area.
-
-void CEdit::ShowSelect()
-{
- int cursor1, cursor2, line;
-
- if ( m_cursor1 < m_cursor2 )
- {
- cursor1 = m_cursor1;
- cursor2 = m_cursor2;
- }
- else
- {
- cursor1 = m_cursor2;
- cursor2 = m_cursor1;
- }
-
- line = RetCursorLine(cursor2);
- if ( line >= m_lineFirst+m_lineVisible )
- {
- line -= m_lineVisible-1;
- if ( line < 0 ) line = 0;
- Scroll(line, false);
- }
-
- line = RetCursorLine(cursor1);
- if ( line < m_lineFirst )
- {
- Scroll(line, false);
- }
-}
-
-
-// Management of the display mode of special characters.
-
-void CEdit::SetDisplaySpec(bool bDisplay)
-{
- m_bDisplaySpec = bDisplay;
-}
-
-bool CEdit::RetDisplaySpec()
-{
- return m_bDisplaySpec;
-}
-
-
-// Multi-fonts mode management.
-
-void CEdit::SetMultiFont(bool bMulti)
-{
- if ( bMulti )
- {
- delete m_format;
- m_format = (char*)malloc(sizeof(char)*m_maxChar);
- memset(m_format, 0, m_maxChar);
- }
- else
- {
- delete m_format;
- m_format = 0;
- }
-}
-
-bool CEdit::RetMultiFont()
-{
- return ( m_format != 0 );
-}
-
-
-// Management of the character size.
-
-void CEdit::SetFontSize(float size)
-{
- CControl::SetFontSize(size);
-
- MoveAdjust();
-}
-
-
-// Moves according to the visible lift.
-
-void CEdit::Scroll()
-{
- float value;
-
- if ( m_scroll != 0 )
- {
- value = m_scroll->RetVisibleValue();
- value *= m_lineTotal-m_lineVisible;
- Scroll((int)(value+0.5f), true);
- }
-}
-
-// Moves according to the visible lift.
-
-void CEdit::Scroll(int pos, bool bAdjustCursor)
-{
- int max, line;
-
- m_lineFirst = pos;
-
- if ( m_lineFirst < 0 ) m_lineFirst = 0;
-
- max = m_lineTotal-m_lineVisible;
- if ( max < 0 ) max = 0;
- if ( m_lineFirst > max ) m_lineFirst = max;
-
- line = RetCursorLine(m_cursor1);
-
- if ( bAdjustCursor && m_bEdit )
- {
- // Cursor too high?
- if ( line < m_lineFirst )
- {
- MoveLine(m_lineFirst-line, false, false);
- return;
- }
-
- // Cursor too low?
- if ( line >= m_lineFirst+m_lineVisible )
- {
- MoveLine(m_lineFirst+m_lineVisible-line-1, false, false);
- return;
- }
- }
-
- Justif();
-}
-
-// Moves the cursor to the beginning of the line.
-
-void CEdit::MoveHome(bool bWord, bool bSelect)
-{
- int begin, tab;
-
- if ( bWord )
- {
- m_cursor1 = 0;
- }
- else
- {
- begin = m_cursor1;
- while ( begin > 0 && m_text[begin-1] != '\n' )
- {
- begin --;
- }
-
- tab = begin;
- while ( tab < m_len && (m_text[tab] == '\t' || m_text[tab] == ' ') )
- {
- tab ++;
- }
-
- if ( m_cursor1 == tab )
- {
- m_cursor1 = begin;
- }
- else
- {
- m_cursor1 = tab;
- }
- }
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
-}
-
-// Moves the cursor to the end of the line.
-
-void CEdit::MoveEnd(bool bWord, bool bSelect)
-{
- if ( bWord )
- {
- m_cursor1 = m_len;
- }
- else
- {
- while ( m_cursor1 < m_len && m_text[m_cursor1] != '\n' )
- {
- m_cursor1 ++;
- }
- }
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
-}
-
-// Moves the cursor through characters.
-
-void CEdit::MoveChar(int move, bool bWord, bool bSelect)
-{
- int character;
-
- if ( move == -1 ) // back?
- {
- if ( bWord )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsSpace(character) ) break;
- m_cursor1 --;
- }
-
- if ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( IsSpace(character) )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsSpace(character) ) break;
- m_cursor1 --;
- }
- }
- else if ( IsWord(character) )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsWord(character) ) break;
- m_cursor1 --;
- }
- }
- else if ( IsSep(character) )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsSep(character) ) break;
- m_cursor1 --;
- }
- }
- }
- }
- else
- {
- m_cursor1 --;
- if ( m_cursor1 < 0 ) m_cursor1 = 0;
- }
- }
-
- if ( move == 1 ) // advance?
- {
- if ( bWord )
- {
- if ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( IsSpace(character) )
- {
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsSpace(character) ) break;
- m_cursor1 ++;
- }
- }
- else if ( IsWord(character) )
- {
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsWord(character) ) break;
- m_cursor1 ++;
- }
- }
- else if ( IsSep(character) )
- {
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsSep(character) ) break;
- m_cursor1 ++;
- }
- }
- }
-
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsSpace(character) ) break;
- m_cursor1 ++;
- }
- }
- else
- {
- m_cursor1 ++;
- if ( m_cursor1 > m_len ) m_cursor1 = m_len;
- }
- }
-
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
-}
-
-// Moves the cursor lines.
-
-void CEdit::MoveLine(int move, bool bWord, bool bSelect)
-{
- float column, indentLength;
- int i, line, c;
-
- if ( move == 0 ) return;
-
- for ( i=0 ; i>move ; i-- ) // back?
- {
- while ( m_cursor1 > 0 && m_text[m_cursor1-1] != '\n' )
- {
- m_cursor1 --;
- }
- if ( m_cursor1 != 0 )
- {
- m_cursor1 --;
- while ( m_cursor1 > 0 )
- {
- if ( m_text[--m_cursor1] == '\n' )
- {
- m_cursor1 ++;
- break;
- }
- }
- }
- }
-
- for ( i=0 ; i<move ; i++ ) // advance?
- {
- while ( m_cursor1 < m_len )
- {
- if ( m_text[m_cursor1++] == '\n' )
- {
- break;
- }
- }
- }
-
- line = RetCursorLine(m_cursor1);
-
- column = m_column;
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- column -= indentLength*m_lineIndent[line];
- }
-
- if ( m_format == 0 )
- {
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[line],
- m_lineOffset[line+1]-m_lineOffset[line],
- column, m_fontSize,
- m_fontStretch, m_fontType);
- }
- else
- {
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[line],
- m_format+m_lineOffset[line],
- m_lineOffset[line+1]-m_lineOffset[line],
- column, m_fontSize, m_fontStretch);
- }
-
- m_cursor1 = m_lineOffset[line]+c;
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
-}
-
-// Sets the horizontal position.
-
-void CEdit::ColumnFix()
-{
- float indentLength;
- int line;
-
- line = RetCursorLine(m_cursor1);
-
- if ( m_format == 0 )
- {
- m_column = m_engine->RetText()->RetStringWidth
- (
- m_text+m_lineOffset[line],
- m_cursor1-m_lineOffset[line],
- m_fontSize, m_fontStretch, m_fontType
- );
- }
- else
- {
- m_column = m_engine->RetText()->RetStringWidth
- (
- m_text+m_lineOffset[line],
- m_format+m_lineOffset[line],
- m_cursor1-m_lineOffset[line],
- m_fontSize, m_fontStretch
- );
- }
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- m_column += indentLength*m_lineIndent[line];
- }
-}
-
-
-// Cut the selected characters or entire line.
-
-bool CEdit::Cut()
-{
- HGLOBAL hg;
- char* text;
- char c;
- int c1, c2, start, len, i, j;
-
- if ( !m_bEdit ) return false;
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( c1 == c2 )
- {
- while ( c1 > 0 )
- {
- if ( m_text[c1-1] == '\n' ) break;
- c1 --;
- }
- while ( c2 < m_len )
- {
- c2 ++;
- if ( m_text[c2-1] == '\n' ) break;
- }
- }
-
- if ( c1 == c2 ) return false;
-
- start = c1;
- len = c2-c1;
-
- if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
- {
- return false;
- }
- if ( !(text = (char*)GlobalLock(hg)) )
- {
- GlobalFree(hg);
- return false;
- }
-
- j = 0;
- for ( i=start ; i<start+len ; i++ )
- {
- c = m_text[i];
- if ( c == '\n' ) text[j++] = '\r';
- text[j++] = c;
- }
- text[j] = 0;
- GlobalUnlock(hg);
-
- if ( !OpenClipboard(NULL) )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !EmptyClipboard() )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !SetClipboardData(CF_TEXT, hg) )
- {
- GlobalFree(hg);
- return false;
- }
- CloseClipboard();
-
- UndoMemorize(OPERUNDO_SPEC);
- m_cursor1 = c1;
- m_cursor2 = c2;
- DeleteOne(0); // deletes the selected characters
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-// Copy the selected characters or entire line.
-
-bool CEdit::Copy()
-{
- HGLOBAL hg;
- char* text;
- char c;
- int c1, c2, start, len, i, j;
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( c1 == c2 )
- {
- while ( c1 > 0 )
- {
- if ( m_text[c1-1] == '\n' ) break;
- c1 --;
- }
- while ( c2 < m_len )
- {
- c2 ++;
- if ( m_text[c2-1] == '\n' ) break;
- }
- }
-
- if ( c1 == c2 ) return false;
-
- start = c1;
- len = c2-c1;
-
- if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
- {
- return false;
- }
- if ( !(text = (char*)GlobalLock(hg)) )
- {
- GlobalFree(hg);
- return false;
- }
-
- j = 0;
- for ( i=start ; i<start+len ; i++ )
- {
- c = m_text[i];
- if ( c == '\n' ) text[j++] = '\r';
- text[j++] = c;
- }
- text[j] = 0;
- GlobalUnlock(hg);
-
- if ( !OpenClipboard(NULL) )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !EmptyClipboard() )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !SetClipboardData(CF_TEXT, hg) )
- {
- GlobalFree(hg);
- return false;
- }
- CloseClipboard();
-
- return true;
-}
-
-// Paste the contents of the notebook.
-
-bool CEdit::Paste()
-{
- HANDLE h;
- char c;
- char* p;
-
- if ( !m_bEdit ) return false;
-
- if ( !OpenClipboard(NULL) )
- {
- return false;
- }
-
- if ( !(h = GetClipboardData(CF_TEXT)) )
- {
- CloseClipboard();
- return false;
- }
-
- if ( !(p = (char*)GlobalLock(h)) )
- {
- CloseClipboard();
- return false;
- }
-
- UndoMemorize(OPERUNDO_SPEC);
-
- while ( *p != 0 )
- {
- c = *p++;
- if ( c == '\r' ) continue;
- if ( c == '\t' && m_bAutoIndent ) continue;
- InsertOne(c);
- }
-
- GlobalUnlock(h);
- CloseClipboard();
-
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-
-// Cancels the last action.
-
-bool CEdit::Undo()
-{
- if ( !m_bEdit ) return false;
-
- return UndoRecall();
-}
-
-
-// Inserts a character.
-
-void CEdit::Insert(char character)
-{
- int i, level, tab;
-
- if ( !m_bEdit ) return;
-
- if ( !m_bMulti ) // single-line?
- {
- if ( character == '\n' ||
- character == '\t' ) return;
- }
-
- UndoMemorize(OPERUNDO_INSERT);
-
- if ( m_bMulti && !m_bAutoIndent )
- {
- if ( character == '\n' )
- {
- InsertOne(character);
- level = IndentCompute();
- for ( i=0 ; i<level ; i++ )
- {
- InsertOne('\t');
- }
- }
- else if ( character == '{' )
- {
- tab = IndentTabCount();
- if ( tab != -1 )
- {
- level = IndentCompute();
- IndentTabAdjust(level-tab);
- }
- InsertOne(character);
- }
- else if ( character == '}' )
- {
- tab = IndentTabCount();
- if ( tab != -1 )
- {
- level = IndentCompute()-1;
- IndentTabAdjust(level-tab);
- }
- InsertOne(character);
- }
- else
- {
- InsertOne(character);
- }
- }
- else if ( m_bAutoIndent )
- {
- if ( character == '{' )
- {
- InsertOne(character);
- InsertOne('\n');
- InsertOne('\n');
- InsertOne('}');
- MoveChar(-1, false, false);
- MoveChar(-1, false, false);
- }
-#if 0
- else if ( character == '(' )
- {
- InsertOne(character);
- InsertOne(')');
- MoveChar(-1, false, false);
- }
- else if ( character == '[' )
- {
- InsertOne(character);
- InsertOne(']');
- MoveChar(-1, false, false);
- }
-#endif
- else if ( character == '\t' )
- {
- for ( i=0 ; i<m_engine->RetEditIndentValue() ; i++ )
- {
- InsertOne(' ');
- }
- }
- else
- {
- InsertOne(character);
- }
- }
- else
- {
- InsertOne(character);
- }
-
- Justif();
- ColumnFix();
-}
-
-// Inserts a plain character.
-
-void CEdit::InsertOne(char character)
-{
- int i;
-
- if ( !m_bEdit ) return;
- if ( !m_bMulti && character == '\n' ) return;
-
- if ( m_cursor1 != m_cursor2 )
- {
- DeleteOne(0); // deletes the selected characters
- }
-
- if ( m_len >= m_maxChar ) return;
-
- for ( i=m_len ; i>=m_cursor1 ; i-- )
- {
- m_text[i] = m_text[i-1]; // shoot
-
- if ( m_format != 0 )
- {
- m_format[i] = m_format[i-1]; // shoot
- }
- }
-
- m_len ++;
-
- m_text[m_cursor1] = character;
-
- if ( m_format != 0 )
- {
- m_format[m_cursor1] = 0;
- }
-
- m_cursor1++;
- m_cursor2 = m_cursor1;
-}
-
-// Deletes the character left of cursor or all selected characters.
-
-void CEdit::Delete(int dir)
-{
- if ( !m_bEdit ) return;
-
- UndoMemorize(OPERUNDO_DELETE);
- DeleteOne(dir);
-
- Justif();
- ColumnFix();
-}
-
-// Deletes the character left of cursor or all selected plain characters.
-
-void CEdit::DeleteOne(int dir)
-{
- int i, end, hole;
-
- if ( !m_bEdit ) return;
-
- if ( m_cursor1 == m_cursor2 )
- {
- if ( dir < 0 )
- {
- if ( m_cursor1 == 0 ) return;
- m_cursor1 --;
- }
- else
- {
- if ( m_cursor2 == m_len ) return;
- m_cursor2 ++;
- }
- }
-
- if ( m_cursor1 > m_cursor2 ) Math::Swap(m_cursor1, m_cursor2);
- hole = m_cursor2-m_cursor1;
- end = m_len-hole;
- for ( i=m_cursor1 ; i<end ; i++ )
- {
- m_text[i] = m_text[i+hole];
-
- if ( m_format != 0 )
- {
- m_format[i] = m_format[i+hole];
- }
- }
- m_len -= hole;
- m_cursor2 = m_cursor1;
-}
-
-
-// Calculates the indentation level of brackets {and}.
-
-int CEdit::IndentCompute()
-{
- int i, level;
-
- level = 0;
- for ( i=0 ; i<m_cursor1 ; i++ )
- {
- if ( m_text[i] == '{' ) level ++;
- if ( m_text[i] == '}' ) level --;
- }
-
- if ( level < 0 ) level = 0;
- return level;
-}
-
-// Counts the number of tabs before the cursor.
-// Returns -1 if there is something else.
-
-int CEdit::IndentTabCount()
-{
- int i, nb;
-
- if ( m_cursor1 != m_cursor2 ) return -1;
-
- i = m_cursor1;
- nb = 0;
- while ( i > 0 )
- {
- if ( m_text[i-1] == '\n' ) return nb;
- if ( m_text[i-1] != '\t' ) return -1;
- nb ++;
- i --;
- }
- return nb;
-}
-
-// Adds or removes qq tabs.
-
-void CEdit::IndentTabAdjust(int number)
-{
- int i;
-
- for ( i=0 ; i<number ; i++ ) // add?
- {
- InsertOne('\t');
- }
-
- for ( i=0 ; i>number ; i-- ) // delete?
- {
- DeleteOne(-1);
- }
-}
-
-
-// Indent the left or right the entire selection.
-
-bool CEdit::Shift(bool bLeft)
-{
- bool bInvert = false;
- int c1, c2, i;
-
- if ( m_cursor1 == m_cursor2 ) return false;
-
- UndoMemorize(OPERUNDO_SPEC);
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 )
- {
- Math::Swap(c1, c2); // always c1 <= c2
- bInvert = true;
- }
-
- if ( c1 > 0 )
- {
- if ( m_text[c1-1] != '\n' ) return false;
- }
- if ( c2 < m_len )
- {
- if ( m_text[c2-1] != '\n' ) return false;
- }
-
- if ( bLeft ) // shifts left?
- {
- i = c1;
- while ( i < c2 )
- {
- if ( m_text[i] == '\t' )
- {
- m_cursor1 = i;
- m_cursor2 = i+1;
- DeleteOne(0);
- c2 --;
- }
- while ( i < c2 && m_text[i++] != '\n' );
- }
- }
- else // shifts right?
- {
- i = c1;
- while ( i < c2 )
- {
- m_cursor1 = m_cursor2 = i;
- InsertOne('\t');
- c2 ++;
- while ( i < c2 && m_text[i++] != '\n' );
- }
- }
-
- if ( bInvert ) Math::Swap(c1, c2);
- m_cursor1 = c1;
- m_cursor2 = c2;
-
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-// Math::Min conversion <-> shift the selection.
-
-bool CEdit::MinMaj(bool bMaj)
-{
- int c1, c2, i, character;
-
- if ( m_cursor1 == m_cursor2 ) return false;
-
- UndoMemorize(OPERUNDO_SPEC);
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // alwyas c1 <= c2
-
- for ( i=c1 ; i<c2 ; i++ )
- {
- character = (unsigned char)m_text[i];
- if ( bMaj ) character = RetToUpper(character);
- else character = RetToLower(character);
- m_text[i] = character;
- }
-
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-
-// Cut all text lines.
-
-void CEdit::Justif()
-{
- float width, value, size, indentLength;
- int i, j, line, indent;
- bool bDual, bString, bRem;
-
- indent = 0;
- m_lineTotal = 0;
- m_lineOffset[m_lineTotal] = 0;
- m_lineIndent[m_lineTotal] = indent;
- m_lineTotal ++;
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- }
-
- bString = bRem = false;
- i = 0;
- while ( true )
- {
- bDual = false;
-
- width = m_dim.x-(10.0f/640.0f)*2.0f-(m_bMulti?MARGX*2.0f+SCROLL_WIDTH:0.0f);
- if ( m_bAutoIndent )
- {
- width -= indentLength*m_lineIndent[m_lineTotal-1];
- }
-
- if ( m_format == 0 )
- {
- i += m_engine->RetText()->Justif(m_text+i, m_len-i, width,
- m_fontSize, m_fontStretch,
- m_fontType);
- }
- else
- {
- size = m_fontSize;
-
- if ( (m_format[i]&TITLE_MASK) == TITLE_BIG ) // headline?
- {
- size *= BIG_FONT;
- bDual = true;
- }
-
- if ( (m_format[i]&IMAGE_MASK) != 0 ) // image part?
- {
- i ++; // jumps just a character (index in m_image)
- }
- else
- {
- i += m_engine->RetText()->Justif(m_text+i, m_format+i,
- m_len-i, width,
- size, m_fontStretch);
- }
- }
-
- if ( i >= m_len ) break;
-
- if ( m_bAutoIndent )
- {
- for ( j=m_lineOffset[m_lineTotal-1] ; j<i ; j++ )
- {
- if ( !bRem && m_text[j] == '\"' ) bString = !bString;
- if ( !bString &&
- m_text[j] == '/' &&
- m_text[j+1] == '/' ) bRem = true;
- if ( m_text[j] == '\n' ) bString = bRem = false;
- if ( m_text[j] == '{' && !bString && !bRem ) indent ++;
- if ( m_text[j] == '}' && !bString && !bRem ) indent --;
- }
- if ( indent < 0 ) indent = 0;
- }
-
- m_lineOffset[m_lineTotal] = i;
- m_lineIndent[m_lineTotal] = indent;
- m_lineTotal ++;
- if ( bDual )
- {
- m_lineOffset[m_lineTotal] = i;
- m_lineIndent[m_lineTotal] = indent;
- m_lineTotal ++;
- }
- if ( m_lineTotal >= EDITLINEMAX-2 ) break;
- }
- if ( m_len > 0 && m_text[m_len-1] == '\n' )
- {
- m_lineOffset[m_lineTotal] = m_len;
- m_lineIndent[m_lineTotal] = 0;
- m_lineTotal ++;
- }
- m_lineOffset[m_lineTotal] = m_len;
- m_lineIndent[m_lineTotal] = 0;
-
- if ( m_bAutoIndent )
- {
- for ( i=0 ; i<=m_lineTotal ; i++ )
- {
- if ( m_text[m_lineOffset[i]] == '}' )
- {
- if ( m_lineIndent[i] > 0 ) m_lineIndent[i] --;
- }
- }
- }
-
- if ( m_bMulti )
- {
- if ( m_bEdit )
- {
- line = RetCursorLine(m_cursor1);
- if ( line < m_lineFirst )
- {
- m_lineFirst = line;
- }
- if ( line >= m_lineFirst+m_lineVisible )
- {
- m_lineFirst = line-m_lineVisible+1;
- }
- }
- }
- else
- {
- m_lineFirst = 0;
- }
-
- if ( m_scroll != 0 )
- {
- if ( m_lineTotal <= m_lineVisible )
- {
- m_scroll->SetVisibleRatio(1.0f);
- m_scroll->SetVisibleValue(0.0f);
- m_scroll->SetArrowStep(0.0f);
- }
- else
- {
- value = (float)m_lineVisible/m_lineTotal;
- m_scroll->SetVisibleRatio(value);
-
- value = (float)m_lineFirst/(m_lineTotal-m_lineVisible);
- m_scroll->SetVisibleValue(value);
-
- value = (float)1.0f/(m_lineTotal-m_lineVisible);
- m_scroll->SetArrowStep(value);
- }
- }
-
- m_timeBlink = 0.0f; // lights the cursor immediately
-}
-
-// Returns the rank of the line where the cursor is located.
-
-int CEdit::RetCursorLine(int cursor)
-{
- int line, i;
-
- line = 0;
- for ( i=0 ; i<m_lineTotal ; i++ )
- {
- if ( cursor >= m_lineOffset[i] )
- {
- line = i;
- }
- }
- return line;
-}
-
-
-// Flush the buffer undo.
-
-void CEdit::UndoFlush()
-{
- int i;
-
- for ( i=0 ; i<EDITUNDOMAX ; i++ )
- {
- delete m_undo[i].text;
- m_undo[i].text = 0;
- }
-
- m_bUndoForce = true;
- m_undoOper = OPERUNDO_SPEC;
-}
-
-// Memorize the current state before a change.
-
-void CEdit::UndoMemorize(OperUndo oper)
-{
- int i, len;
-
- if ( !m_bUndoForce &&
- oper != OPERUNDO_SPEC &&
- m_undoOper != OPERUNDO_SPEC &&
- oper == m_undoOper ) return;
-
- m_bUndoForce = false;
- m_undoOper = oper;
-
- delete m_undo[EDITUNDOMAX-1].text;
-
- for ( i=EDITUNDOMAX-1 ; i>=1 ; i-- )
- {
- m_undo[i] = m_undo[i-1];
- }
-
- len = m_len;
- if ( len == 0 ) len ++;
- m_undo[0].text = (char*)malloc(sizeof(char)*(len+1));
- memcpy(m_undo[0].text, m_text, m_len);
- m_undo[0].len = m_len;
-
- m_undo[0].cursor1 = m_cursor1;
- m_undo[0].cursor2 = m_cursor2;
- m_undo[0].lineFirst = m_lineFirst;
-}
-
-// Back to previous state.
-
-bool CEdit::UndoRecall()
-{
- int i;
-
- if ( m_undo[0].text == 0 ) return false;
-
- m_len = m_undo[0].len;
- memcpy(m_text, m_undo[0].text, m_len);
-
- m_cursor1 = m_undo[0].cursor1;
- m_cursor2 = m_undo[0].cursor2;
- m_lineFirst = m_undo[0].lineFirst;
-
- for ( i=0 ; i<EDITUNDOMAX-1 ; i++ )
- {
- m_undo[i] = m_undo[i+1];
- }
- m_undo[EDITUNDOMAX-1].text = 0;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-
-// Clears the format of all characters.
-
-bool CEdit::ClearFormat()
-{
- if ( m_format == 0 )
- {
- SetMultiFont(true);
- }
- memset(m_format, m_fontType, m_len);
-
- return true;
-}
-
-// Changes the format of a sequence of characters.
-
-bool CEdit::SetFormat(int cursor1, int cursor2, int format)
-{
- int i;
-
- if ( m_format == 0 ) return false;
-
- for ( i=cursor1 ; i<cursor2 ; i++ )
- {
- m_format[i] |= format;
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// edit.cpp + + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <windows.h> +#include <d3d.h> + +#include "common/struct.h" +#include "old/d3dengine.h" +#include "common/language.h" +#include "old/math3d.h" +#include "common/event.h" +#include "common/misc.h" +#include "common/iman.h" +#include "common/restext.h" +#include "ui/scroll.h" +#include "old/text.h" +#include "ui/edit.h" + + +const float MARGX = (5.0f/640.0f); +const float MARGY = (5.0f/480.0f); +const float MARGYS = (4.0f/480.0f); +const float MARGY1 = (1.0f/480.0f); +const float DELAY_DBCLICK = 0.3f; // time limit for double-click +const float DELAY_SCROLL = 0.1f; // time limit for scroll +const float BIG_FONT = 1.6f; // expansion for \b; + + + + +// Indicates whether a character is a space. + +bool IsSpace(int character) +{ + return ( character == ' ' || + character == '\t' || + character == '\n' ); +} + +// Indicates whether a character is part of a word. + +bool IsWord(int character) +{ + char c; + + c = tolower(RetNoAccent(character)); + + return ( (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '_' ); +} + +// Indicates whether a character is a word separator. + +bool IsSep(int character) +{ + if ( IsSpace(character) ) return false; + return !IsWord(character); +} + + + +// Object's constructor. + +CEdit::CEdit(CInstanceManager* iMan) : CControl(iMan) +{ + Math::Point pos; + int i; + + m_maxChar = 100; + m_text = (char*)malloc(sizeof(char)*(m_maxChar+1)); + m_format = 0; + m_len = 0; + + m_fontType = FONT_COURIER; + m_scroll = 0; + m_bEdit = true; + m_bHilite = true; + m_bInsideScroll = true; + m_bCapture = false; + m_bDisplaySpec = false; + m_bSoluce = false; + m_bGeneric = false; + m_bAutoIndent = false; + m_cursor1 = 0; + m_cursor2 = 0; + m_column = 0; + m_imageTotal = 0; + + HyperFlush(); + + for ( i=0 ; i<EDITUNDOMAX ; i++ ) + { + m_undo[i].text = 0; + } + m_bUndoForce = true; + m_undoOper = OPERUNDO_SPEC; +} + +// Object's destructor. + +CEdit::~CEdit() +{ + int i; + + FreeImage(); + + for ( i=0 ; i<EDITUNDOMAX ; i++ ) + { + delete m_undo[i].text; + } + + delete m_text; + delete m_format; + delete m_scroll; +} + + +// Creates a new editable line. + +bool CEdit::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg) +{ + CScroll* pc; + Math::Point start, end; + + if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg(); + CControl::Create(pos, dim, icon, eventMsg); + + m_len = 0; + m_lineFirst = 0; + m_time = 0.0f; + m_timeBlink = 0.0f; + m_timeLastClick = 0.0f; + m_timeLastScroll = 0.0f; + + m_bMulti = false; + MoveAdjust(); + if ( m_lineVisible <= 1 ) + { + m_bMulti = false; + } + else + { + m_bMulti = true; + MoveAdjust(); // readjusts multi-line mode + m_scroll = new CScroll(m_iMan); + pc = (CScroll*)m_scroll; + pc->Create(pos, dim, -1, EVENT_NULL); + MoveAdjust(); + } + + return true; +} + + +void CEdit::SetPos(Math::Point pos) +{ + CControl::SetPos(pos); + MoveAdjust(); +} + +void CEdit::SetDim(Math::Point dim) +{ + CControl::SetDim(dim); + MoveAdjust(); +} + +void CEdit::MoveAdjust() +{ + Math::Point pos, dim; + float height; + + m_lineDescent = m_engine->RetText()->RetDescent(m_fontSize, m_fontType); + m_lineAscent = m_engine->RetText()->RetAscent(m_fontSize, m_fontType); + m_lineHeight = m_engine->RetText()->RetHeight(m_fontSize, m_fontType); + + height = m_dim.y-(m_bMulti?MARGY*2.0f:MARGY1); + m_lineVisible = (int)(height/m_lineHeight); + + if ( m_scroll != 0 ) + { + if ( m_bInsideScroll ) + { + pos.x = m_pos.x+m_dim.x-MARGX-SCROLL_WIDTH; + pos.y = m_pos.y+MARGYS; + dim.x = SCROLL_WIDTH; + dim.y = m_dim.y-MARGYS*2.0f; + } + else + { + pos.x = m_pos.x+m_dim.x-SCROLL_WIDTH; + pos.y = m_pos.y; + dim.x = SCROLL_WIDTH; + dim.y = m_dim.y; + } + m_scroll->SetPos(pos); + m_scroll->SetDim(dim); + } + + Justif(); + + if ( m_lineFirst > m_lineTotal-m_lineVisible ) + { + m_lineFirst = m_lineTotal-m_lineVisible; + if ( m_lineFirst < 0 ) m_lineFirst = 0; + } + + pos.x = m_pos.x+m_dim.x-(m_bMulti?SCROLL_WIDTH:0.0f); + pos.y = m_pos.y; + GlintCreate(pos, false, false); +} + + +// Management of an event. + +bool CEdit::EventProcess(const Event &event) +{ + bool bShift, bControl; + + if ( (m_state & STATE_VISIBLE) == 0 ) return true; + + if ( event.event == EVENT_KEYDOWN && + event.param == VK_WHEELUP && + Detect(event.pos) ) + { + Scroll(m_lineFirst-3, true); + return true; + } + if ( event.event == EVENT_KEYDOWN && + event.param == VK_WHEELDOWN && + Detect(event.pos) ) + { + Scroll(m_lineFirst+3, true); + return true; + } + + CControl::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + m_time += event.rTime; + m_timeBlink += event.rTime; + } + + if ( event.event == EVENT_MOUSEMOVE ) + { + if ( Detect(event.pos) && + event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) ) + { + if ( m_bEdit ) + { + m_engine->SetMouseType(D3DMOUSEEDIT); + } + else + { + if ( IsLinkPos(event.pos) ) + { + m_engine->SetMouseType(D3DMOUSEHAND); + } + else + { + m_engine->SetMouseType(D3DMOUSENORM); + } + } + } + } + + if ( m_scroll != 0 && !m_bGeneric ) + { + m_scroll->EventProcess(event); + + if ( event.event == m_scroll->RetEventMsg() ) + { + Scroll(); + return true; + } + } + + if ( event.event == EVENT_KEYDOWN && m_bFocus ) + { + bShift = (event.keyState&KS_SHIFT); + bControl = (event.keyState&KS_CONTROL); + + if ( (event.param == 'X' && !bShift && bControl) || + (event.param == VK_DELETE && bShift && !bControl) ) + { + Cut(); + return true; + } + if ( (event.param == 'C' && !bShift && bControl) || + (event.param == VK_INSERT && !bShift && bControl) ) + { + Copy(); + return true; + } + if ( (event.param == 'V' && !bShift && bControl) || + (event.param == VK_INSERT && bShift && !bControl) ) + { + Paste(); + return true; + } + + if ( event.param == 'A' && !bShift && bControl ) + { + SetCursor(999999, 0); + return true; + } + + if ( event.param == 'O' && !bShift && bControl ) + { + Event newEvent; + m_event->MakeEvent(newEvent, EVENT_STUDIO_OPEN); + m_event->AddEvent(newEvent); + } + if ( event.param == 'S' && !bShift && bControl ) + { + Event newEvent; + m_event->MakeEvent(newEvent, EVENT_STUDIO_SAVE); + m_event->AddEvent(newEvent); + } + + if ( event.param == 'Z' && !bShift && bControl ) + { + Undo(); + return true; + } + + if ( event.param == 'U' && !bShift && bControl ) + { + if ( MinMaj(false) ) return true; + } + if ( event.param == 'U' && bShift && bControl ) + { + if ( MinMaj(true) ) return true; + } + + if ( event.param == VK_TAB && !bShift && !bControl && !m_bAutoIndent ) + { + if ( Shift(false) ) return true; + } + if ( event.param == VK_TAB && bShift && !bControl && !m_bAutoIndent ) + { + if ( Shift(true) ) return true; + } + + if ( m_bEdit ) + { + if ( event.param == VK_LEFT ) + { + MoveChar(-1, bControl, bShift); + return true; + } + if ( event.param == VK_RIGHT ) + { + MoveChar(1, bControl, bShift); + return true; + } + if ( event.param == VK_UP ) + { + MoveLine(-1, bControl, bShift); + return true; + } + if ( event.param == VK_DOWN ) + { + MoveLine(1, bControl, bShift); + return true; + } + + if ( event.param == VK_PRIOR ) // PageUp ? + { + MoveLine(-(m_lineVisible-1), bControl, bShift); + return true; + } + if ( event.param == VK_NEXT ) // PageDown ? + { + MoveLine(m_lineVisible-1, bControl, bShift); + return true; + } + } + else + { + if ( event.param == VK_LEFT || + event.param == VK_UP ) + { + Scroll(m_lineFirst-1, true); + return true; + } + if ( event.param == VK_RIGHT || + event.param == VK_DOWN ) + { + Scroll(m_lineFirst+1, true); + return true; + } + + if ( event.param == VK_PRIOR ) // PageUp ? + { + Scroll(m_lineFirst-(m_lineVisible-1), true); + return true; + } + if ( event.param == VK_NEXT ) // PageDown ? + { + Scroll(m_lineFirst+(m_lineVisible-1), true); + return true; + } + } + + if ( event.param == VK_HOME ) + { + MoveHome(bControl, bShift); + return true; + } + if ( event.param == VK_END ) + { + MoveEnd(bControl, bShift); + return true; + } + + if ( event.param == VK_BACK ) // backspace ( <- ) ? + { + Delete(-1); + SendModifEvent(); + return true; + } + if ( event.param == VK_DELETE ) + { + Delete(1); + SendModifEvent(); + return true; + } + + if ( event.param == VK_RETURN ) + { + Insert('\n'); + SendModifEvent(); + return true; + } + if ( event.param == VK_TAB ) + { + Insert('\t'); + SendModifEvent(); + return true; + } + } + + if ( event.event == EVENT_CHAR && m_bFocus ) + { + if ( event.param >= ' ' && event.param <= 255 ) + { + Insert((char)event.param); + SendModifEvent(); + return true; + } + } + + if ( event.event == EVENT_FOCUS ) + { + if ( event.param == m_eventMsg ) + { + m_bFocus = true; + } + else + { + m_bFocus = false; + } + } + + if ( event.event == EVENT_LBUTTONDOWN ) + { + m_mouseFirstPos = event.pos; + m_mouseLastPos = event.pos; + if ( Detect(event.pos) ) + { + if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) ) + { + MouseClick(event.pos); + if ( m_bEdit || m_bHilite ) m_bCapture = true; + } + m_bFocus = true; + } + else + { + m_bFocus = false; + } + } + + if ( event.event == EVENT_MOUSEMOVE && m_bCapture ) + { + m_mouseLastPos = event.pos; + MouseMove(event.pos); + } + + if ( event.event == EVENT_FRAME && m_bCapture ) + { + MouseMove(m_mouseLastPos); + } + + if ( event.event == EVENT_LBUTTONUP ) + { + if ( Detect(event.pos) ) + { + if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) ) + { + MouseRelease(m_mouseFirstPos); + } + } + if ( m_bCapture ) + { + if ( m_timeLastClick+DELAY_DBCLICK > m_time ) // double-click ? + { + MouseDoubleClick(event.pos); + } + m_timeLastClick = m_time; + m_bCapture = false; + } + } + + return true; +} + + +// Sends an event to indicate that the text was modified. + +void CEdit::SendModifEvent() +{ + Event newEvent; + + m_event->MakeEvent(newEvent, m_eventMsg); + m_event->AddEvent(newEvent); +} + + +// Detects whether the mouse is over a hyperlink character. + +bool CEdit::IsLinkPos(Math::Point pos) +{ + int i; + + if ( m_format == 0 ) return false; + + i = MouseDetect(pos); + if ( i == -1 ) return false; + if ( i >= m_len ) return false; + + if ( (m_format[i]&COLOR_MASK) == COLOR_LINK ) return true; + return false; +} + + +// Positions the cursor after a double click. + +void CEdit::MouseDoubleClick(Math::Point mouse) +{ + int i, character; + + if ( m_bMulti ) // Multi-line? + { + i = MouseDetect(mouse); + if ( i == -1 ) return; + + while ( i > 0 ) + { + character = (unsigned char)m_text[i-1]; + if ( !IsWord(character) ) break; + i --; + } + m_cursor2 = i; + + while ( i < m_len ) + { + character = (unsigned char)m_text[i]; + if ( !IsWord(character) ) break; + i ++; + } + m_cursor1 = i; + } + else // single-line? + { + m_cursor2 = 0; + m_cursor1 = m_len; // selects all + } + + m_bUndoForce = true; + + Justif(); + ColumnFix(); +} + +// Positions the cursor when clicked. + +void CEdit::MouseClick(Math::Point mouse) +{ + int i; + + i = MouseDetect(mouse); + if ( i == -1 ) return; + + if ( m_bEdit || m_bHilite ) + { + m_cursor1 = i; + m_cursor2 = i; + m_bUndoForce = true; + m_timeBlink = 0.0f; // lights the cursor immediately + ColumnFix(); + } +} + +// Positions the cursor when clicked released. + +void CEdit::MouseRelease(Math::Point mouse) +{ + int i, j, rank; + + i = MouseDetect(mouse); + if ( i == -1 ) return; + + if ( !m_bEdit ) + { + if ( m_format != 0 && i < m_len && m_cursor1 == m_cursor2 && + (m_format[i]&COLOR_MASK) == COLOR_LINK ) + { + rank = -1; + for ( j=0 ; j<=i ; j++ ) + { + if ( (j == 0 || (m_format[j-1]&COLOR_MASK) != COLOR_LINK) && + (m_format[j+0]&COLOR_MASK) == COLOR_LINK ) + { + rank ++; + } + } + HyperJump(m_link[rank].name, m_link[rank].marker); + } + } +} + +// Positions the cursor after movement. + +void CEdit::MouseMove(Math::Point mouse) +{ + int i; + + if ( m_bMulti && + m_timeLastScroll+DELAY_SCROLL <= m_time ) + { + if ( mouse.y > m_pos.y+m_dim.y ) // above? + { + Scroll(m_lineFirst-1, false); + mouse.y = m_pos.y+m_dim.y-MARGY-m_lineHeight/2.0f; + } + if ( mouse.y < m_pos.y ) // lower? + { + Scroll(m_lineFirst+1, false); + mouse.y = m_pos.y+m_dim.y-MARGY-m_lineVisible*m_lineHeight+m_lineHeight/2.0f; + } + m_timeLastScroll = m_time; + } + + i = MouseDetect(mouse); + if ( i != -1 ) + { + m_cursor1 = i; + m_bUndoForce = true; + m_timeBlink = 0.0f; // lights the cursor immediately + ColumnFix(); + } +} + +// Positions the cursor when clicked. + +int CEdit::MouseDetect(Math::Point mouse) +{ + Math::Point pos; + float indentLength, offset, size; + int i, len, c; + bool bTitle; + + if ( m_bAutoIndent ) + { + indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType) + * m_engine->RetEditIndentValue(); + } + + pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1); + for ( i=m_lineFirst ; i<m_lineTotal ; i++ ) + { + bTitle = ( m_format != 0 && (m_format[m_lineOffset[i]]&TITLE_MASK) == TITLE_BIG ); + + if ( i >= m_lineFirst+m_lineVisible ) break; + + pos.x = m_pos.x+(10.0f/640.0f); + if ( m_bAutoIndent ) + { + pos.x += indentLength*m_lineIndent[i]; + } + offset = mouse.x-pos.x; + + if ( bTitle ) pos.y -= m_lineHeight; + + if ( mouse.y > pos.y ) + { + len = m_lineOffset[i+1] - m_lineOffset[i]; + + if ( m_format == 0 ) + { + c = m_engine->RetText()->Detect(m_text+m_lineOffset[i], + len, offset, m_fontSize, + m_fontStretch, m_fontType); + } + else + { + size = m_fontSize; + if ( bTitle ) size *= BIG_FONT; + + c = m_engine->RetText()->Detect(m_text+m_lineOffset[i], + m_format+m_lineOffset[i], + len, offset, size, + m_fontStretch); + } + return m_lineOffset[i]+c; + } + + if ( bTitle ) i ++; + pos.y -= m_lineHeight; + } + return -1; +} + + +// Clears all history. + +void CEdit::HyperFlush() +{ + m_historyTotal = 0; + m_historyCurrent = -1; +} + +// Indicates which is the home page. + +void CEdit::HyperHome(char *filename) +{ + HyperFlush(); + HyperAdd(filename, 0); +} + +// Performs a hyper jump through a link. + +void CEdit::HyperJump(char *name, char *marker) +{ + char filename[100]; + char sMarker[100]; + int i, line, pos; + + if ( m_historyCurrent >= 0 ) + { + m_history[m_historyCurrent].firstLine = m_lineFirst; + } + + strcpy(sMarker, marker); + +//? sprintf(filename, "help\\%s.txt", name); + if ( name[0] == '%' ) + { + UserDir(filename, name, ""); + strcat(filename, ".txt"); + } + else + { + sprintf(filename, "help\\%s.txt", name); + } + if ( ReadText(filename) ) + { + Justif(); + + line = 0; + for ( i=0 ; i<m_markerTotal ; i++ ) + { + if ( strcmp(sMarker, m_marker[i].name) == 0 ) + { + pos = m_marker[i].pos; + for ( i=0 ; i<m_lineTotal ; i++ ) + { + if ( pos >= m_lineOffset[i] ) + { + line = i; + } + } + break; + } + } + + SetFirstLine(line); + HyperAdd(filename, line); + } +} + +// Adds text to the history of visited. + +bool CEdit::HyperAdd(char *filename, int firstLine) +{ + if ( m_historyCurrent >= EDITHISTORYMAX-1 ) return false; + + m_historyCurrent ++; + strcpy(m_history[m_historyCurrent].filename, filename); + m_history[m_historyCurrent].firstLine = firstLine; + + m_historyTotal = m_historyCurrent+1; + return true; +} + +// Indicates whether a button EVENT_HYPER_ * is active or not. + +bool CEdit::HyperTest(EventMsg event) +{ + if ( event == EVENT_HYPER_HOME ) + { + return ( m_historyCurrent > 0 ); + } + + if ( event == EVENT_HYPER_PREV ) + { + return ( m_historyCurrent > 0 ); + } + + if ( event == EVENT_HYPER_NEXT ) + { + return ( m_historyCurrent < m_historyTotal-1 ); + } + + return false; +} + +// Performs the action corresponding to a button EVENT_HYPER_ *. + +bool CEdit::HyperGo(EventMsg event) +{ + if ( !HyperTest(event) ) return false; + + m_history[m_historyCurrent].firstLine = m_lineFirst; + + if ( event == EVENT_HYPER_HOME ) + { + m_historyCurrent = 0; + } + + if ( event == EVENT_HYPER_PREV ) + { + m_historyCurrent --; + } + + if ( event == EVENT_HYPER_NEXT ) + { + m_historyCurrent ++; + } + + ReadText(m_history[m_historyCurrent].filename); + Justif(); + SetFirstLine(m_history[m_historyCurrent].firstLine); + return true; +} + + +// Draw the editable line. + +void CEdit::Draw() +{ + Math::Point pos, ppos, dim, start, end; + float size, indentLength; + int i, j, beg, len, c1, c2, o1, o2, eol, iIndex, line; + + if ( (m_state & STATE_VISIBLE) == 0 ) return; + + if ( m_state & STATE_SHADOW ) + { + DrawShadow(m_pos, m_dim); + } + + pos.x = m_pos.x; + pos.y = m_pos.y; + dim.x = m_dim.x; + if ( !m_bInsideScroll ) dim.x -= m_bMulti?SCROLL_WIDTH:0.0f; + dim.y = m_dim.y; + DrawBack(pos, dim); // background + + // Displays all lines. + c1 = m_cursor1; + c2 = m_cursor2; + if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2 + + if ( m_bInsideScroll ) + { + dim.x -= m_bMulti?SCROLL_WIDTH:0.0f + (1.0f/640.0f); + } + + if ( m_bAutoIndent ) + { + indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType) + * m_engine->RetEditIndentValue(); + } + + pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1); + for ( i=m_lineFirst ; i<m_lineTotal ; i++ ) + { + if ( i == m_lineFirst && i < m_lineTotal-1 && + m_lineOffset[i] == m_lineOffset[i+1] ) + { + pos.y -= m_lineHeight; // Double jump line \b; + i ++; + } + + if ( i >= m_lineFirst+m_lineVisible ) break; + + pos.x = m_pos.x+(10.0f/640.0f); + if ( m_bAutoIndent ) + { + for ( j=0 ; j<m_lineIndent[i] ; j++ ) + { + char s = '\t'; // line | dotted + m_engine->RetText()->DrawText(&s, 1, pos, 1.0f, 1, m_fontSize, m_fontStretch, m_fontType, 0); + pos.x += indentLength; + } + } + + beg = m_lineOffset[i]; + len = m_lineOffset[i+1] - m_lineOffset[i]; + + ppos = pos; + size = m_fontSize; + + // Headline \b;? + if ( beg+len < m_len && m_format != 0 && + (m_format[beg]&TITLE_MASK) == TITLE_BIG ) + { + start.x = ppos.x-MARGX; + end.x = dim.x-MARGX*2.0f; + start.y = ppos.y-(m_bMulti?0.0f:MARGY1)-m_lineHeight*(BIG_FONT-1.0f); + end.y = m_lineHeight*BIG_FONT; + DrawPart(start, end, 2); // blue gradient background -> + + size *= BIG_FONT; + ppos.y -= m_lineHeight*(BIG_FONT-1.0f); + } + + // As \t;? + if ( beg+len < m_len && m_format != 0 && + (m_format[beg]&TITLE_MASK) == TITLE_NORM ) + { + start.x = ppos.x-MARGX; + end.x = dim.x-MARGX*2.0f; + start.y = ppos.y-(m_bMulti?0.0f:MARGY1); + end.y = m_lineHeight; + DrawPart(start, end, 2); // blue gradient background -> + } + + // Subtitle \s;? + if ( beg+len < m_len && m_format != 0 && + (m_format[beg]&TITLE_MASK) == TITLE_LITTLE ) + { + start.x = ppos.x-MARGX; + end.x = dim.x-MARGX*2.0f; + start.y = ppos.y-(m_bMulti?0.0f:MARGY1); + end.y = m_lineHeight; + DrawPart(start, end, 3); // yellow background gradient -> + } + + // Table \tab;? + if ( beg+len < m_len && m_format != 0 && + (m_format[beg]&COLOR_MASK) == COLOR_TABLE ) + { + start.x = ppos.x-MARGX; + end.x = dim.x-MARGX*2.0f; + start.y = ppos.y-(m_bMulti?0.0f:MARGY1); + end.y = m_lineHeight; + DrawPart(start, end, 11); // fond orange d�grad� -> + } + + // Image \image; ? + if ( beg+len < m_len && m_format != 0 && + (m_format[beg]&IMAGE_MASK) != 0 ) + { + line = 1; + while ( true ) // includes the image slices + { + if ( i+line >= m_lineTotal || + i+line >= m_lineFirst+m_lineVisible || + (m_format[beg+line]&IMAGE_MASK) == 0 ) break; + line ++; + } + + iIndex = m_text[beg]; // character = index in m_image + pos.y -= m_lineHeight*(line-1); + DrawImage(pos, m_image[iIndex].name, + m_image[iIndex].width*(m_fontSize/SMALLFONT), + m_image[iIndex].offset, m_image[iIndex].height*line, line); + pos.y -= m_lineHeight; + i += line-1; + continue; + } + + if ( ((m_bEdit && m_bFocus && m_bHilite) || + (!m_bEdit && m_bHilite) ) && + c1 != c2 && beg <= c2 && beg+len >= c1 ) // selected area? + { + o1 = c1; if ( o1 < beg ) o1 = beg; + o2 = c2; if ( o2 > beg+len ) o2 = beg+len; + + if ( m_format == 0 ) + { + start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, o1-beg, size, m_fontStretch, m_fontType); + end.x = m_engine->RetText()->RetStringWidth(m_text+o1, o2-o1, size, m_fontStretch, m_fontType); + } + else + { + start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, m_format+beg, o1-beg, size, m_fontStretch); + end.x = m_engine->RetText()->RetStringWidth(m_text+o1, m_format+o1, o2-o1, size, m_fontStretch); + } + + start.y = ppos.y-(m_bMulti?0.0f:MARGY1); + end.y = m_lineHeight; + if ( m_format != 0 && (m_format[beg]&TITLE_MASK) == TITLE_BIG ) end.y *= BIG_FONT; + DrawPart(start, end, 1); // plain yellow background + } + + eol = 16; // > + if ( len > 0 && m_text[beg+len-1] == '\n' ) + { + len --; // does not display the '\ n' + eol = 0; // nothing + } + if ( beg+len >= m_len ) + { + eol = 2; // square (eot) + } + if ( !m_bMulti || !m_bDisplaySpec ) eol = 0; + if ( m_format == 0 ) + { + m_engine->RetText()->DrawText(m_text+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, m_fontType, eol); + } + else + { + m_engine->RetText()->DrawText(m_text+beg, m_format+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, eol); + } + + pos.y -= m_lineHeight; + + if ( i < m_lineTotal-2 && m_lineOffset[i+1] == m_lineOffset[i+2] ) + { + pos.y -= m_lineHeight; // double jump line \b; + i ++; + } + } + + // Shows the cursor. + if ( (m_bEdit && m_bFocus && m_bHilite && Math::Mod(m_timeBlink, 1.0f) <= 0.5f) ) // it blinks + { + pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1*2.0f); + for ( i=m_lineFirst ; i<m_lineTotal ; i++ ) + { + if ( i == m_lineTotal-1 || m_cursor1 < m_lineOffset[i+1] ) + { + pos.x = m_pos.x+(10.0f/640.0f); + if ( m_bAutoIndent ) + { + pos.x += indentLength*m_lineIndent[i]; + } + + len = m_cursor1 - m_lineOffset[i]; + + if ( m_format == 0 ) + { + m_engine->RetText()->DimText(m_text+m_lineOffset[i], len, + pos, 1, size, + m_fontStretch, m_fontType, + start, end); + } + else + { + m_engine->RetText()->DimText(m_text+m_lineOffset[i], + m_format+m_lineOffset[i], + len, pos, 1, size, + m_fontStretch, + start, end); + } + + pos.x = end.x; + break; + } + pos.y -= m_lineHeight; + } + pos.x -= 1.0f/640.0f; + dim.x = 2.0f/640.0f; + dim.y = m_lineHeight; + DrawPart(pos, dim, 0); // red + } + + if ( m_scroll != 0 && !m_bGeneric ) + { + m_scroll->Draw(); + } +} + +// Draw an image part. + +void CEdit::DrawImage(Math::Point pos, char *name, float width, + float offset, float height, int nbLine) +{ + Math::Point uv1, uv2, dim; + float dp; + char filename[100]; + +//? sprintf(filename, "diagram\\%s.bmp", name); + UserDir(filename, name, "diagram"); + strcat(filename, ".bmp"); + + m_engine->SetTexture(filename); + m_engine->SetState(D3DSTATENORMAL); + + uv1.x = 0.0f; + uv2.x = 1.0f; + uv1.y = offset; + uv2.y = offset+height; + + dp = 0.5f/256.0f; + uv1.x += dp; + uv1.y += dp; + uv2.x -= dp; + uv2.y -= dp; + + dim.x = width; + dim.y = m_lineHeight*nbLine; + DrawIcon(pos, dim, uv1, uv2); +} + +// Draw the background. + +void CEdit::DrawBack(Math::Point pos, Math::Point dim) +{ + Math::Point uv1,uv2, corner; + float dp; + + if ( m_bGeneric ) return; + + m_engine->SetTexture("button2.tga"); + m_engine->SetState(D3DSTATENORMAL); + + if ( m_bMulti ) + { + uv1.x = 128.0f/256.0f; // light blue + uv1.y = 64.0f/256.0f; + uv2.x = 160.0f/256.0f; + uv2.y = 96.0f/256.0f; + } + else + { + uv1.x = 160.0f/256.0f; // medium blue + uv1.y = 192.0f/256.0f; + uv2.x = 192.0f/256.0f; + uv2.y = 224.0f/256.0f; + } + if ( m_icon == 1 ) + { + uv1.x = 192.0f/256.0f; // orange + uv1.y = 96.0f/256.0f; + uv2.x = 224.0f/256.0f; + uv2.y = 128.0f/256.0f; + } + + dp = 0.5f/256.0f; + uv1.x += dp; + uv1.y += dp; + uv2.x -= dp; + uv2.y -= dp; + + if ( m_bMulti ) + { + corner.x = 10.0f/640.0f; + corner.y = 10.0f/480.0f; + DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f); + } + else + { + DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f); + } +} + +// Draws an icon background. + +void CEdit::DrawPart(Math::Point pos, Math::Point dim, int icon) +{ + Math::Point uv1, uv2; + float dp; + +#if _POLISH + m_engine->SetTexture("textp.tga"); +#else + m_engine->SetTexture("text.tga"); +#endif + m_engine->SetState(D3DSTATENORMAL); + + uv1.x = (16.0f/256.0f)*(icon%16); + uv1.y = (240.0f/256.0f); + uv2.x = (16.0f/256.0f)+uv1.x; + uv2.y = (16.0f/256.0f)+uv1.y; + + dp = 0.5f/256.0f; + uv1.x += dp; + uv1.y += dp; + uv2.x -= dp; + uv2.y -= dp; + + DrawIcon(pos, dim, uv1, uv2); +} + + +// Give the text to edit. + +void CEdit::SetText(char *text, bool bNew) +{ + int i, j, font; + bool bBOL; + + if ( !bNew ) UndoMemorize(OPERUNDO_SPEC); + + m_len = strlen(text); + if ( m_len > m_maxChar ) m_len = m_maxChar; + + if ( m_format == 0 ) + { + if ( m_bAutoIndent ) + { + j = 0; + bBOL = true; + for ( i=0 ; i<m_len ; i++ ) + { + if ( text[i] == '\t' ) + { + if ( !bBOL ) m_text[j++] = ' '; + continue; // removes tabs + } + bBOL = ( text[i] == '\n' ); + + m_text[j++] = text[i]; + } + m_len = j; + } + else + { + strncpy(m_text, text, m_len); + } + } + else + { + font = m_fontType; + j = 0; + bBOL = true; + for ( i=0 ; i<m_len ; i++ ) + { + if ( m_bAutoIndent ) + { + if ( text[i] == '\t' ) + { + if ( !bBOL ) + { + m_text[j] = ' '; + m_format[j] = font; + j ++; + } + continue; // removes tabs + } + bBOL = ( text[i] == '\n' ); + } + + if ( text[i] == '\\' && text[i+2] == ';' ) + { + if ( text[i+1] == 'n' ) // normal ? + { + font &= ~FONT_MASK; + font |= FONT_COLOBOT; + i += 2; + } + else if ( text[i+1] == 'c' ) // cbot ? + { + font &= ~FONT_MASK; + font |= FONT_COURIER; + i += 2; + } + else if ( text[i+1] == 'b' ) // big title ? + { + font &= ~TITLE_MASK; + font |= TITLE_BIG; + i += 2; + } + else if ( text[i+1] == 't' ) // title ? + { + font &= ~TITLE_MASK; + font |= TITLE_NORM; + i += 2; + } + else if ( text[i+1] == 's' ) // subtitle ? + { + font &= ~TITLE_MASK; + font |= TITLE_LITTLE; + i += 2; + } + } + else + { + m_text[j] = text[i]; + m_format[j] = font; + j ++; + + font &= ~TITLE_MASK; // reset title + } + } + m_len = j; + } + + if ( bNew ) UndoFlush(); + + m_cursor1 = 0; + m_cursor2 = 0; // cursor to the beginning + Justif(); + ColumnFix(); +} + +// Returns a pointer to the edited text. + +char* CEdit::RetText() +{ + m_text[m_len] = 0; + return m_text; +} + +// Returns the edited text. + +void CEdit::GetText(char *buffer, int max) +{ + if ( m_len < max ) max = m_len; + if ( m_len > max ) max = max-1; + + strncpy(buffer, m_text, max); + buffer[max] = 0; +} + +// Returns the length of the text. + +int CEdit::RetTextLength() +{ + return m_len; +} + + + +// Returns a name in a command. +// \x nom1 nom2 nom3; + +void GetNameParam(char *cmd, int rank, char *buffer) +{ + int i; + + for ( i=0 ; i<rank ; i++ ) + { + while ( *cmd != ' ' && *cmd != ';' ) + { + cmd ++; + } + if ( *cmd != ';' ) cmd ++; + } + + while ( *cmd != ' ' && *cmd != ';' ) + { + *buffer++ = *cmd++; + } + *buffer = 0; +} + +// Returns a number of a command. +// \x nom n1 n2; + +int RetValueParam(char *cmd, int rank) +{ + int n, i; + + for ( i=0 ; i<rank ; i++ ) + { + while ( *cmd != ' ' && *cmd != ';' ) + { + cmd ++; + } + if ( *cmd != ';' ) cmd ++; + } + + sscanf(cmd, "%d", &n); + return n; +} + +// Frees all images. + +void CEdit::FreeImage() +{ + char filename[100]; + int i; + + for ( i=0 ; i<m_imageTotal ; i++ ) + { +//? sprintf(filename, "diagram\\%s.bmp", m_image[i].name); + UserDir(filename, m_image[i].name, "diagram"); + strcat(filename, ".bmp"); + m_engine->FreeTexture(filename); + } +} + +// Reads the texture of an image. + +void CEdit::LoadImage(char *name) +{ + char filename[100]; + +//? sprintf(filename, "diagram\\%s.bmp", name); + UserDir(filename, name, "diagram"); + strcat(filename, ".bmp"); + m_engine->LoadTexture(filename); +} + +// Read from a text file. + +bool CEdit::ReadText(char *filename, int addSize) +{ + FILE *file = NULL; + char *buffer; + int len, i, j, n, font, iIndex, iLines, iCount, iLink, res; + char iName[50]; + char text[50]; + float iWidth; + KeyRank key; + bool bInSoluce, bBOL; + + if ( filename[0] == 0 ) return false; + file = fopen(filename, "rb"); + if ( file == NULL ) return false; + + fseek(file, 0, SEEK_END); + len = ftell(file); + fseek(file, 0, SEEK_SET); + + m_maxChar = len+addSize+100; + m_len = len; + m_cursor1 = 0; + m_cursor2 = 0; + + FreeImage(); + delete m_text; + m_text = (char*)malloc(sizeof(char)*(m_maxChar+1)); + buffer = (char*)malloc(sizeof(char)*(m_maxChar+1)); + fread(buffer, 1, len, file); + + if ( m_format != 0 ) + { + delete m_format; + m_format = (char*)malloc(sizeof(char)*m_maxChar); + } + + fclose(file); + + bInSoluce = false; + font = m_fontType; + iIndex = 0; + iLink = 0; + m_imageTotal = 0; + m_markerTotal = 0; + i = j = 0; + bBOL = true; + while ( i < m_len ) + { + if ( m_bAutoIndent ) + { + if ( buffer[i] == '\t' ) + { + if ( !bBOL ) + { + m_text[j] = buffer[i]; + if ( m_format != 0 ) m_format[j] = font; + j ++; + } + i ++; + continue; // removes the tabs + } + bBOL = ( buffer[i] == '\n' || buffer[i] == '\r' ); + } + + if ( buffer[i] == '\r' ) // removes \ r + { + i ++; + } + else if ( m_format != 0 && buffer[i] == '\\' && buffer[i+2] == ';' ) + { + if ( buffer[i+1] == 'n' ) // normal ? + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~FONT_MASK; + font |= FONT_COLOBOT; + } + i += 3; + } + else if ( buffer[i+1] == 'c' ) // cbot ? + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~FONT_MASK; + font |= FONT_COURIER; + } + i += 3; + } + else if ( buffer[i+1] == 'b' ) // big title ? + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~TITLE_MASK; + font |= TITLE_BIG; + } + i += 3; + } + else if ( buffer[i+1] == 't' ) // title ? + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~TITLE_MASK; + font |= TITLE_NORM; + } + i += 3; + } + else if ( buffer[i+1] == 's' ) // subtitle ? + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~TITLE_MASK; + font |= TITLE_LITTLE; + } + i += 3; + } + else if ( buffer[i+1] == 'l' ) // link ? + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~COLOR_MASK; + font |= COLOR_LINK; + } + i += 3; + } + else + { + i += 3; + } + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \u marker name; ? + buffer[i+1] == 'u' && + buffer[i+2] == ' ' ) + { + if ( m_bSoluce || !bInSoluce ) + { + if ( iLink < EDITLINKMAX ) + { + GetNameParam(buffer+i+3, 0, m_link[iLink].name); + GetNameParam(buffer+i+3, 1, m_link[iLink].marker); + iLink ++; + } + font &= ~COLOR_MASK; + } + i += strchr(buffer+i, ';')-(buffer+i)+1; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \m marker; ? + buffer[i+1] == 'm' && + buffer[i+2] == ' ' ) + { + if ( m_bSoluce || !bInSoluce ) + { + if ( m_markerTotal < EDITLINKMAX ) + { + GetNameParam(buffer+i+3, 0, m_marker[m_markerTotal].name); + m_marker[m_markerTotal].pos = j; + m_markerTotal ++; + } + } + i += strchr(buffer+i, ';')-(buffer+i)+1; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \image name lx ly; ? + buffer[i+1] == 'i' && + buffer[i+2] == 'm' && + buffer[i+3] == 'a' && + buffer[i+4] == 'g' && + buffer[i+5] == 'e' && + buffer[i+6] == ' ' ) + { + if ( m_bSoluce || !bInSoluce ) + { +#if _DEMO + strcpy(iName, "demo"); +#else + GetNameParam(buffer+i+7, 0, iName); +#endif +//? iWidth = m_lineHeight*RetValueParam(buffer+i+7, 1); + iWidth = (float)RetValueParam(buffer+i+7, 1); + iWidth *= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT); + iLines = RetValueParam(buffer+i+7, 2); + LoadImage(iName); + + // A part of image per line of text. + for ( iCount=0 ; iCount<iLines ; iCount++ ) + { + strcpy(m_image[iIndex].name, iName); + m_image[iIndex].offset = (float)iCount/iLines; + m_image[iIndex].height = 1.0f/iLines; + m_image[iIndex].width = iWidth*0.75f; + + m_text[j] = (char)(iIndex++); // as an index into m_image + m_format[j] = (unsigned char)IMAGE_MASK; + j ++; + } + } + i += strchr(buffer+i, ';')-(buffer+i)+1; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \button; ? + buffer[i+1] == 'b' && + buffer[i+2] == 'u' && + buffer[i+3] == 't' && + buffer[i+4] == 't' && + buffer[i+5] == 'o' && + buffer[i+6] == 'n' && + buffer[i+7] == ' ' ) + { + if ( m_bSoluce || !bInSoluce ) + { + m_text[j] = RetValueParam(buffer+i+8, 0); + m_format[j] = font|FONT_BUTTON; + j ++; + } + i += strchr(buffer+i, ';')-(buffer+i)+1; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \token; ? + buffer[i+1] == 't' && + buffer[i+2] == 'o' && + buffer[i+3] == 'k' && + buffer[i+4] == 'e' && + buffer[i+5] == 'n' && + buffer[i+6] == ';' ) + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~COLOR_MASK; + font |= COLOR_TOKEN; + } + i += 7; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \type; ? + buffer[i+1] == 't' && + buffer[i+2] == 'y' && + buffer[i+3] == 'p' && + buffer[i+4] == 'e' && + buffer[i+5] == ';' ) + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~COLOR_MASK; + font |= COLOR_TYPE; + } + i += 6; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \const; ? + buffer[i+1] == 'c' && + buffer[i+2] == 'o' && + buffer[i+3] == 'n' && + buffer[i+4] == 's' && + buffer[i+5] == 't' && + buffer[i+6] == ';' ) + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~COLOR_MASK; + font |= COLOR_CONST; + } + i += 7; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \key; ? + buffer[i+1] == 'k' && + buffer[i+2] == 'e' && + buffer[i+3] == 'y' && + buffer[i+4] == ';' ) + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~COLOR_MASK; + font |= COLOR_KEY; + } + i += 5; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \tab; ? + buffer[i+1] == 't' && + buffer[i+2] == 'a' && + buffer[i+3] == 'b' && + buffer[i+4] == ';' ) + { + if ( m_bSoluce || !bInSoluce ) + { + font |= COLOR_TABLE; + } + i += 5; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \norm; ? + buffer[i+1] == 'n' && + buffer[i+2] == 'o' && + buffer[i+3] == 'r' && + buffer[i+4] == 'm' && + buffer[i+5] == ';' ) + { + if ( m_bSoluce || !bInSoluce ) + { + font &= ~COLOR_MASK; + } + i += 6; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \begin soluce; ? + buffer[i+1] == 'b' && + buffer[i+2] == 's' && + buffer[i+3] == ';' ) + { + bInSoluce = true; + i += 4; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \end soluce; ? + buffer[i+1] == 'e' && + buffer[i+2] == 's' && + buffer[i+3] == ';' ) + { + bInSoluce = false; + i += 4; + } + else if ( m_format != 0 && + buffer[i+0] == '\\' && // \key name; ? + buffer[i+1] == 'k' && + buffer[i+2] == 'e' && + buffer[i+3] == 'y' && + buffer[i+4] == ' ' ) + { + if ( m_bSoluce || !bInSoluce ) + { + if ( SearchKey(buffer+i+5, key) ) + { + res = m_engine->RetKey(key, 0); + if ( res != 0 ) + { + if ( GetResource(RES_KEY, res, iName) ) + { + m_text[j] = ' '; + m_format[j] = font; + j ++; + n = 0; + while ( iName[n] != 0 ) + { + m_text[j] = iName[n++]; + m_format[j] = font; + j ++; + } + m_text[j] = ' '; + m_format[j] = font; + j ++; + + res = m_engine->RetKey(key, 1); + if ( res != 0 ) + { + if ( GetResource(RES_KEY, res, iName) ) + { + GetResource(RES_TEXT, RT_KEY_OR, text); + n = 0; + while ( text[n] != 0 ) + { + m_text[j] = text[n++]; + m_format[j] = font&~COLOR_MASK; + j ++; + } + n = 0; + while ( iName[n] != 0 ) + { + m_text[j] = iName[n++]; + m_format[j] = font; + j ++; + } + m_text[j] = ' '; + m_format[j] = font; + j ++; + } + } + while ( buffer[i++] != ';' ); + continue; + } + } + } + m_text[j] = '?'; + m_format[j] = font; + j ++; + } + while ( buffer[i++] != ';' ); + } + else + { + if ( m_bSoluce || !bInSoluce ) + { + m_text[j] = buffer[i]; + if ( m_format != 0 ) m_format[j] = font; + j ++; + } + i ++; + + font &= ~TITLE_MASK; // reset title + + if ( (font&COLOR_MASK) == COLOR_TABLE ) + { + font &= ~COLOR_TABLE; + } + } + } + m_len = j; + m_imageTotal = iIndex; + + delete buffer; + + Justif(); + ColumnFix(); + return true; +} + +// Writes all the text in a file. + +bool CEdit::WriteText(char *filename) +{ + FILE* file; + char buffer[1000+20]; + int i, j, k, n; + float iDim; + + if ( filename[0] == 0 ) return false; + file = fopen(filename, "wb"); + if ( file == NULL ) return false; + + if ( m_bAutoIndent ) + { + iDim = m_dim.x; + m_dim.x = 1000.0f; // puts an infinite width! + Justif(); + } + + i = j = k = 0; + while ( m_text[i] != 0 && i < m_len ) + { + if ( m_bAutoIndent && i == m_lineOffset[k] ) + { + for ( n=0 ; n<m_lineIndent[k] ; n++ ) + { + buffer[j++] = '\t'; + } + k ++; + } + + buffer[j++] = m_text[i]; + + if ( m_text[i] == '\n' ) + { + buffer[j-1] = '\r'; + buffer[j++] = '\n'; // \r\n (0x0D, 0x0A) + } + + if ( j >= 1000-1 ) + { + fwrite(buffer, 1, j, file); + j = 0; + } + + i ++; + } + if ( j > 0 ) + { + fwrite(buffer, 1, j, file); + } + + fclose(file); + + if ( m_bAutoIndent ) + { + m_dim.x = iDim; // presents the initial width + Justif(); + } + + return true; +} + + +// Manage the number of max characters editable. + +void CEdit::SetMaxChar(int max) +{ + m_maxChar = max; + FreeImage(); + delete m_text; + m_text = (char*)malloc(sizeof(char)*(m_maxChar+1)); + + if ( m_format != 0 ) + { + delete m_format; + m_format = (char*)malloc(sizeof(char)*m_maxChar); + } + + m_len = 0; + m_cursor1 = 0; + m_cursor2 = 0; + Justif(); + UndoFlush(); +} + +int CEdit::RetMaxChar() +{ + return m_maxChar; +} + + +// Mode management "editable". + +void CEdit::SetEditCap(bool bMode) +{ + m_bEdit = bMode; +} + +bool CEdit::RetEditCap() +{ + return m_bEdit; +} + +// Mode management "hilitable" (that's the franch). + +void CEdit::SetHiliteCap(bool bEnable) +{ + m_bHilite = bEnable; +} + +bool CEdit::RetHiliteCap() +{ + return m_bHilite; +} + +// Lift in / out connection. + +void CEdit::SetInsideScroll(bool bInside) +{ + m_bInsideScroll = bInside; +} + +bool CEdit::RetInsideScroll() +{ + return m_bInsideScroll; +} + +// Specifies whether to display the links showing the solution. + +void CEdit::SetSoluceMode(bool bSoluce) +{ + m_bSoluce = bSoluce; +} + +bool CEdit::RetSoluceMode() +{ + return m_bSoluce; +} + +// Indicates whether the text is a defile that generic. + +void CEdit::SetGenericMode(bool bGeneric) +{ + m_bGeneric = bGeneric; +} + +bool CEdit::RetGenericMode() +{ + return m_bGeneric; +} + + +// Management of automatic indentation mode with {}. + +void CEdit::SetAutoIndent(bool bMode) +{ + m_bAutoIndent = bMode; +} + +bool CEdit::RetAutoIndent() +{ + return m_bAutoIndent; +} + + + +// Moves the cursors. + +void CEdit::SetCursor(int cursor1, int cursor2) +{ + if ( cursor1 > m_len ) cursor1 = m_len; + if ( cursor2 > m_len ) cursor2 = m_len; + + m_cursor1 = cursor1; + m_cursor2 = cursor2; + m_bUndoForce = true; + ColumnFix(); +} + +// Returns the sliders. + +void CEdit::GetCursor(int &cursor1, int &cursor2) +{ + cursor1 = m_cursor1; + cursor2 = m_cursor2; +} + + +// Displayed line modifies the first. + +void CEdit::SetFirstLine(int rank) +{ + Scroll(rank, true); +} + +// Returns the first displayed line. + +int CEdit::RetFirstLine() +{ + if ( m_historyTotal > 0 ) + { + if ( m_historyCurrent == 0 ) + { + return m_lineFirst; + } + else + { + return m_history[0].firstLine; + } + } + return m_lineFirst; +} + + +// Shows the selected area. + +void CEdit::ShowSelect() +{ + int cursor1, cursor2, line; + + if ( m_cursor1 < m_cursor2 ) + { + cursor1 = m_cursor1; + cursor2 = m_cursor2; + } + else + { + cursor1 = m_cursor2; + cursor2 = m_cursor1; + } + + line = RetCursorLine(cursor2); + if ( line >= m_lineFirst+m_lineVisible ) + { + line -= m_lineVisible-1; + if ( line < 0 ) line = 0; + Scroll(line, false); + } + + line = RetCursorLine(cursor1); + if ( line < m_lineFirst ) + { + Scroll(line, false); + } +} + + +// Management of the display mode of special characters. + +void CEdit::SetDisplaySpec(bool bDisplay) +{ + m_bDisplaySpec = bDisplay; +} + +bool CEdit::RetDisplaySpec() +{ + return m_bDisplaySpec; +} + + +// Multi-fonts mode management. + +void CEdit::SetMultiFont(bool bMulti) +{ + if ( bMulti ) + { + delete m_format; + m_format = (char*)malloc(sizeof(char)*m_maxChar); + memset(m_format, 0, m_maxChar); + } + else + { + delete m_format; + m_format = 0; + } +} + +bool CEdit::RetMultiFont() +{ + return ( m_format != 0 ); +} + + +// Management of the character size. + +void CEdit::SetFontSize(float size) +{ + CControl::SetFontSize(size); + + MoveAdjust(); +} + + +// Moves according to the visible lift. + +void CEdit::Scroll() +{ + float value; + + if ( m_scroll != 0 ) + { + value = m_scroll->RetVisibleValue(); + value *= m_lineTotal-m_lineVisible; + Scroll((int)(value+0.5f), true); + } +} + +// Moves according to the visible lift. + +void CEdit::Scroll(int pos, bool bAdjustCursor) +{ + int max, line; + + m_lineFirst = pos; + + if ( m_lineFirst < 0 ) m_lineFirst = 0; + + max = m_lineTotal-m_lineVisible; + if ( max < 0 ) max = 0; + if ( m_lineFirst > max ) m_lineFirst = max; + + line = RetCursorLine(m_cursor1); + + if ( bAdjustCursor && m_bEdit ) + { + // Cursor too high? + if ( line < m_lineFirst ) + { + MoveLine(m_lineFirst-line, false, false); + return; + } + + // Cursor too low? + if ( line >= m_lineFirst+m_lineVisible ) + { + MoveLine(m_lineFirst+m_lineVisible-line-1, false, false); + return; + } + } + + Justif(); +} + +// Moves the cursor to the beginning of the line. + +void CEdit::MoveHome(bool bWord, bool bSelect) +{ + int begin, tab; + + if ( bWord ) + { + m_cursor1 = 0; + } + else + { + begin = m_cursor1; + while ( begin > 0 && m_text[begin-1] != '\n' ) + { + begin --; + } + + tab = begin; + while ( tab < m_len && (m_text[tab] == '\t' || m_text[tab] == ' ') ) + { + tab ++; + } + + if ( m_cursor1 == tab ) + { + m_cursor1 = begin; + } + else + { + m_cursor1 = tab; + } + } + if ( !bSelect ) m_cursor2 = m_cursor1; + + m_bUndoForce = true; + Justif(); + ColumnFix(); +} + +// Moves the cursor to the end of the line. + +void CEdit::MoveEnd(bool bWord, bool bSelect) +{ + if ( bWord ) + { + m_cursor1 = m_len; + } + else + { + while ( m_cursor1 < m_len && m_text[m_cursor1] != '\n' ) + { + m_cursor1 ++; + } + } + if ( !bSelect ) m_cursor2 = m_cursor1; + + m_bUndoForce = true; + Justif(); + ColumnFix(); +} + +// Moves the cursor through characters. + +void CEdit::MoveChar(int move, bool bWord, bool bSelect) +{ + int character; + + if ( move == -1 ) // back? + { + if ( bWord ) + { + while ( m_cursor1 > 0 ) + { + character = (unsigned char)m_text[m_cursor1-1]; + if ( !IsSpace(character) ) break; + m_cursor1 --; + } + + if ( m_cursor1 > 0 ) + { + character = (unsigned char)m_text[m_cursor1-1]; + if ( IsSpace(character) ) + { + while ( m_cursor1 > 0 ) + { + character = (unsigned char)m_text[m_cursor1-1]; + if ( !IsSpace(character) ) break; + m_cursor1 --; + } + } + else if ( IsWord(character) ) + { + while ( m_cursor1 > 0 ) + { + character = (unsigned char)m_text[m_cursor1-1]; + if ( !IsWord(character) ) break; + m_cursor1 --; + } + } + else if ( IsSep(character) ) + { + while ( m_cursor1 > 0 ) + { + character = (unsigned char)m_text[m_cursor1-1]; + if ( !IsSep(character) ) break; + m_cursor1 --; + } + } + } + } + else + { + m_cursor1 --; + if ( m_cursor1 < 0 ) m_cursor1 = 0; + } + } + + if ( move == 1 ) // advance? + { + if ( bWord ) + { + if ( m_cursor1 < m_len ) + { + character = (unsigned char)m_text[m_cursor1]; + if ( IsSpace(character) ) + { + while ( m_cursor1 < m_len ) + { + character = (unsigned char)m_text[m_cursor1]; + if ( !IsSpace(character) ) break; + m_cursor1 ++; + } + } + else if ( IsWord(character) ) + { + while ( m_cursor1 < m_len ) + { + character = (unsigned char)m_text[m_cursor1]; + if ( !IsWord(character) ) break; + m_cursor1 ++; + } + } + else if ( IsSep(character) ) + { + while ( m_cursor1 < m_len ) + { + character = (unsigned char)m_text[m_cursor1]; + if ( !IsSep(character) ) break; + m_cursor1 ++; + } + } + } + + while ( m_cursor1 < m_len ) + { + character = (unsigned char)m_text[m_cursor1]; + if ( !IsSpace(character) ) break; + m_cursor1 ++; + } + } + else + { + m_cursor1 ++; + if ( m_cursor1 > m_len ) m_cursor1 = m_len; + } + } + + if ( !bSelect ) m_cursor2 = m_cursor1; + + m_bUndoForce = true; + Justif(); + ColumnFix(); +} + +// Moves the cursor lines. + +void CEdit::MoveLine(int move, bool bWord, bool bSelect) +{ + float column, indentLength; + int i, line, c; + + if ( move == 0 ) return; + + for ( i=0 ; i>move ; i-- ) // back? + { + while ( m_cursor1 > 0 && m_text[m_cursor1-1] != '\n' ) + { + m_cursor1 --; + } + if ( m_cursor1 != 0 ) + { + m_cursor1 --; + while ( m_cursor1 > 0 ) + { + if ( m_text[--m_cursor1] == '\n' ) + { + m_cursor1 ++; + break; + } + } + } + } + + for ( i=0 ; i<move ; i++ ) // advance? + { + while ( m_cursor1 < m_len ) + { + if ( m_text[m_cursor1++] == '\n' ) + { + break; + } + } + } + + line = RetCursorLine(m_cursor1); + + column = m_column; + if ( m_bAutoIndent ) + { + indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType) + * m_engine->RetEditIndentValue(); + column -= indentLength*m_lineIndent[line]; + } + + if ( m_format == 0 ) + { + c = m_engine->RetText()->Detect(m_text+m_lineOffset[line], + m_lineOffset[line+1]-m_lineOffset[line], + column, m_fontSize, + m_fontStretch, m_fontType); + } + else + { + c = m_engine->RetText()->Detect(m_text+m_lineOffset[line], + m_format+m_lineOffset[line], + m_lineOffset[line+1]-m_lineOffset[line], + column, m_fontSize, m_fontStretch); + } + + m_cursor1 = m_lineOffset[line]+c; + if ( !bSelect ) m_cursor2 = m_cursor1; + + m_bUndoForce = true; + Justif(); +} + +// Sets the horizontal position. + +void CEdit::ColumnFix() +{ + float indentLength; + int line; + + line = RetCursorLine(m_cursor1); + + if ( m_format == 0 ) + { + m_column = m_engine->RetText()->RetStringWidth + ( + m_text+m_lineOffset[line], + m_cursor1-m_lineOffset[line], + m_fontSize, m_fontStretch, m_fontType + ); + } + else + { + m_column = m_engine->RetText()->RetStringWidth + ( + m_text+m_lineOffset[line], + m_format+m_lineOffset[line], + m_cursor1-m_lineOffset[line], + m_fontSize, m_fontStretch + ); + } + + if ( m_bAutoIndent ) + { + indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType) + * m_engine->RetEditIndentValue(); + m_column += indentLength*m_lineIndent[line]; + } +} + + +// Cut the selected characters or entire line. + +bool CEdit::Cut() +{ + HGLOBAL hg; + char* text; + char c; + int c1, c2, start, len, i, j; + + if ( !m_bEdit ) return false; + + c1 = m_cursor1; + c2 = m_cursor2; + if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2 + + if ( c1 == c2 ) + { + while ( c1 > 0 ) + { + if ( m_text[c1-1] == '\n' ) break; + c1 --; + } + while ( c2 < m_len ) + { + c2 ++; + if ( m_text[c2-1] == '\n' ) break; + } + } + + if ( c1 == c2 ) return false; + + start = c1; + len = c2-c1; + + if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) ) + { + return false; + } + if ( !(text = (char*)GlobalLock(hg)) ) + { + GlobalFree(hg); + return false; + } + + j = 0; + for ( i=start ; i<start+len ; i++ ) + { + c = m_text[i]; + if ( c == '\n' ) text[j++] = '\r'; + text[j++] = c; + } + text[j] = 0; + GlobalUnlock(hg); + + if ( !OpenClipboard(NULL) ) + { + GlobalFree(hg); + return false; + } + if ( !EmptyClipboard() ) + { + GlobalFree(hg); + return false; + } + if ( !SetClipboardData(CF_TEXT, hg) ) + { + GlobalFree(hg); + return false; + } + CloseClipboard(); + + UndoMemorize(OPERUNDO_SPEC); + m_cursor1 = c1; + m_cursor2 = c2; + DeleteOne(0); // deletes the selected characters + Justif(); + ColumnFix(); + SendModifEvent(); + return true; +} + +// Copy the selected characters or entire line. + +bool CEdit::Copy() +{ + HGLOBAL hg; + char* text; + char c; + int c1, c2, start, len, i, j; + + c1 = m_cursor1; + c2 = m_cursor2; + if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2 + + if ( c1 == c2 ) + { + while ( c1 > 0 ) + { + if ( m_text[c1-1] == '\n' ) break; + c1 --; + } + while ( c2 < m_len ) + { + c2 ++; + if ( m_text[c2-1] == '\n' ) break; + } + } + + if ( c1 == c2 ) return false; + + start = c1; + len = c2-c1; + + if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) ) + { + return false; + } + if ( !(text = (char*)GlobalLock(hg)) ) + { + GlobalFree(hg); + return false; + } + + j = 0; + for ( i=start ; i<start+len ; i++ ) + { + c = m_text[i]; + if ( c == '\n' ) text[j++] = '\r'; + text[j++] = c; + } + text[j] = 0; + GlobalUnlock(hg); + + if ( !OpenClipboard(NULL) ) + { + GlobalFree(hg); + return false; + } + if ( !EmptyClipboard() ) + { + GlobalFree(hg); + return false; + } + if ( !SetClipboardData(CF_TEXT, hg) ) + { + GlobalFree(hg); + return false; + } + CloseClipboard(); + + return true; +} + +// Paste the contents of the notebook. + +bool CEdit::Paste() +{ + HANDLE h; + char c; + char* p; + + if ( !m_bEdit ) return false; + + if ( !OpenClipboard(NULL) ) + { + return false; + } + + if ( !(h = GetClipboardData(CF_TEXT)) ) + { + CloseClipboard(); + return false; + } + + if ( !(p = (char*)GlobalLock(h)) ) + { + CloseClipboard(); + return false; + } + + UndoMemorize(OPERUNDO_SPEC); + + while ( *p != 0 ) + { + c = *p++; + if ( c == '\r' ) continue; + if ( c == '\t' && m_bAutoIndent ) continue; + InsertOne(c); + } + + GlobalUnlock(h); + CloseClipboard(); + + Justif(); + ColumnFix(); + SendModifEvent(); + return true; +} + + +// Cancels the last action. + +bool CEdit::Undo() +{ + if ( !m_bEdit ) return false; + + return UndoRecall(); +} + + +// Inserts a character. + +void CEdit::Insert(char character) +{ + int i, level, tab; + + if ( !m_bEdit ) return; + + if ( !m_bMulti ) // single-line? + { + if ( character == '\n' || + character == '\t' ) return; + } + + UndoMemorize(OPERUNDO_INSERT); + + if ( m_bMulti && !m_bAutoIndent ) + { + if ( character == '\n' ) + { + InsertOne(character); + level = IndentCompute(); + for ( i=0 ; i<level ; i++ ) + { + InsertOne('\t'); + } + } + else if ( character == '{' ) + { + tab = IndentTabCount(); + if ( tab != -1 ) + { + level = IndentCompute(); + IndentTabAdjust(level-tab); + } + InsertOne(character); + } + else if ( character == '}' ) + { + tab = IndentTabCount(); + if ( tab != -1 ) + { + level = IndentCompute()-1; + IndentTabAdjust(level-tab); + } + InsertOne(character); + } + else + { + InsertOne(character); + } + } + else if ( m_bAutoIndent ) + { + if ( character == '{' ) + { + InsertOne(character); + InsertOne('\n'); + InsertOne('\n'); + InsertOne('}'); + MoveChar(-1, false, false); + MoveChar(-1, false, false); + } +#if 0 + else if ( character == '(' ) + { + InsertOne(character); + InsertOne(')'); + MoveChar(-1, false, false); + } + else if ( character == '[' ) + { + InsertOne(character); + InsertOne(']'); + MoveChar(-1, false, false); + } +#endif + else if ( character == '\t' ) + { + for ( i=0 ; i<m_engine->RetEditIndentValue() ; i++ ) + { + InsertOne(' '); + } + } + else + { + InsertOne(character); + } + } + else + { + InsertOne(character); + } + + Justif(); + ColumnFix(); +} + +// Inserts a plain character. + +void CEdit::InsertOne(char character) +{ + int i; + + if ( !m_bEdit ) return; + if ( !m_bMulti && character == '\n' ) return; + + if ( m_cursor1 != m_cursor2 ) + { + DeleteOne(0); // deletes the selected characters + } + + if ( m_len >= m_maxChar ) return; + + for ( i=m_len ; i>=m_cursor1 ; i-- ) + { + m_text[i] = m_text[i-1]; // shoot + + if ( m_format != 0 ) + { + m_format[i] = m_format[i-1]; // shoot + } + } + + m_len ++; + + m_text[m_cursor1] = character; + + if ( m_format != 0 ) + { + m_format[m_cursor1] = 0; + } + + m_cursor1++; + m_cursor2 = m_cursor1; +} + +// Deletes the character left of cursor or all selected characters. + +void CEdit::Delete(int dir) +{ + if ( !m_bEdit ) return; + + UndoMemorize(OPERUNDO_DELETE); + DeleteOne(dir); + + Justif(); + ColumnFix(); +} + +// Deletes the character left of cursor or all selected plain characters. + +void CEdit::DeleteOne(int dir) +{ + int i, end, hole; + + if ( !m_bEdit ) return; + + if ( m_cursor1 == m_cursor2 ) + { + if ( dir < 0 ) + { + if ( m_cursor1 == 0 ) return; + m_cursor1 --; + } + else + { + if ( m_cursor2 == m_len ) return; + m_cursor2 ++; + } + } + + if ( m_cursor1 > m_cursor2 ) Math::Swap(m_cursor1, m_cursor2); + hole = m_cursor2-m_cursor1; + end = m_len-hole; + for ( i=m_cursor1 ; i<end ; i++ ) + { + m_text[i] = m_text[i+hole]; + + if ( m_format != 0 ) + { + m_format[i] = m_format[i+hole]; + } + } + m_len -= hole; + m_cursor2 = m_cursor1; +} + + +// Calculates the indentation level of brackets {and}. + +int CEdit::IndentCompute() +{ + int i, level; + + level = 0; + for ( i=0 ; i<m_cursor1 ; i++ ) + { + if ( m_text[i] == '{' ) level ++; + if ( m_text[i] == '}' ) level --; + } + + if ( level < 0 ) level = 0; + return level; +} + +// Counts the number of tabs before the cursor. +// Returns -1 if there is something else. + +int CEdit::IndentTabCount() +{ + int i, nb; + + if ( m_cursor1 != m_cursor2 ) return -1; + + i = m_cursor1; + nb = 0; + while ( i > 0 ) + { + if ( m_text[i-1] == '\n' ) return nb; + if ( m_text[i-1] != '\t' ) return -1; + nb ++; + i --; + } + return nb; +} + +// Adds or removes qq tabs. + +void CEdit::IndentTabAdjust(int number) +{ + int i; + + for ( i=0 ; i<number ; i++ ) // add? + { + InsertOne('\t'); + } + + for ( i=0 ; i>number ; i-- ) // delete? + { + DeleteOne(-1); + } +} + + +// Indent the left or right the entire selection. + +bool CEdit::Shift(bool bLeft) +{ + bool bInvert = false; + int c1, c2, i; + + if ( m_cursor1 == m_cursor2 ) return false; + + UndoMemorize(OPERUNDO_SPEC); + + c1 = m_cursor1; + c2 = m_cursor2; + if ( c1 > c2 ) + { + Math::Swap(c1, c2); // always c1 <= c2 + bInvert = true; + } + + if ( c1 > 0 ) + { + if ( m_text[c1-1] != '\n' ) return false; + } + if ( c2 < m_len ) + { + if ( m_text[c2-1] != '\n' ) return false; + } + + if ( bLeft ) // shifts left? + { + i = c1; + while ( i < c2 ) + { + if ( m_text[i] == '\t' ) + { + m_cursor1 = i; + m_cursor2 = i+1; + DeleteOne(0); + c2 --; + } + while ( i < c2 && m_text[i++] != '\n' ); + } + } + else // shifts right? + { + i = c1; + while ( i < c2 ) + { + m_cursor1 = m_cursor2 = i; + InsertOne('\t'); + c2 ++; + while ( i < c2 && m_text[i++] != '\n' ); + } + } + + if ( bInvert ) Math::Swap(c1, c2); + m_cursor1 = c1; + m_cursor2 = c2; + + Justif(); + ColumnFix(); + SendModifEvent(); + return true; +} + +// Math::Min conversion <-> shift the selection. + +bool CEdit::MinMaj(bool bMaj) +{ + int c1, c2, i, character; + + if ( m_cursor1 == m_cursor2 ) return false; + + UndoMemorize(OPERUNDO_SPEC); + + c1 = m_cursor1; + c2 = m_cursor2; + if ( c1 > c2 ) Math::Swap(c1, c2); // alwyas c1 <= c2 + + for ( i=c1 ; i<c2 ; i++ ) + { + character = (unsigned char)m_text[i]; + if ( bMaj ) character = RetToUpper(character); + else character = RetToLower(character); + m_text[i] = character; + } + + Justif(); + ColumnFix(); + SendModifEvent(); + return true; +} + + +// Cut all text lines. + +void CEdit::Justif() +{ + float width, value, size, indentLength; + int i, j, line, indent; + bool bDual, bString, bRem; + + indent = 0; + m_lineTotal = 0; + m_lineOffset[m_lineTotal] = 0; + m_lineIndent[m_lineTotal] = indent; + m_lineTotal ++; + + if ( m_bAutoIndent ) + { + indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType) + * m_engine->RetEditIndentValue(); + } + + bString = bRem = false; + i = 0; + while ( true ) + { + bDual = false; + + width = m_dim.x-(10.0f/640.0f)*2.0f-(m_bMulti?MARGX*2.0f+SCROLL_WIDTH:0.0f); + if ( m_bAutoIndent ) + { + width -= indentLength*m_lineIndent[m_lineTotal-1]; + } + + if ( m_format == 0 ) + { + i += m_engine->RetText()->Justif(m_text+i, m_len-i, width, + m_fontSize, m_fontStretch, + m_fontType); + } + else + { + size = m_fontSize; + + if ( (m_format[i]&TITLE_MASK) == TITLE_BIG ) // headline? + { + size *= BIG_FONT; + bDual = true; + } + + if ( (m_format[i]&IMAGE_MASK) != 0 ) // image part? + { + i ++; // jumps just a character (index in m_image) + } + else + { + i += m_engine->RetText()->Justif(m_text+i, m_format+i, + m_len-i, width, + size, m_fontStretch); + } + } + + if ( i >= m_len ) break; + + if ( m_bAutoIndent ) + { + for ( j=m_lineOffset[m_lineTotal-1] ; j<i ; j++ ) + { + if ( !bRem && m_text[j] == '\"' ) bString = !bString; + if ( !bString && + m_text[j] == '/' && + m_text[j+1] == '/' ) bRem = true; + if ( m_text[j] == '\n' ) bString = bRem = false; + if ( m_text[j] == '{' && !bString && !bRem ) indent ++; + if ( m_text[j] == '}' && !bString && !bRem ) indent --; + } + if ( indent < 0 ) indent = 0; + } + + m_lineOffset[m_lineTotal] = i; + m_lineIndent[m_lineTotal] = indent; + m_lineTotal ++; + if ( bDual ) + { + m_lineOffset[m_lineTotal] = i; + m_lineIndent[m_lineTotal] = indent; + m_lineTotal ++; + } + if ( m_lineTotal >= EDITLINEMAX-2 ) break; + } + if ( m_len > 0 && m_text[m_len-1] == '\n' ) + { + m_lineOffset[m_lineTotal] = m_len; + m_lineIndent[m_lineTotal] = 0; + m_lineTotal ++; + } + m_lineOffset[m_lineTotal] = m_len; + m_lineIndent[m_lineTotal] = 0; + + if ( m_bAutoIndent ) + { + for ( i=0 ; i<=m_lineTotal ; i++ ) + { + if ( m_text[m_lineOffset[i]] == '}' ) + { + if ( m_lineIndent[i] > 0 ) m_lineIndent[i] --; + } + } + } + + if ( m_bMulti ) + { + if ( m_bEdit ) + { + line = RetCursorLine(m_cursor1); + if ( line < m_lineFirst ) + { + m_lineFirst = line; + } + if ( line >= m_lineFirst+m_lineVisible ) + { + m_lineFirst = line-m_lineVisible+1; + } + } + } + else + { + m_lineFirst = 0; + } + + if ( m_scroll != 0 ) + { + if ( m_lineTotal <= m_lineVisible ) + { + m_scroll->SetVisibleRatio(1.0f); + m_scroll->SetVisibleValue(0.0f); + m_scroll->SetArrowStep(0.0f); + } + else + { + value = (float)m_lineVisible/m_lineTotal; + m_scroll->SetVisibleRatio(value); + + value = (float)m_lineFirst/(m_lineTotal-m_lineVisible); + m_scroll->SetVisibleValue(value); + + value = (float)1.0f/(m_lineTotal-m_lineVisible); + m_scroll->SetArrowStep(value); + } + } + + m_timeBlink = 0.0f; // lights the cursor immediately +} + +// Returns the rank of the line where the cursor is located. + +int CEdit::RetCursorLine(int cursor) +{ + int line, i; + + line = 0; + for ( i=0 ; i<m_lineTotal ; i++ ) + { + if ( cursor >= m_lineOffset[i] ) + { + line = i; + } + } + return line; +} + + +// Flush the buffer undo. + +void CEdit::UndoFlush() +{ + int i; + + for ( i=0 ; i<EDITUNDOMAX ; i++ ) + { + delete m_undo[i].text; + m_undo[i].text = 0; + } + + m_bUndoForce = true; + m_undoOper = OPERUNDO_SPEC; +} + +// Memorize the current state before a change. + +void CEdit::UndoMemorize(OperUndo oper) +{ + int i, len; + + if ( !m_bUndoForce && + oper != OPERUNDO_SPEC && + m_undoOper != OPERUNDO_SPEC && + oper == m_undoOper ) return; + + m_bUndoForce = false; + m_undoOper = oper; + + delete m_undo[EDITUNDOMAX-1].text; + + for ( i=EDITUNDOMAX-1 ; i>=1 ; i-- ) + { + m_undo[i] = m_undo[i-1]; + } + + len = m_len; + if ( len == 0 ) len ++; + m_undo[0].text = (char*)malloc(sizeof(char)*(len+1)); + memcpy(m_undo[0].text, m_text, m_len); + m_undo[0].len = m_len; + + m_undo[0].cursor1 = m_cursor1; + m_undo[0].cursor2 = m_cursor2; + m_undo[0].lineFirst = m_lineFirst; +} + +// Back to previous state. + +bool CEdit::UndoRecall() +{ + int i; + + if ( m_undo[0].text == 0 ) return false; + + m_len = m_undo[0].len; + memcpy(m_text, m_undo[0].text, m_len); + + m_cursor1 = m_undo[0].cursor1; + m_cursor2 = m_undo[0].cursor2; + m_lineFirst = m_undo[0].lineFirst; + + for ( i=0 ; i<EDITUNDOMAX-1 ; i++ ) + { + m_undo[i] = m_undo[i+1]; + } + m_undo[EDITUNDOMAX-1].text = 0; + + m_bUndoForce = true; + Justif(); + ColumnFix(); + SendModifEvent(); + return true; +} + + +// Clears the format of all characters. + +bool CEdit::ClearFormat() +{ + if ( m_format == 0 ) + { + SetMultiFont(true); + } + memset(m_format, m_fontType, m_len); + + return true; +} + +// Changes the format of a sequence of characters. + +bool CEdit::SetFormat(int cursor1, int cursor2, int format) +{ + int i; + + if ( m_format == 0 ) return false; + + for ( i=cursor1 ; i<cursor2 ; i++ ) + { + m_format[i] |= format; + } + + return true; +} + + |