home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / tvision / wrdwrp / teditor1.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-10  |  19.7 KB  |  685 lines

  1. /*------------------------------------------------------------*/
  2. /* filename - teditor1.cpp                                    */
  3. /*                                                            */
  4. /* function(s)                                                */
  5. /*            TEditor member functions                        */
  6. /*------------------------------------------------------------*/
  7.  
  8. /*------------------------------------------------------------*/
  9. /*                                                            */
  10. /*    Turbo Vision -  Version 1.0                             */
  11. /*                                                            */
  12. /*                                                            */
  13. /*    Copyright (c) 1991 by Borland International             */
  14. /*    All Rights Reserved.                                    */
  15. /*                                                            */
  16. /*------------------------------------------------------------*/
  17.  
  18. //  Primatech Modification History:
  19. //
  20. //      11-07-91 JLS  Changed constructor to initialize new data fields
  21. //      11-26-91 JLS  Added break after evCommand case in handleEvent()
  22. //      12-02-91 JLS  Changed cmDelChar processing so that a soft return is
  23. //                      not deleted, just skipped.
  24.  
  25.  
  26. #define Uses_TRect
  27. #define Uses_TKeys
  28. #define Uses_TEditor
  29. #define Uses_TIndicator
  30. #define Uses_TEvent
  31. #define Uses_TScrollBar
  32. #define Uses_TFindDialogRec
  33. #define Uses_TReplaceDialogRec
  34. #define Uses_opstream
  35. #define Uses_ipstream
  36. #include <tv.h>
  37.  
  38. #if !defined( __STRING_H )
  39. #include <string.h>
  40. #endif  // __STRING_H
  41.  
  42. #if !defined( __CTYPE_H )
  43. #include <ctype.h>
  44. #endif  // __CTYPE_H
  45.  
  46. #if !defined( __DOS_H )
  47. #include <Dos.h>
  48. #endif  // __DOS_H
  49.  
  50. inline int isWordChar( int ch )
  51. {
  52.     return isalnum(ch) || ch == '_';
  53. }
  54.  
  55. const ushort firstKeys[] =
  56. {
  57.     38,
  58.     kbCtrlA, cmWordLeft,
  59.     kbCtrlC, cmPageDown,
  60.     kbCtrlD, cmCharRight,
  61.     kbCtrlE, cmLineUp,
  62.     kbCtrlF, cmWordRight,
  63.     kbCtrlG, cmDelChar,
  64.     kbCtrlH, cmBackSpace,
  65.     kbCtrlK, 0xFF02,
  66.     kbCtrlL, cmSearchAgain,
  67.     kbCtrlM, cmNewLine,
  68.     kbCtrlO, cmIndentMode,
  69.     kbCtrlQ, 0xFF01,
  70.     kbCtrlR, cmPageUp,
  71.     kbCtrlS, cmCharLeft,
  72.     kbCtrlT, cmDelWord,
  73.     kbCtrlU, cmUndo,
  74.     kbCtrlV, cmInsMode,
  75.     kbCtrlW, cmToggleWrap,
  76.     kbCtrlX, cmLineDown,
  77.     kbCtrlY, cmDelLine,
  78.     kbLeft, cmCharLeft,
  79.     kbRight, cmCharRight,
  80.     kbCtrlLeft, cmWordLeft,
  81.     kbCtrlRight, cmWordRight,
  82.     kbHome, cmLineStart,
  83.     kbEnd, cmLineEnd,
  84.     kbUp, cmLineUp,
  85.     kbDown, cmLineDown,
  86.     kbPgUp, cmPageUp,
  87.     kbPgDn, cmPageDown,
  88.     kbCtrlPgUp, cmTextStart,
  89.     kbCtrlPgDn, cmTextEnd,
  90.     kbCtrlHome, cmWindowStart,
  91.     kbCtrlEnd, cmWindowEnd,
  92.     kbIns, cmInsMode,
  93.     kbDel, cmDelChar,
  94.     kbShiftIns, cmPaste,
  95.     kbShiftDel, cmCut,
  96.     kbCtrlIns, cmCopy,
  97.     kbCtrlDel, cmClear
  98. };
  99.  
  100. const ushort quickKeys[] =
  101. {   8,
  102.     'A', cmReplace,
  103.     'C', cmTextEnd,
  104.     'D', cmLineEnd,
  105.     'F', cmFind,
  106.     'H', cmDelStart,
  107.     'R', cmTextStart,
  108.     'S', cmLineStart,
  109.     'Y', cmDelEnd
  110. };
  111.  
  112. const ushort blockKeys[] =
  113. {   5,
  114.     'B', cmStartSelect,
  115.     'C', cmPaste,
  116.     'H', cmHideSelect,
  117.     'K', cmCopy,
  118.     'Y', cmCut
  119. };
  120.  
  121. const ushort *keyMap[] = { firstKeys, quickKeys, blockKeys };
  122.  
  123. ushort defEditorDialog( int, ... );
  124.  
  125. #pragma warn -asc
  126.  
  127. ushort scanKeyMap( const void *keyMap, int keyCode )
  128. {
  129. asm {
  130.     PUSH DS
  131.     LDS SI,keyMap
  132.     MOV DX,keyCode
  133.     CLD
  134.     LODSW
  135.     MOV CX,AX
  136.     }
  137. __1:
  138. asm {
  139.     LODSW
  140.     MOV BX,AX
  141.     LODSW
  142.     CMP BL,DL
  143.     JNE __3
  144.     OR  BH,BH
  145.     JE  __4
  146.     CMP BH,DH
  147.     JE  __4
  148.     }
  149. __3:
  150. asm {
  151.     LOOP    __1
  152.     XOR AX,AX
  153.     }
  154. __4:
  155. asm POP DS
  156.     return _AX;
  157. }
  158.  
  159. #pragma warn .asc
  160.  
  161. #define cpEditor    "\x06\x07"
  162.  
  163.  
  164. TEditor::TEditor( const TRect& bounds,
  165.                   TScrollBar *aHScrollBar,
  166.                   TScrollBar *aVScrollBar,
  167.                   TIndicator *aIndicator,
  168.                   ushort aBufSize ) :
  169.     TView( bounds ),
  170.     hScrollBar( aHScrollBar ),
  171.     vScrollBar( aVScrollBar ),
  172.     indicator( aIndicator ),
  173.     bufSize( aBufSize ),
  174.     canUndo( True ),
  175.     selecting( False ),
  176.     overwrite( False ),
  177.     autoIndent( False ),
  178.     lockCount( 0 ),
  179.     keyState( 0 ),
  180.     wordWrap( False ),
  181.     autosizeMargin( False ),
  182.     rMargin( bounds.b.x - bounds.a.x - 1),
  183.     tabSize( 4 )
  184. {
  185.     growMode = gfGrowHiX | gfGrowHiY;
  186.     options |= ofSelectable;
  187.     eventMask = evMouseDown | evKeyDown | evCommand | evBroadcast;
  188.     showCursor();
  189.     initBuffer();
  190.     if( buffer != 0 )
  191.         isValid = True;
  192.     else
  193.         {
  194.         editorDialog( edOutOfMemory );
  195.         bufSize = 0;
  196.         isValid = False;
  197.         }
  198.     setBufLen(0);
  199. }
  200.  
  201. TEditor::~TEditor()
  202. {
  203. }
  204.  
  205. void TEditor::shutDown()
  206. {
  207.     doneBuffer();
  208.     TView::shutDown();
  209. }
  210.  
  211. void TEditor::changeBounds( const TRect& bounds )
  212. {
  213.     lock();
  214.     setBounds(bounds);
  215.     delta.x = max(0, min(delta.x, limit.x - size.x));
  216.     delta.y = max(0, min(delta.y, limit.y - size.y));
  217.  
  218.     if (autosizeMargin) {
  219.         ushort oldMargin = rMargin;
  220.         rMargin = bounds.b.x - bounds.a.x - 1;
  221.         if (wordWrap && oldMargin != rMargin) {
  222.             wordWrapBuffer(0, bufLen);
  223.         }
  224.     }
  225.  
  226.     update(ufView);
  227.  
  228.     unlock();
  229. }
  230.  
  231. // 11-11-91 JLS Added code for variable tab size
  232. int TEditor::charPos( ushort p, ushort target )
  233. {
  234.     int pos = 0;
  235.     while( p < target )
  236.         {
  237.         if( bufChar(p) == '\t' )
  238.             {
  239.             pos += (tabSize - (pos % tabSize));
  240.             }
  241.         else
  242.             pos++;
  243.  
  244.         p++;
  245.         }
  246.     return pos;
  247. }
  248.  
  249.  
  250. // 11-11-91 JLS Added code for variable tab size
  251. ushort TEditor::charPtr( ushort p, int target )
  252. {
  253.     int pos = 0;
  254.     char ch;
  255.     
  256.     while( (pos < target) && (p < bufLen) && (ch = bufChar(p)) != '\x0D' )
  257.         {
  258.         if( ch == '\t' )      // TAB
  259.             {
  260.             pos += (tabSize - (pos % tabSize));
  261.             }
  262.         else
  263.             pos++;
  264.  
  265.         p++;
  266.         }
  267.  
  268.     if( pos > target )
  269.         p--;
  270.  
  271.     return p;
  272. }
  273.  
  274. Boolean TEditor::clipCopy()
  275. {
  276.     Boolean res = False;
  277.     if( (clipboard != 0) && (clipboard != this) )
  278.         {
  279.         res = clipboard->insertFrom(this);
  280.         selecting = False;
  281.         update(ufUpdate);
  282.         }
  283.     return res;
  284. }
  285.  
  286. void TEditor::clipCut()
  287. {
  288.     if( clipCopy() == True )
  289.         deleteSelect();
  290. }
  291.  
  292. void TEditor::clipPaste()
  293. {
  294.     if( (clipboard != 0) && (clipboard != this) )
  295.         insertFrom(clipboard);
  296. }
  297.  
  298. void TEditor::convertEvent( TEvent& event )
  299. {
  300.     if( event.what == evKeyDown )
  301.         {
  302.         if( (event.shiftState & (kbRightShift | kbLeftShift)) != 0 &&
  303.             event.keyDown.charScan.scanCode >= 0x47 &&
  304.             event.keyDown.charScan.scanCode <= 0x51
  305.           )
  306.             event.keyDown.charScan.charCode = 0;
  307.  
  308.         ushort key = event.keyDown.keyCode;
  309.         if( keyState != 0 )
  310.             {
  311.             if( (key & 0xFF) >= 0x01 && (key & 0xFF) <= 0x1A )
  312.                 key += 0x40;
  313.             if( (key & 0xFF) >= 0x61 && (key & 0xFF) <= 0x7A )
  314.                 key -= 0x20;
  315.             }
  316.         key = scanKeyMap(keyMap[keyState], key);
  317.         keyState = 0;
  318.         if( key != 0 )
  319.             if( (key & 0xFF00) == 0xFF00 )
  320.                 {
  321.                 keyState = (key & 0xFF);
  322.                 clearEvent(event);
  323.                 }
  324.             else
  325.                 {
  326.                 event.what = evCommand;
  327.                 event.message.command = key;
  328.                 }
  329.         }
  330. }
  331.  
  332. Boolean TEditor::cursorVisible()
  333. {
  334.   return Boolean((curPos.y >= delta.y) && (curPos.y < delta.y + size.y));
  335. }
  336.  
  337. void TEditor::deleteRange( ushort startPtr,
  338.                            ushort endPtr,
  339.                            Boolean delSelect
  340.                          )
  341. {
  342.     if( hasSelection() == True && delSelect == True )
  343.         deleteSelect();
  344.     else
  345.         {
  346.         Boolean realWordWrap = wordWrap;
  347.         wordWrap = False;
  348.         setSelect(curPtr, endPtr, True);
  349.         deleteSelect();
  350.         wordWrap = realWordWrap;
  351.  
  352.         setSelect(startPtr, curPtr, False);
  353.         deleteSelect(wordWrap);
  354.         }
  355. }
  356.  
  357. void TEditor::doneBuffer()
  358. {
  359.     delete buffer;
  360. }
  361.  
  362. #pragma warn -stv
  363. void TEditor::doSearchReplace()
  364. {
  365.     int i;
  366.     do  {
  367.         i = cmCancel;
  368.         if( search(findStr, editorFlags) == False )
  369.             {
  370.             if( (editorFlags & (efReplaceAll | efDoReplace)) !=
  371.                 (efReplaceAll | efDoReplace) )
  372.                     editorDialog( edSearchFailed );
  373.             }
  374.         else
  375.             if( (editorFlags & efDoReplace) != 0 )
  376.                 {
  377.                 i = cmYes;
  378.                 if( (editorFlags & efPromptOnReplace) != 0 )
  379.                     {
  380.                     TPoint c = makeGlobal( cursor );
  381.                     i = editorDialog( edReplacePrompt, &c );
  382.                     }
  383.                 if( i == cmYes )
  384.                     {
  385.                     lock();
  386.                     insertText( replaceStr, strlen(replaceStr), False);
  387.                     trackCursor(False);
  388.                     unlock();
  389.                     }
  390.                 }
  391.         } while( i != cmCancel && (editorFlags & efReplaceAll) != 0 );
  392. }
  393. #pragma warn .stv
  394.  
  395. void TEditor::doUpdate()
  396. {
  397.     if( updateFlags != 0 )
  398.         {
  399.         setCursor(curPos.x - delta.x, curPos.y - delta.y);
  400.         if( (updateFlags & ufView) != 0 )
  401.             drawView();
  402.         else
  403.             if( (updateFlags & ufLine) != 0 )
  404.                 drawLines( curPos.y-delta.y, 1, lineStart(curPtr) );
  405.         if( hScrollBar != 0 )
  406.             hScrollBar->setParams(delta.x, 0, limit.x - size.x, size.x / 2, 1);
  407.         if( vScrollBar != 0 )
  408.             vScrollBar->setParams(delta.y, 0, limit.y - size.y, size.y - 1, 1);
  409.         if( indicator != 0 )
  410.             indicator->setValue(curPos, modified);
  411.         if( (state & sfActive) != 0 )
  412.             updateCommands();
  413.         updateFlags = 0;
  414.         }
  415. }
  416.  
  417. void TEditor::draw()
  418. {
  419.     if( drawLine != delta.y )
  420.         {
  421.         drawPtr = lineMove( drawPtr, delta.y - drawLine );
  422.         drawLine = delta.y;
  423.         }
  424.     drawLines( 0, size.y, drawPtr );
  425. }
  426.  
  427. void TEditor::drawLines( int y, int count, ushort linePtr )
  428. {
  429.     ushort color = getColor(0x0201);
  430.     while( count-- > 0 )
  431.         {
  432.         ushort b[maxLineLength];
  433.         formatLine( b, linePtr, delta.x+size.x, color );
  434.         writeBuf(0, y, size.x, 1, &b[delta.x]);
  435.         linePtr = nextLine(linePtr);
  436.         y++;
  437.         }
  438. }
  439.  
  440. void TEditor::find()
  441. {
  442.     TFindDialogRec findRec( findStr, editorFlags );
  443.     if( editorDialog( edFind, &findRec ) != cmCancel )
  444.         {
  445.         strcpy( findStr, findRec.find );
  446.         editorFlags = findRec.options & ~efDoReplace;
  447.         doSearchReplace();
  448.         }
  449. }
  450.  
  451. #pragma warn -stv
  452. ushort TEditor::getMousePtr( TPoint m )
  453. {
  454.     TPoint mouse = makeLocal( m );
  455.     mouse.x = max(0, min(mouse.x, size.x - 1));
  456.     mouse.y = max(0, min(mouse.y, size.y - 1));
  457.     return charPtr(lineMove(drawPtr, mouse.y + delta.y - drawLine),
  458.         mouse.x + delta.x);
  459. }
  460. #pragma warn .stv
  461.  
  462. TPalette& TEditor::getPalette() const
  463. {
  464.     static TPalette palette( cpEditor, sizeof( cpEditor )-1 );
  465.     return palette;
  466. }
  467.  
  468. void TEditor::checkScrollBar( const TEvent& event,
  469.                               TScrollBar *p,
  470.                               int& d
  471.                             )
  472. {
  473.     if( (event.message.infoPtr == p) && (p->value != d) )
  474.         {
  475.         d = p->value;
  476.         update( ufView );
  477.         }
  478. }
  479.  
  480. #pragma warn -stv
  481. void TEditor::handleEvent( TEvent& event )
  482. {
  483.     TView::handleEvent( event );
  484.     convertEvent( event );
  485.     Boolean centerCursor = Boolean(!cursorVisible());
  486.     uchar selectMode = 0;
  487.  
  488.     if( selecting == True || (event.shiftState & (kbRightShift | kbLeftShift)) != 0 )
  489.         selectMode = smExtend;
  490.  
  491.     switch( event.what )
  492.         {
  493.  
  494.         case evMouseDown:
  495.             if( event.mouse.doubleClick == True )
  496.                 selectMode |= smDouble;
  497.  
  498.             do  {
  499.                 lock();
  500.                 if( event.what == evMouseAuto )
  501.                     {
  502.                     TPoint mouse = makeLocal( event.mouse.where );
  503.                     TPoint d = delta;
  504.                     if( mouse.x < 0 )
  505.                         d.x--;
  506.                     if( mouse.x >= size.x )
  507.                         d.x++;
  508.                     if( mouse.y < 0 )
  509.                         d.y--;
  510.                     if( mouse.y >= size.y )
  511.                         d.y++;
  512.                     scrollTo(d.x, d.y);
  513.                     }
  514.                 setCurPtr(getMousePtr(event.mouse.where), selectMode);
  515.                 selectMode |= smExtend;
  516.                 unlock();
  517.                 } while( mouseEvent(event, evMouseMove + evMouseAuto) );
  518.             break;
  519.  
  520.         case evKeyDown:
  521.             if( event.keyDown.charScan.charCode == 9 ||
  522.                 ( event.keyDown.charScan.charCode >= 32 && event.keyDown.charScan.charCode < 255 ) )
  523.                     {
  524.                     lock();
  525.                     if( overwrite == True && hasSelection() == False )
  526.                         if( curPtr != lineEnd(curPtr) )
  527.                             selEnd = nextChar(curPtr);
  528.                     insertText( &event.keyDown.charScan.charCode, 1, False);
  529.                     trackCursor(centerCursor);
  530.                     unlock();
  531.                     }
  532.             else
  533.                 return;
  534.             break;
  535.  
  536.         case evCommand:
  537.             switch( event.message.command )
  538.                 {
  539.                 case cmFind:
  540.                     find();
  541.                     break;
  542.                 case cmReplace:
  543.                     replace();
  544.                     break;
  545.                 case cmSearchAgain:
  546.                 case cmReplaceAgain:
  547.                     doSearchReplace();
  548.                     break;
  549.                 default:
  550.                     lock();
  551.                     switch( event.message.command )
  552.                         {
  553.                         case cmCut:
  554.                             clipCut();
  555.                             break;
  556.                         case cmCopy:
  557.                             clipCopy();
  558.                             break;
  559.                         case cmPaste:
  560.                             clipPaste();
  561.                             break;
  562.                         case cmUndo:
  563.                             undo();
  564.                             break;
  565.                         case cmClear:
  566.                             deleteSelect();
  567.                             break;
  568.                         case cmCharLeft:
  569.                             setCurPtr(prevChar(curPtr), selectMode);
  570.                             break;
  571.                         case cmCharRight:
  572.                             setCurPtr(nextChar(curPtr), selectMode);
  573.                             break;
  574.                         case cmWordLeft:
  575.                             setCurPtr(prevWord(curPtr), selectMode);
  576.                             break;
  577.                         case cmWordRight:
  578.                             setCurPtr(nextWord(curPtr), selectMode);
  579.                             break;
  580.                         case cmLineStart:
  581.                             setCurPtr(lineStart(curPtr), selectMode);
  582.                             break;
  583.                         case cmLineEnd:
  584.                             setCurPtr(lineEnd(curPtr), selectMode);
  585.                             break;
  586.                         case cmLineUp:
  587.                             setCurPtr(lineMove(curPtr, -1), selectMode);
  588.                             break;
  589.                         case cmLineDown:
  590.                             setCurPtr(lineMove(curPtr, 1), selectMode);
  591.                             break;
  592.                         case cmPageUp:
  593.                             setCurPtr(lineMove(curPtr, -(size.y-1)), selectMode);
  594.                             break;
  595.                         case cmPageDown:
  596.                             setCurPtr(lineMove(curPtr, size.y-1), selectMode);
  597.                             break;
  598.                         case cmTextStart:
  599.                             setCurPtr(0, selectMode);
  600.                             break;
  601.                         case cmTextEnd:
  602.                             setCurPtr(bufLen, selectMode);
  603.                             break;
  604.                         case cmWindowStart:
  605.                             setCurPtr(0, selectMode);       // ?????
  606.                             break;
  607.                         case cmWindowEnd:
  608.                             setCurPtr(bufLen, selectMode);  // ?????
  609.                             break;
  610.                         case cmNewLine:
  611.                             newLine();
  612.                             break;
  613.                         case cmBackSpace:
  614.                             deleteRange(prevChar(curPtr), curPtr, True);
  615.                             break;
  616.                         case cmDelChar:
  617.                             // If sitting on soft return, don't delete it. Hard returns can be deleted
  618.                             if (buffer[curPtr+gapLen] == '\r' && buffer[curPtr+gapLen+1] != '\n')
  619.                                 setCurPtr(nextChar(curPtr), selectMode);
  620.                             else
  621.                                 deleteRange(curPtr, nextChar(curPtr), True);
  622.                             break;
  623.                         case cmDelWord:
  624.                             deleteRange(curPtr, nextWord(curPtr), False);
  625.                             break;
  626.                         case cmDelStart:
  627.                             deleteRange(lineStart(curPtr), curPtr, False);
  628.                             break;
  629.                         case cmDelEnd:
  630.                             deleteRange(curPtr, lineEnd(curPtr), False);
  631.                             break;
  632.                         case cmDelLine:
  633.                             deleteRange(lineStart(curPtr), nextLine(curPtr), False);
  634.                             break;
  635.                         case cmInsMode:
  636.                             toggleInsMode();
  637.                             break;
  638.                         case cmStartSelect:
  639.                             startSelect();
  640.                             break;
  641.                         case cmHideSelect:
  642.                             hideSelect();
  643.                             break;
  644.                         case cmIndentMode:
  645.                             autoIndent = Boolean(!autoIndent);
  646.                             break;
  647.                         case cmToggleWrap:
  648.                             if (wordWrap)
  649.                                 wordWrap = False;
  650.                             else
  651.                                 {
  652.                                 wordWrap = True;
  653.                                 wordWrapBuffer(0, bufLen);
  654.                                 }
  655.                             break;
  656.                         case cmToggleAutoMargin:
  657.                             autosizeMargin = Boolean(!autosizeMargin);
  658.                             break;
  659.                         default:
  660.                             unlock();
  661.                             return;
  662.                         }
  663.                     trackCursor(centerCursor);
  664.                     unlock();
  665.                     break;
  666.                 }
  667.             break;
  668.  
  669.         case evBroadcast:
  670.             switch( event.message.command )
  671.                 {
  672.                 case cmScrollBarChanged:
  673.                     checkScrollBar( event, hScrollBar, delta.x );
  674.                     checkScrollBar( event, vScrollBar, delta.y );
  675.                     break;
  676.                 default:
  677.                     return;
  678.                 }
  679.         }
  680.     clearEvent(event);
  681. }
  682. #pragma warn .stv
  683.  
  684.  
  685.