home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / tvision / wrdwrp / teditor2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-03  |  16.7 KB  |  754 lines

  1. /*------------------------------------------------------------*/
  2. /* filename - teditor2.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-06-91 JLS  Removed two apparently useless calls to setBufSize()
  21. //      11-08-91 JLS  Put two calls to setBufSize() back in
  22. //      11-12-91 JLS  Added code in insertBuffer() to support word wrapping
  23. //      11-19-91 JLS  Moved more code into wordWrapBuffer() and modified
  24. //                      insertBuffer() accordingly
  25.  
  26. #define Uses_TKeys
  27. #define Uses_TEditor
  28. #define Uses_TIndicator
  29. #define Uses_TEvent
  30. #define Uses_TScrollBar
  31. #define Uses_TFindDialogRec
  32. #define Uses_TReplaceDialogRec
  33. #define Uses_opstream
  34. #define Uses_ipstream
  35. #include <tv.h>
  36.  
  37. #if !defined( __STRING_H )
  38. #include <string.h>
  39. #endif  // __STRING_H
  40.  
  41. #if !defined( __CTYPE_H )
  42. #include <ctype.h>
  43. #endif  // __CTYPE_H
  44.  
  45. #if !defined( __DOS_H )
  46. #include <Dos.h>
  47. #endif  // __DOS_H
  48.  
  49. inline int isWordChar( int ch )
  50. {
  51.     return isalnum(ch) || ch == '_';
  52. }
  53.  
  54. #pragma warn -asc
  55.  
  56. int TEditor::countLines( void *buf, ushort count )
  57. {
  58. asm {
  59.     LES DI,buf
  60.     MOV CX,count
  61.     XOR DX,DX
  62.     MOV AL,0Dh
  63.     CLD
  64.     }
  65. __1:
  66. asm {
  67.     JCXZ __2
  68.     REPNE SCASB
  69.     JNE __2
  70.     INC DX
  71.     JMP __1
  72.     }
  73. __2:
  74.     return _DX;
  75. }
  76.  
  77. ushort scan( const void *block, ushort size, const char *str )
  78. {
  79.     ushort len = strlen( str );
  80. asm {
  81.     PUSH DS
  82.     LES DI,block
  83.     LDS SI,str
  84.     MOV CX,size
  85.     JCXZ __3
  86.     CLD
  87.     MOV AX,len
  88.     CMP AX,1
  89.     JB __5
  90.     JA __1
  91.     LODSB           // searching for a single character
  92.     REPNE SCASB
  93.     JNE __3
  94.     JMP __5
  95.     }
  96. __1:
  97. asm {
  98.     MOV BX,AX
  99.     DEC BX
  100.     MOV DX,CX
  101.     SUB DX,AX
  102.     JB  __3
  103.     LODSB
  104.     INC DX
  105.     INC DX
  106.     }
  107. __2:
  108. asm {
  109.     DEC DX
  110.     MOV CX,DX
  111.     REPNE SCASB
  112.     JNE __3
  113.     MOV DX,CX
  114.     MOV CX,BX
  115.     REP CMPSB
  116.     JE  __4
  117.     SUB CX,BX
  118.     ADD SI,CX
  119.     ADD DI,CX
  120.     INC DI
  121.     OR  DX,DX
  122.     JNE __2
  123.     }
  124. __3:
  125. asm {
  126.     XOR AX,AX
  127.     JMP __6
  128.     }
  129. __4:
  130. asm SUB DI,BX
  131. __5:
  132. asm {
  133.     MOV AX,DI
  134.     SUB AX,WORD PTR block
  135.     }
  136. __6:
  137. asm {
  138.     DEC AX
  139.     POP DS
  140.     }
  141.     return _AX;
  142. }
  143.  
  144. ushort iScan( const void *block, ushort size, const char *str )
  145. {
  146.     char s[256];
  147.     ushort len = strlen( str );
  148. asm {
  149.     PUSH DS
  150.     MOV AX,SS
  151.     MOV ES,AX
  152.     LEA DI,s
  153.     LDS SI,str
  154.     MOV AX,len;
  155.     MOV CX,AX
  156.     MOV BX,AX
  157.     JCXZ __9
  158.     }
  159. __1:
  160. asm {
  161.     LODSB
  162.     CMP AL,'a'
  163.     JB  __2
  164.     CMP AL,'z'
  165.     JA  __2
  166.     SUB AL,20h
  167.     }
  168. __2:
  169. asm {
  170.     STOSB
  171.     LOOP __1
  172.     SUB DI,BX
  173.     LDS SI,block
  174.     MOV CX,size
  175.     JCXZ __8
  176.     CLD
  177.     SUB CX,BX
  178.     JB  __8
  179.     INC CX
  180.     }
  181. __4:
  182. asm {
  183.     MOV AH,ES:[DI]
  184.     AND AH,0xDF
  185.     }
  186. __5:
  187. asm {
  188.     LODSB
  189.     AND AL,0xDF
  190.     CMP AL,AH
  191.     LOOPNE  __5
  192.     JNE __8
  193.     DEC SI
  194.     MOV DX,CX
  195.     MOV CX,BX
  196.     }
  197. __6:
  198. asm {
  199.     REPE CMPSB
  200.     JE  __10
  201.     MOV AL,DS:[SI-1]
  202.     CMP AL,'a'
  203.     JB  __7
  204.     CMP AL,'z'
  205.     JA  __7
  206.     SUB AL,20h
  207.     }
  208. __7:
  209. asm {
  210.     CMP AL,ES:[DI-1]
  211.     JE  __6
  212.     SUB CX,BX
  213.     ADD SI,CX
  214.     ADD DI,CX
  215.     INC SI
  216.     MOV CX,DX
  217.     JNE __4
  218.     }
  219. __8:
  220. asm {
  221.     XOR AX,AX
  222.     JMP __11
  223.     }
  224. __9:
  225. asm {
  226.     MOV AX, 1
  227.     JMP __11
  228.     }
  229. __10:
  230. asm {
  231.     SUB SI,BX
  232.     MOV AX,SI
  233.     SUB AX,wORD PTR block
  234.     INC AX
  235.     }
  236. __11:
  237. asm {
  238.     DEC AX
  239.     POP DS
  240.     }
  241.     return _AX;
  242. }
  243.  
  244. #pragma warn .asc
  245.  
  246. void TEditor::hideSelect()
  247. {
  248.     selecting = False;
  249.     setSelect(curPtr, curPtr, False);
  250. }
  251.  
  252. void TEditor::initBuffer()
  253. {
  254.     buffer = new char[bufSize];
  255. }
  256.  
  257.  
  258. Boolean TEditor::insertBuffer( char *p,
  259.                                ushort offset,
  260.                                ushort length,
  261.                                Boolean allowUndo,
  262.                                Boolean selectText,
  263.                                Boolean alwaysWrap
  264.                              )
  265. {
  266.     selecting = False;
  267.     ushort selLen = selEnd - selStart;
  268.     if( selLen == 0 && length == 0 && !alwaysWrap )
  269.         return True;
  270.  
  271.     ushort delLen = 0;
  272.     if( allowUndo == True )
  273.         if( curPtr == selStart )
  274.             delLen = selLen;
  275.         else
  276.             if( selLen > insCount )
  277.                 delLen = selLen - insCount;
  278.  
  279.     long newSize = long(bufLen + delCount - selLen + delLen) + length;
  280.  
  281.     if( newSize > bufLen + delCount )
  282.         if( newSize > 0xFFF0l || setBufSize(ushort(newSize)) == False )
  283.             {
  284.             editorDialog( edOutOfMemory );
  285.             return False;
  286.             }
  287.  
  288.     ushort selLines = countLines( &buffer[bufPtr(selStart)], selLen );
  289.  
  290.     if( curPtr == selEnd )
  291.         {
  292.         if( allowUndo == True )
  293.             {
  294.             if( delLen > 0 )
  295.                 memmove( 
  296.                          &buffer[curPtr + gapLen - delCount - delLen],
  297.                          &buffer[selStart],
  298.                          delLen
  299.                        );
  300.             insCount -= selLen - delLen;
  301.             }
  302.         curPtr = selStart;
  303.         curPos.y -= selLines;
  304.         }
  305.  
  306.     if( delta.y > curPos.y )
  307.         {
  308.         delta.y -= selLines;
  309.         if( delta.y < curPos.y )
  310.             delta.y = curPos.y;
  311.         }
  312.  
  313.     // Insert the text
  314.     if (length > 0)
  315.         memmove(buffer + curPtr, p + offset, length);
  316.  
  317.     // Change all internal pointers to be correct before calling word-wrap
  318.     short lines = countLines(buffer+curPtr, length);    // count no. of inserted lines
  319.     ushort prevline = prevLine(lineStart(curPtr));
  320.  
  321.     curPtr += length;
  322.     bufLen += length - selLen;
  323.     gapLen -= length - selLen;
  324.     limit.y += lines - selLines;
  325.     delta.y = max(0, min(delta.y, limit.y - size.y));
  326.  
  327.     if( allowUndo == True )
  328.         {
  329.         delCount += delLen;
  330.         insCount += length;
  331.         }
  332.  
  333.     // The wordWrapBuffer() function might change member data items (curPtr, etc.)
  334.     WordWrapState wrap_rc =
  335.         wordWrap ? wordWrapBuffer(prevline, curPtr-prevline+1) : wwsNoWrap;
  336.  
  337.     if (wrap_rc == wwsError)
  338.         return False;
  339.  
  340.     else if (wrap_rc == wwsNoWrap) {
  341.         // If the buffer wrapped, these fields were already adjusted
  342.         curPos.y += lines;
  343.         drawLine = curPos.y;
  344.         drawPtr = lineStart(curPtr);
  345.         curPos.x = charPos(drawPtr, curPtr);
  346.     }
  347.  
  348.     if (selLines == 0 && lines == 0)
  349.         update(ufLine);
  350.     else
  351.         update(ufView);
  352.  
  353.     if( selectText == False )
  354.         selStart = curPtr;
  355.     selEnd = curPtr;
  356.  
  357.     // Don't mark clipboard as modified -- it will ask to be saved if it is
  358.     if (!isClipboard())
  359.         modified = True;
  360.  
  361.     setBufSize(bufLen + delCount);      // Shrink buffer to minimum size
  362.  
  363.     return True;
  364. }
  365.  
  366.  
  367. Boolean TEditor::insertFrom( TEditor *editor )
  368. {
  369.     return insertBuffer( editor->buffer,
  370.                          editor->bufPtr(editor->selStart),
  371.                          editor->selEnd - editor->selStart,
  372.                          canUndo,
  373.                          isClipboard()
  374.                         );
  375. }
  376.  
  377.  
  378. ushort TEditor::lineMove( ushort p, int count )
  379. {
  380.     ushort i = p;
  381.     p = lineStart(p);
  382.     int pos = charPos(p, i);
  383.     while( count != 0 )
  384.         {
  385.         i = p;
  386.         if( count < 0 )
  387.             {
  388.             p = prevLine(p);
  389.             count++;
  390.             }
  391.         else
  392.             {
  393.             p = nextLine(p);
  394.             count--;
  395.             }
  396.         }
  397.     if( p != i )
  398.         p = charPtr(p, pos);
  399.     return p;
  400. }
  401.  
  402. void TEditor::newLine()
  403. {
  404.     const char crlf[] = "\x0D\x0A";
  405.     ushort p = lineStart(curPtr);
  406.  
  407.     ushort i = p;
  408.     while( i < curPtr &&
  409.            ( (buffer[i] == ' ') || (buffer[i] == '\t'))
  410.          )
  411.          i++;
  412.  
  413.     insertText(crlf, 2, False);
  414.     if( autoIndent )
  415.         insertText( &buffer[p], i - p, False);
  416. }
  417.  
  418. ushort TEditor::nextWord( ushort p )
  419. {
  420.     while( p < bufLen && isWordChar(bufChar(p)) )
  421.         p = nextChar(p);
  422.     while( p < bufLen && !isWordChar(bufChar(p)) )
  423.         p = nextChar(p);
  424.     return p;
  425. }
  426.  
  427. ushort TEditor::prevWord( ushort p )
  428. {
  429.     while( p > 0 && !isWordChar(bufChar(prevChar(p))) )
  430.         p = prevChar(p);
  431.     while( p > 0 && isWordChar(bufChar(prevChar(p))) )
  432.         p = prevChar(p);
  433.     return p;
  434. }
  435.  
  436. void TEditor::replace()
  437. {
  438.     TReplaceDialogRec replaceRec( findStr, replaceStr, editorFlags );
  439.     if( editorDialog( edReplace, &replaceRec ) != cmCancel )
  440.         {
  441.         strcpy( findStr, replaceRec.find );
  442.         strcpy( replaceStr, replaceRec.replace );
  443.         editorFlags = replaceRec.options | efDoReplace;
  444.         doSearchReplace();
  445.         }
  446.  
  447. }
  448.  
  449. void TEditor::scrollTo( int x, int y )
  450. {
  451.     x = max(0, min(x, limit.x - size.x));
  452.     y = max(0, min(y, limit.y - size.y));
  453.     if( x != delta.x || y != delta.y )
  454.         {
  455.         delta.x = x;
  456.         delta.y = y;
  457.         update(ufView);
  458.         }
  459. }
  460.  
  461. Boolean TEditor::search( const char *findStr, ushort opts )
  462. {
  463.     ushort pos = curPtr;
  464.     ushort i;
  465.     do  {
  466.         if( (opts & efCaseSensitive) != 0 )
  467.             i = scan( &buffer[bufPtr(pos)], bufLen - pos, findStr);
  468.         else
  469.             i = iScan( &buffer[bufPtr(pos)], bufLen - pos, findStr);
  470.  
  471.         if( i != sfSearchFailed )
  472.             {
  473.             i += pos;
  474.             if( (opts & efWholeWordsOnly) == 0 ||
  475.                 !(
  476.                     ( i != 0 && isWordChar(bufChar(i - 1)) != 0 ) ||
  477.                     ( i + strlen(findStr) != bufLen &&
  478.                         isWordChar(bufChar(i + strlen(findStr)))
  479.                     )
  480.                  ))
  481.                 {
  482.                 lock();
  483.                 setSelect(i, i + strlen(findStr), False);
  484.                 trackCursor(Boolean(!cursorVisible()));
  485.                 unlock();
  486.                 return True;
  487.                 }
  488.             else
  489.                 pos = i + 1;
  490.             }
  491.         } while( i != sfSearchFailed );
  492.     return False;
  493. }
  494.  
  495. void TEditor::setBufLen( ushort length )
  496. {
  497.     bufLen = length;
  498.     gapLen = bufSize - length;
  499.     selStart = 0;
  500.     selEnd = 0;
  501.     curPtr = 0;
  502.     delta.x = 0;
  503.     delta.y = 0;
  504.     curPos = delta;
  505.  
  506.     if (bufLen > 0)
  507.         wordWrapBuffer(gapLen, bufLen);
  508.  
  509.     limit.x = wordWrap ? rMargin : maxLineLength;
  510.     limit.y = countLines(buffer + gapLen, bufLen) + 1;
  511.     drawLine = 0;
  512.     drawPtr = 0;
  513.     delCount = 0;
  514.     insCount = 0;
  515.     modified = False;
  516.     update(ufView);
  517. }
  518.  
  519.  
  520. Boolean TEditor::setBufSize( ushort newSize )
  521. {
  522.     return Boolean(newSize <= bufSize);
  523. }
  524.  
  525.  
  526. void TEditor::setCmdState( ushort command, Boolean enable )
  527. {
  528.     TCommandSet s;
  529.     s += command;
  530.     if( enable == True && (state & sfActive) != 0 )
  531.         enableCommands(s);
  532.     else
  533.         disableCommands(s);
  534. }
  535.  
  536. void TEditor::setCurPtr( ushort p, uchar selectMode )
  537. {
  538.     ushort anchor;
  539.     if( (selectMode & smExtend) == 0 )
  540.         anchor = p;
  541.     else if( curPtr == selStart )
  542.         anchor = selEnd;
  543.     else
  544.         anchor = selStart;
  545.  
  546.     if( p < anchor )
  547.         {
  548.         if( (selectMode & smDouble) != 0 )
  549.             {
  550.             p = prevLine(nextLine(p));
  551.             anchor = nextLine(prevLine(anchor));
  552.             }
  553.         setSelect(p, anchor, True);
  554.         }
  555.     else
  556.         {
  557.         if( (selectMode & smDouble) != 0 )
  558.             {
  559.             p = nextLine(p);
  560.             anchor = prevLine(nextLine(anchor));
  561.             }
  562.         setSelect(anchor, p, False);
  563.         }
  564. }
  565.  
  566. void TEditor::setSelect( ushort newStart, ushort newEnd, Boolean curStart )
  567. {
  568.     ushort p;
  569.     if( curStart != 0 )
  570.         p = newStart;
  571.     else
  572.         p = newEnd;
  573.  
  574.     uchar flags = ufUpdate;
  575.  
  576.     if( newStart != selStart || newEnd != selEnd )
  577.         if( newStart != newEnd || selStart != selEnd )
  578.             flags = ufView;
  579.  
  580.     if( p != curPtr )
  581.         {
  582.         if( p > curPtr )
  583.             {
  584.             ushort l = p - curPtr;
  585.             memmove( &buffer[curPtr], &buffer[curPtr + gapLen], l);
  586.             curPos.y += countLines(&buffer[curPtr], l);
  587.             curPtr = p;
  588.             }
  589.         else
  590.             {
  591.             ushort l = curPtr - p;
  592.             curPtr = p;
  593.             curPos.y -= countLines(&buffer[curPtr], l);
  594.             memmove( &buffer[curPtr + gapLen], &buffer[curPtr], l);
  595.             }
  596.         drawLine = curPos.y;
  597.         drawPtr = lineStart(p);
  598.         curPos.x = charPos(drawPtr, p);
  599.         delCount = 0;
  600.         insCount = 0;
  601.         setBufSize(bufLen);     // Shrink buffer to minimum size
  602.     }
  603.     selStart = newStart;
  604.     selEnd = newEnd;
  605.     update(flags);
  606. }
  607.  
  608. void TEditor::setState( ushort aState, Boolean enable )
  609. {
  610.     TView::setState(aState, enable);
  611.     switch( aState )
  612.         {
  613.         case sfActive:
  614.             if( hScrollBar != 0 )
  615.                 hScrollBar->setState(sfVisible, enable);
  616.             if( vScrollBar != 0 )
  617.                 vScrollBar->setState(sfVisible, enable);
  618.             if( indicator != 0 )
  619.                 indicator->setState(sfVisible, enable);
  620.             updateCommands();
  621.             break;
  622.  
  623.         case sfExposed:
  624.             if( enable == True )
  625.                 unlock();
  626.         }
  627. }
  628.  
  629. void TEditor::startSelect()
  630. {
  631.     hideSelect();
  632.     selecting = True;
  633. }
  634.  
  635. void TEditor::toggleInsMode()
  636. {
  637.     overwrite = Boolean(!overwrite);
  638.     setState(sfCursorIns, Boolean(!getState(sfCursorIns)));
  639. }
  640.  
  641. void TEditor::trackCursor( Boolean center )
  642. {
  643.     if( center == True )
  644.         scrollTo( curPos.x - size.x + 1, curPos.y - size.y / 2);
  645.     else
  646.         scrollTo( max(curPos.x - size.x + 1, min(delta.x, curPos.x)),
  647.                   max(curPos.y - size.y + 1, min(delta.y, curPos.y)));
  648. }
  649.  
  650. void TEditor::undo()
  651. {
  652.     if( delCount != 0 || insCount != 0 )
  653.         {
  654.         selStart = curPtr - insCount;
  655.         selEnd = curPtr;
  656.         ushort length = delCount;
  657.         delCount = 0;
  658.         insCount = 0;
  659.         insertBuffer(buffer, curPtr + gapLen - length, length, False, True);
  660.         }
  661. }
  662.  
  663. void TEditor::unlock()
  664. {
  665.     if( lockCount > 0 )
  666.         {
  667.         lockCount--;
  668.         if( lockCount == 0 )
  669.             doUpdate();
  670.         }
  671. }
  672.  
  673. void TEditor::update( uchar aFlags )
  674. {
  675.     updateFlags |= aFlags;
  676.     if( lockCount == 0 )
  677.         doUpdate();
  678. }
  679.  
  680. void TEditor::updateCommands()
  681. {
  682.     setCmdState( cmUndo, Boolean( delCount != 0 || insCount != 0 ) );
  683.     if( !isClipboard() )
  684.         {
  685.         setCmdState(cmCut, hasSelection());
  686.         setCmdState(cmCopy, hasSelection());
  687.         setCmdState(cmPaste,
  688.                     Boolean(clipboard != 0 && (clipboard->hasSelection())) );
  689.         }
  690.     setCmdState(cmClear, hasSelection());
  691.     setCmdState(cmFind, True);
  692.     setCmdState(cmReplace, True);
  693.  
  694.     if (strlen(findStr) != 0) {
  695.         setCmdState(cmSearchAgain, True);
  696.         setCmdState(cmReplaceAgain, True);
  697.     } else {
  698.         setCmdState(cmSearchAgain, False);
  699.         setCmdState(cmReplaceAgain, False);
  700.     }
  701.  
  702.     setCmdState(cmToggleWrap, True);
  703.     setCmdState(cmToggleAutoMargin, True);
  704. }
  705.  
  706. Boolean TEditor::valid( ushort )
  707. {
  708.   return isValid;
  709. }
  710.  
  711. void TEditor::write( opstream& os )
  712. {
  713.     TView::write( os );
  714.     os << hScrollBar << vScrollBar << indicator
  715.        << bufSize << (int)canUndo;
  716. }
  717.  
  718. void *TEditor::read( ipstream& is )
  719. {
  720.     TView::read( is );
  721.     int temp;
  722.     is >> hScrollBar >> vScrollBar >> indicator
  723.        >> bufSize >> temp;
  724.     canUndo = Boolean(temp);
  725.     selecting = False;
  726.     overwrite = False;
  727.     autoIndent = False; 
  728.     lockCount = 0;
  729.     keyState = 0;
  730.     initBuffer();
  731.     if( buffer != 0 )
  732.         isValid = True;
  733.     else
  734.         {
  735.         TEditor::editorDialog( edOutOfMemory, 0 );
  736.         bufSize = 0;
  737.         }
  738.     lockCount = 0; 
  739.     lock();
  740.     setBufLen( 0 );
  741.     return this;
  742. }
  743.  
  744. TStreamable *TEditor::build()
  745. {
  746.     return new TEditor( streamableInit );
  747. }
  748.  
  749. TEditor::TEditor( StreamableInit ) : TView( streamableInit )
  750. {
  751. }
  752.  
  753.  
  754.