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