diff options
Diffstat (limited to 'freebsdtvision/lib/TEditor.cc')
-rw-r--r-- | freebsdtvision/lib/TEditor.cc | 1144 |
1 files changed, 1144 insertions, 0 deletions
diff --git a/freebsdtvision/lib/TEditor.cc b/freebsdtvision/lib/TEditor.cc new file mode 100644 index 0000000..7644fcc --- /dev/null +++ b/freebsdtvision/lib/TEditor.cc @@ -0,0 +1,1144 @@ +/* + * TEditor.cc + * + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Sergio Sigala <sergio@sigala.it> + * Modified again by Dmitrij Korovkin <tkf@glasnet.ru> + */ + +#define Uses_TKeys +#define Uses_TEditor +#define Uses_TIndicator +#define Uses_TEvent +#define Uses_TScrollBar +#define Uses_TFindDialogRec +#define Uses_TReplaceDialogRec +#define Uses_opstream +#define Uses_ipstream +#include <tvision/tv.h> + +#include <ctype.h> +#include <string.h> + +/* + * SS: declarations fixed. See `asm.cc'. + */ +int countLines( void *buf, size_t count ); +size_t scan( const void *block, size_t size, const char *str ); +size_t iScan( const void *block, size_t size, const char *str ); + +inline int isWordChar( int ch ) +{ +#ifndef __UNPATCHED + return isalnum((uchar)ch) || ch == '_'; +// ^^^^^- correction for extended ASCII. +#else + return isalnum(ch) || ch == '_'; +#endif +} + +const ushort firstKeys[] = +{ + 37, + kbCtrlA, cmWordLeft, + kbCtrlC, cmPageDown, + kbCtrlD, cmCharRight, + kbCtrlE, cmLineUp, + kbCtrlF, cmWordRight, + kbCtrlG, cmDelChar, + kbCtrlH, cmBackSpace, + kbCtrlK, 0xFF02, + kbCtrlL, cmSearchAgain, + kbCtrlM, cmNewLine, + kbCtrlO, cmIndentMode, + kbCtrlQ, 0xFF01, + kbCtrlR, cmPageUp, + kbCtrlS, cmCharLeft, + kbCtrlT, cmDelWord, + kbCtrlU, cmUndo, + kbCtrlV, cmInsMode, + kbCtrlX, cmLineDown, + kbCtrlY, cmDelLine, + kbLeft, cmCharLeft, + kbRight, cmCharRight, + kbCtrlLeft, cmWordLeft, + kbCtrlRight, cmWordRight, + kbHome, cmLineStart, + kbEnd, cmLineEnd, + kbUp, cmLineUp, + kbDown, cmLineDown, + kbPgUp, cmPageUp, + kbPgDn, cmPageDown, + kbCtrlPgUp, cmTextStart, + kbCtrlPgDn, cmTextEnd, + kbIns, cmInsMode, + kbDel, cmDelChar, + kbShiftIns, cmPaste, + kbShiftDel, cmCut, + kbCtrlIns, cmCopy, + kbCtrlDel, cmClear +}; + +const ushort quickKeys[] = +{ 8, + 'A', cmReplace, + 'C', cmTextEnd, + 'D', cmLineEnd, + 'F', cmFind, + 'H', cmDelStart, + 'R', cmTextStart, + 'S', cmLineStart, + 'Y', cmDelEnd +}; + +const ushort blockKeys[] = +{ 5, + 'B', cmStartSelect, + 'C', cmPaste, + 'H', cmHideSelect, + 'K', cmCopy, + 'Y', cmCut +}; + +const ushort *keyMap[] = { firstKeys, quickKeys, blockKeys }; + +ushort defEditorDialog( int, ... ); + +ushort scanKeyMap( const void *keyMap, ushort keyCode ) +{ + register ushort *kM = (ushort *)keyMap; + uchar codeLow = keyCode & 0xff; + uchar codeHi = keyCode >> 8; + + int n; + + for (n = *kM++; n--; kM++) + { + uchar mapLow = *kM & 0xff; + uchar mapHi = *kM >> 8; + kM++; + ushort command = *kM; + + if ((mapLow == codeLow) && ((mapHi == 0) || (mapHi == codeHi))) + return command; + }; + return 0; +} + +#define cpEditor "\x06\x07" + +TEditor::TEditor( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + TIndicator *aIndicator, + uint aBufSize ) : + TView( bounds ), + hScrollBar( aHScrollBar ), + vScrollBar( aVScrollBar ), + indicator( aIndicator ), + bufSize( aBufSize ), + canUndo( True ), + selecting( False ), + overwrite( False ), + autoIndent( False ) , + lockCount( 0 ), + keyState( 0 ) +{ + growMode = gfGrowHiX | gfGrowHiY; + options |= ofSelectable; + eventMask = evMouseDown | evKeyDown | evCommand | evBroadcast; + showCursor(); + initBuffer(); + if( buffer != 0 ) + isValid = True; + else + { + editorDialog( edOutOfMemory ); + bufSize = 0; + isValid = False; + } + setBufLen(0); +} + +TEditor::~TEditor() +{ +} + +void TEditor::shutDown() +{ + doneBuffer(); + TView::shutDown(); +} + +void TEditor::changeBounds( const TRect& bounds ) +{ + setBounds(bounds); + delta.x = max(0, min(delta.x, limit.x - size.x)); + delta.y = max(0, min(delta.y, limit.y - size.y)); + update(ufView); +} + +uint TEditor::charPos( uint p, uint target ) +{ + uint pos = 0; + while( p < target ) + { + if( bufChar(p) == '\x9' ) + pos |= 7; + pos++; + p++; + } + return pos; +} + +uint TEditor::charPtr( uint p, uint target ) +{ + uint pos = 0; + /* SS: changed */ + while( (pos < target) && (p < bufLen) && (bufChar(p) != '\n') ) + { + if( bufChar(p) == '\x09' ) + pos |= 7; + pos++; + p++; + } + if( pos > target ) + p--; + return p; +} + +Boolean TEditor::clipCopy() +{ + Boolean res = False; + if( (clipboard != 0) && (clipboard != this) ) + { + res = clipboard->insertFrom(this); + selecting = False; + update(ufUpdate); + } + return res; +} + +void TEditor::clipCut() +{ + if( clipCopy() == True ) + deleteSelect(); +} + +void TEditor::clipPaste() +{ + if( (clipboard != 0) && (clipboard != this) ) + insertFrom(clipboard); +} + +void TEditor::convertEvent( TEvent& event ) +{ + if( event.what == evKeyDown ) + { + if( (event.keyDown.controlKeyState & kbShift) != 0 && + event.keyDown.charScan.scanCode >= 0x47 && + event.keyDown.charScan.scanCode <= 0x51 + ) + event.keyDown.charScan.charCode = 0; + + ushort key = event.keyDown.keyCode; + if( keyState != 0 ) + { + if( (key & 0xFF) >= 0x01 && (key & 0xFF) <= 0x1A ) + key += 0x40; + if( (key & 0xFF) >= 0x61 && (key & 0xFF) <= 0x7A ) + key -= 0x20; + } + key = scanKeyMap(keyMap[keyState], key); + keyState = 0; + if( key != 0 ) + if( (key & 0xFF00) == 0xFF00 ) + { + keyState = (key & 0xFF); + clearEvent(event); + } + else + { + event.what = evCommand; + event.message.command = key; + } + } +} + +Boolean TEditor::cursorVisible() +{ + return Boolean((curPos.y >= delta.y) && (curPos.y < delta.y + size.y)); +} + +void TEditor::deleteRange( uint startPtr, + uint endPtr, + Boolean delSelect + ) +{ + if( hasSelection() == True && delSelect == True ) + deleteSelect(); + else + { + setSelect(curPtr, endPtr, True); + deleteSelect(); + setSelect(startPtr, curPtr, False); + deleteSelect(); + } +} + +void TEditor::deleteSelect() +{ + insertText( 0, 0, False ); +} + +void TEditor::doneBuffer() +{ + delete buffer; +} + +void TEditor::doSearchReplace() +{ + int i; + do { + i = cmCancel; + if( search(findStr, editorFlags) == False ) + { + if( (editorFlags & (efReplaceAll | efDoReplace)) != + (efReplaceAll | efDoReplace) ) + editorDialog( edSearchFailed ); + } + else + if( (editorFlags & efDoReplace) != 0 ) + { + i = cmYes; + if( (editorFlags & efPromptOnReplace) != 0 ) + { + TPoint c = makeGlobal( cursor ); + i = editorDialog( edReplacePrompt, &c ); + } + if( i == cmYes ) + { + lock(); + insertText( replaceStr, strlen(replaceStr), False); + trackCursor(False); + unlock(); + } + } + } while( i != cmCancel && (editorFlags & efReplaceAll) != 0 ); +} + +void TEditor::doUpdate() +{ + if( updateFlags != 0 ) + { + setCursor(curPos.x - delta.x, curPos.y - delta.y); + if( (updateFlags & ufView) != 0 ) + drawView(); + else + if( (updateFlags & ufLine) != 0 ) + drawLines( curPos.y-delta.y, 1, lineStart(curPtr) ); + if( hScrollBar != 0 ) + hScrollBar->setParams(delta.x, 0, limit.x - size.x, size.x / 2, 1); + if( vScrollBar != 0 ) + vScrollBar->setParams(delta.y, 0, limit.y - size.y, size.y - 1, 1); + if( indicator != 0 ) + indicator->setValue(curPos, modified); + if( (state & sfActive) != 0 ) + updateCommands(); + updateFlags = 0; + } +} + +void TEditor::draw() +{ + if( drawLine != delta.y ) + { + drawPtr = lineMove( drawPtr, delta.y - drawLine ); + drawLine = delta.y; + } + drawLines( 0, size.y, drawPtr ); +} + +/*Added again as a such a plug for backward compatibility with an old +application*/ +#ifdef __RUSSIAN_LETTERS +static unsigned KoiTable[128] = +{ + 192, 193, 194, 195, 196, 197, 198, 199, /* 0x80 - 0x87 */ + 200, 201, 202, 203, 204, 205 ,206, 207, /* 0x88 - 0x8f */ + 208, 209, 210, 211, 212, 213, 214, 215, /* 0x90 - 0x97 */ + 216, 217, 218, 219, 220, 221, 222, 223, /* 0x98 - 0x9f */ + 240, 241, 242, 243, 244, 245, 246, 247, /* 0xa0 - 0xa7 */ + 248, 249, 250, 251, 252, 253, 254, 255, /* 0xa8 - 0xaf */ + 176, 177, 178, 179, 180, 181, 182, 183, /* 0xb0 - 0xb7 */ + 184, 185, 186, 187, 188, 189, 190, 191, /* 0xb8 - 0xbf */ + 238, 160, 161, 230, 164, 165, 228, 163, /* 0xc0 - 0xc7 */ + 229, 168, 169, 170, 171, 172, 173, 174, /* 0xc8 - 0xcf */ + 175, 239, 224, 225, 226, 227, 166, 162, /* 0xd0 - 0xd7 */ + 236, 235, 167, 232, 237, 233, 231, 234, /* 0xd8 - 0xdf */ + 158, 128, 129, 150, 132, 133, 148, 131, /* 0xe0 - 0xe7 */ + 149, 136, 137, 138, 139, 140, 141, 142, /* 0xe8 - 0xef */ + 143, 159, 144, 145, 146, 147, 134, 130, /* 0xf0 - 0xf7 */ + 156, 155, 135, 152, 157, 153, 151, 154 /* 0xf8 - 0xff */ +}; +#endif + +void TEditor::drawLines( int y, uint count, uint linePtr ) +{ + ushort color = getColor(0x0201); + while( count-- > 0 ) + { + ushort b[maxLineLength * 4]; + formatLine( b, linePtr, delta.x+size.x, color ); + +/*Added again as a such a plug for backward compatibility with an old +application*/ +#ifdef __RUSSIAN_LETTERS + ushort *p = &b[delta.x]; + for (int i = delta.x; i < size.x; i++, p++ ) + { + int code = *p & 0xff; /* character is in the low byte */ + + if (code > 0x7f) *p = (*p & 0xff00) | KoiTable[code - 0x80]; + } +#endif + writeBuf(0, y, size.x, 1, &b[delta.x]); + linePtr = nextLine(linePtr); + y++; + } +} + +void TEditor::find() +{ + TFindDialogRec findRec( findStr, editorFlags ); + if( editorDialog( edFind, &findRec ) != cmCancel ) + { + strcpy( findStr, findRec.find ); + editorFlags = findRec.options & ~efDoReplace; + doSearchReplace(); + } +} + +uint TEditor::getMousePtr( TPoint m ) +{ + TPoint mouse = makeLocal( m ); + mouse.x = max(0, min(mouse.x, size.x - 1)); + mouse.y = max(0, min(mouse.y, size.y - 1)); + return charPtr(lineMove(drawPtr, mouse.y + delta.y - drawLine), + mouse.x + delta.x); +} + +TPalette& TEditor::getPalette() const +{ + static TPalette palette( cpEditor, sizeof( cpEditor )-1 ); + return palette; +} + +void TEditor::checkScrollBar( const TEvent& event, + TScrollBar *p, + int& d + ) +{ + if( (event.message.infoPtr == p) && (p->value != d) ) + { + d = p->value; + update( ufView ); + } +} + +void TEditor::handleEvent( TEvent& event ) +{ + TView::handleEvent( event ); + + Boolean centerCursor = Boolean(!cursorVisible()); + uchar selectMode = 0; + + if( selecting == True || + (event.what & evMouse && (event.mouse.controlKeyState & kbShift) != 0) || + (event.what & evKeyboard && (event.keyDown.controlKeyState & kbShift ) != 0) + ) + selectMode = smExtend; + + convertEvent( event ); + + switch( event.what ) + { + + case evMouseDown: + if( event.mouse.eventFlags & meDoubleClick ) + selectMode |= smDouble; + + do { + lock(); + if( event.what == evMouseAuto ) + { + TPoint mouse = makeLocal( event.mouse.where ); + TPoint d = delta; + if( mouse.x < 0 ) + d.x--; + if( mouse.x >= size.x ) + d.x++; + if( mouse.y < 0 ) + d.y--; + if( mouse.y >= size.y ) + d.y++; + scrollTo(d.x, d.y); + } + setCurPtr(getMousePtr(event.mouse.where), selectMode); + selectMode |= smExtend; + unlock(); + } while( mouseEvent(event, evMouseMove + evMouseAuto) ); + break; + + case evKeyDown: + if( event.keyDown.charScan.charCode == 9 || + ( event.keyDown.charScan.charCode >= 32 && event.keyDown.charScan.charCode < 255 ) ) + { + lock(); + if( overwrite == True && hasSelection() == False ) + if( curPtr != lineEnd(curPtr) ) + selEnd = nextChar(curPtr); + insertText( &event.keyDown.charScan.charCode, 1, False); + trackCursor(centerCursor); + unlock(); + } + else + return; + break; + + case evCommand: + switch( event.message.command ) + { + case cmFind: + find(); + break; + case cmReplace: + replace(); + break; + case cmSearchAgain: + doSearchReplace(); + break; + default: + lock(); + switch( event.message.command ) + { + case cmCut: + clipCut(); + break; + case cmCopy: + clipCopy(); + break; + case cmPaste: + clipPaste(); + break; + case cmUndo: + undo(); + break; + case cmClear: + deleteSelect(); + break; + case cmCharLeft: + setCurPtr(prevChar(curPtr), selectMode); + break; + case cmCharRight: + setCurPtr(nextChar(curPtr), selectMode); + break; + case cmWordLeft: + setCurPtr(prevWord(curPtr), selectMode); + break; + case cmWordRight: + setCurPtr(nextWord(curPtr), selectMode); + break; + case cmLineStart: + setCurPtr(lineStart(curPtr), selectMode); + break; + case cmLineEnd: + setCurPtr(lineEnd(curPtr), selectMode); + break; + case cmLineUp: + setCurPtr(lineMove(curPtr, -1), selectMode); + break; + case cmLineDown: + setCurPtr(lineMove(curPtr, 1), selectMode); + break; + case cmPageUp: + setCurPtr(lineMove(curPtr, -(size.y-1)), selectMode); + break; + case cmPageDown: + setCurPtr(lineMove(curPtr, size.y-1), selectMode); + break; + case cmTextStart: + setCurPtr(0, selectMode); + break; + case cmTextEnd: + setCurPtr(bufLen, selectMode); + break; + case cmNewLine: + newLine(); + break; + case cmBackSpace: + deleteRange(prevChar(curPtr), curPtr, True); + break; + case cmDelChar: + deleteRange(curPtr, nextChar(curPtr), True); + break; + case cmDelWord: + deleteRange(curPtr, nextWord(curPtr), False); + break; + case cmDelStart: + deleteRange(lineStart(curPtr), curPtr, False); + break; + case cmDelEnd: + deleteRange(curPtr, lineEnd(curPtr), False); + break; + case cmDelLine: + deleteRange(lineStart(curPtr), nextLine(curPtr), False); + break; + case cmInsMode: + toggleInsMode(); + break; + case cmStartSelect: + startSelect(); + break; + case cmHideSelect: + hideSelect(); + break; + case cmIndentMode: + autoIndent = Boolean(!autoIndent); + break; + default: + unlock(); + return; + } + trackCursor(centerCursor); + unlock(); + break; + } +#ifndef __UNPATCHED + break; +#endif + case evBroadcast: + switch( event.message.command ) + { + case cmScrollBarChanged: + if ((event.message.infoPtr == hScrollBar) || + (event.message.infoPtr == vScrollBar)) + { + checkScrollBar( event, hScrollBar, delta.x ); + checkScrollBar( event, vScrollBar, delta.y ); + } + else + return; + break; + default: + return; + } + } + clearEvent(event); +} + +Boolean TEditor::hasSelection() +{ + return Boolean(selStart != selEnd); +} + +void TEditor::hideSelect() +{ + selecting = False; + setSelect(curPtr, curPtr, False); +} + +void TEditor::initBuffer() +{ + buffer = new char[bufSize]; +} + +Boolean TEditor::insertBuffer( char *p, + uint offset, + uint length, + Boolean allowUndo, + Boolean selectText + ) +{ + selecting = False; + uint selLen = selEnd - selStart; + if( selLen == 0 && length == 0 ) + return True; + + uint delLen = 0; + if( allowUndo == True ) + if( curPtr == selStart ) + delLen = selLen; + else + if( selLen > insCount ) + delLen = selLen - insCount; + + uint newSize = uint(bufLen + delCount - selLen + delLen) + length; + + if( newSize > bufLen + delCount && setBufSize(newSize) == False ) + { + editorDialog( edOutOfMemory ); + selEnd = selStart; + return False; + } + + uint selLines = countLines( &buffer[bufPtr(selStart)], selLen ); + if( curPtr == selEnd ) + { + if( allowUndo == True ) + { + if( delLen > 0 ) + memmove( + &buffer[curPtr + gapLen - delCount - delLen], + &buffer[selStart], + delLen + ); + insCount -= selLen - delLen; + } + curPtr = selStart; + curPos.y -= selLines; + } + if( delta.y > curPos.y ) + { + delta.y -= selLines; + if( delta.y < curPos.y ) + delta.y = curPos.y; + } + + if( length > 0 ) + memmove( + &buffer[curPtr], + &p[offset], + length + ); + + uint lines = countLines( &buffer[curPtr], length ); + curPtr += length; + curPos.y += lines; + drawLine = curPos.y; + drawPtr = lineStart(curPtr); + curPos.x = charPos(drawPtr, curPtr); + if( selectText == False ) + selStart = curPtr; + selEnd = curPtr; + bufLen += length - selLen; + gapLen -= length - selLen; + if( allowUndo == True ) + { + delCount += delLen; + insCount += length; + } + limit.y += lines - selLines; + delta.y = max(0, min(delta.y, limit.y - size.y)); + if( isClipboard() == False ) + modified = True; + setBufSize(bufLen + delCount); + if( selLines == 0 && lines == 0 ) + update(ufLine); + else + update(ufView); + return True; +} + +Boolean TEditor::insertFrom( TEditor *editor ) +{ + uint pt = editor->bufPtr(editor->selStart); + return insertBuffer( editor->buffer, + pt, + editor->selEnd - editor->selStart, + canUndo, + isClipboard() + ); +} + +Boolean TEditor::insertText( const void *text, uint length, + Boolean selectText ) +{ + return insertBuffer( (char *)text, 0, length, canUndo, selectText); +} + +Boolean TEditor::isClipboard() +{ + return Boolean(clipboard == this); +} + +uint TEditor::lineMove( uint p, int count ) +{ + uint i = p; + p = lineStart(p); + uint pos = charPos(p, i); + while( count != 0 ) + { + i = p; + if( count < 0 ) + { + p = prevLine(p); + count++; + } + else + { + p = nextLine(p); + count--; + } + } + if( p != i ) + p = charPtr(p, pos); + return p; +} + +void TEditor::lock() +{ + lockCount++; +} + +void TEditor::newLine() +{ + /* SS: changed */ + const char nl[] = "\n"; + uint p = lineStart(curPtr); + uint i = p; + while( i < curPtr && + ( (buffer[i] == ' ') || (buffer[i] == '\x9')) + ) + i++; + insertText(nl, 1, False); + if( autoIndent == True ) + insertText( &buffer[p], i - p, False); +} + +uint TEditor::nextLine( uint p ) +{ + return nextChar(lineEnd(p)); +} + +uint TEditor::nextWord( uint p ) +{ + while( p < bufLen && isWordChar(bufChar(p)) != 0 ) + p = nextChar(p); + while( p < bufLen && isWordChar(bufChar(p)) == 0 ) + p = nextChar(p); + return p; +} + +uint TEditor::prevLine( uint p ) +{ + return lineStart(prevChar(p)); +} + +uint TEditor::prevWord( uint p ) +{ + while( p > 0 && isWordChar(bufChar(prevChar(p))) == 0 ) + p = prevChar(p); + while( p > 0 && isWordChar(bufChar(prevChar(p))) != 0 ) + p = prevChar(p); + return p; +} + +void TEditor::replace() +{ + TReplaceDialogRec replaceRec( findStr, replaceStr, editorFlags ); + if( editorDialog( edReplace, &replaceRec ) != cmCancel ) + { + strcpy( findStr, replaceRec.find ); + strcpy( replaceStr, replaceRec.replace ); + editorFlags = replaceRec.options | efDoReplace; + doSearchReplace(); + } + +} + +void TEditor::scrollTo( int x, int y ) +{ + x = max(0, min(x, limit.x - size.x)); + y = max(0, min(y, limit.y - size.y)); + if( x != delta.x || y != delta.y ) + { + delta.x = x; + delta.y = y; + update(ufView); + } +} + +Boolean TEditor::search( const char *findStr, ushort opts ) +{ + ulong pos = curPtr; + ulong i; + do { + if( (opts & efCaseSensitive) != 0 ) + i = scan( &buffer[bufPtr(pos)], bufLen - pos, findStr); + else + i = iScan( &buffer[bufPtr(pos)], bufLen - pos, findStr); + + if( i != sfSearchFailed ) + { + i += pos; + if( (opts & efWholeWordsOnly) == 0 || + !( + ( i != 0 && isWordChar(bufChar(i - 1)) != 0 ) || + ( i + strlen(findStr) != bufLen && + isWordChar(bufChar(i + strlen(findStr))) + ) + )) + { + lock(); + setSelect(i, i + strlen(findStr), False); + trackCursor(Boolean(!cursorVisible())); + unlock(); + return True; + } + else + pos = i + 1; + } + } while( i != sfSearchFailed ); + return False; +} + +void TEditor::setBufLen( uint length ) +{ + bufLen = length; + gapLen = bufSize - length; + selStart = 0; + selEnd = 0; + curPtr = 0; + delta.x = 0; + delta.y = 0; + curPos = delta; + limit.x = maxLineLength; + limit.y = countLines( &buffer[gapLen], bufLen ) + 1; + drawLine = 0; + drawPtr = 0; + delCount = 0; + insCount = 0; + modified = False; + update(ufView); +} + +Boolean TEditor::setBufSize( uint newSize ) +{ + return Boolean(newSize <= bufSize); +} + +void TEditor::setCmdState( ushort command, Boolean enable ) +{ + TCommandSet s; + s += command; + if( enable == True && (state & sfActive) != 0 ) + enableCommands(s); + else + disableCommands(s); +} + +void TEditor::setCurPtr( uint p, uchar selectMode ) +{ + uint anchor; + if( (selectMode & smExtend) == 0 ) + anchor = p; + else if( curPtr == selStart ) + anchor = selEnd; + else + anchor = selStart; + + if( p < anchor ) + { + if( (selectMode & smDouble) != 0 ) + { + p = prevLine(nextLine(p)); + anchor = nextLine(prevLine(anchor)); + } + setSelect(p, anchor, True); + } + else + { + if( (selectMode & smDouble) != 0 ) + { + p = nextLine(p); + anchor = prevLine(nextLine(anchor)); + } + setSelect(anchor, p, False); + } +} + +void TEditor::setSelect( uint newStart, uint newEnd, Boolean curStart ) +{ + uint p; + if( curStart != 0 ) + p = newStart; + else + p = newEnd; + + uchar flags = ufUpdate; + + if( newStart != selStart || newEnd != selEnd ) + if( newStart != newEnd || selStart != selEnd ) + flags = ufView; + + if( p != curPtr ) + { + if( p > curPtr ) + { + uint l = p - curPtr; + memmove( &buffer[curPtr], &buffer[curPtr + gapLen], l); + curPos.y += countLines(&buffer[curPtr], l); + curPtr = p; + } + else + { + uint l = curPtr - p; + curPtr = p; + curPos.y -= countLines(&buffer[curPtr], l); + memmove( &buffer[curPtr + gapLen], &buffer[curPtr], l); + } + drawLine = curPos.y; + drawPtr = lineStart(p); + curPos.x = charPos(drawPtr, p); + delCount = 0; + insCount = 0; + setBufSize(bufLen); + } + selStart = newStart; + selEnd = newEnd; + update(flags); +} + +void TEditor::setState( ushort aState, Boolean enable ) +{ + TView::setState(aState, enable); + switch( aState ) + { + case sfActive: + if( hScrollBar != 0 ) + hScrollBar->setState(sfVisible, enable); + if( vScrollBar != 0 ) + vScrollBar->setState(sfVisible, enable); + if( indicator != 0 ) + indicator->setState(sfVisible, enable); + updateCommands(); + break; + + case sfExposed: + if( enable == True ) + unlock(); + } +} + +void TEditor::startSelect() +{ + hideSelect(); + selecting = True; +} + +void TEditor::toggleInsMode() +{ + overwrite = Boolean(!overwrite); + setState(sfCursorIns, Boolean(!getState(sfCursorIns))); +} + +void TEditor::trackCursor( Boolean center ) +{ + if( center == True ) + scrollTo( curPos.x - size.x + 1, curPos.y - size.y / 2); + else + scrollTo( max(curPos.x - size.x + 1, min(delta.x, curPos.x)), + max(curPos.y - size.y + 1, min(delta.y, curPos.y))); +} + +void TEditor::undo() +{ + if( delCount != 0 || insCount != 0 ) + { + selStart = curPtr - insCount; + selEnd = curPtr; + ushort length = delCount; + delCount = 0; + insCount = 0; + insertBuffer(buffer, curPtr + gapLen - length, length, False, True); + } +} + +void TEditor::unlock() +{ + if( lockCount > 0 ) + { + lockCount--; + if( lockCount == 0 ) + doUpdate(); + } +} + +void TEditor::update( uchar aFlags ) +{ + updateFlags |= aFlags; + if( lockCount == 0 ) + doUpdate(); +} + +void TEditor::updateCommands() +{ + setCmdState( cmUndo, Boolean( delCount != 0 || insCount != 0 ) ); + if( isClipboard() == False ) + { + setCmdState(cmCut, hasSelection()); + setCmdState(cmCopy, hasSelection()); + setCmdState(cmPaste, + Boolean(clipboard != 0 && (clipboard->hasSelection())) ); + } + setCmdState(cmClear, hasSelection()); + setCmdState(cmFind, True); + setCmdState(cmReplace, True); + setCmdState(cmSearchAgain, True); +} + +Boolean TEditor::valid( ushort ) +{ + return isValid; +} + +#if !defined(NO_STREAMABLE) + +void TEditor::write( opstream& os ) +{ + TView::write( os ); + os << hScrollBar << vScrollBar << indicator + << bufSize << (int)canUndo; +} + +void *TEditor::read( ipstream& is ) +{ + TView::read( is ); + int temp; + is >> hScrollBar >> vScrollBar >> indicator + >> bufSize >> temp; + canUndo = Boolean(temp); + selecting = False; + overwrite = False; + autoIndent = False; + lockCount = 0; + keyState = 0; + initBuffer(); + if( buffer != 0 ) + isValid = True; + else + { + TEditor::editorDialog( edOutOfMemory, 0 ); + bufSize = 0; + } + lockCount = 0; + lock(); + setBufLen( 0 ); + return this; +} + +TStreamable *TEditor::build() +{ + return new TEditor( streamableInit ); +} + +TEditor::TEditor( StreamableInit ) : TView( streamableInit ) +{ +} + +#endif |