home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tv20cpp.zip / src / textview.cpp < prev    next >
C/C++ Source or Header  |  1999-05-19  |  8KB  |  316 lines

  1. /*
  2.  * textview.cc
  3.  *
  4.  * Turbo Vision - Version 2.0
  5.  *
  6.  * Copyright (c) 1994 by Borland International
  7.  * All Rights Reserved.
  8.  *
  9.  * Modified by Sergio Sigala <ssigala@globalnet.it>
  10.  */
  11.  
  12. #define Uses_TTextDevice
  13. #define Uses_TTerminal
  14. #define Uses_otstream
  15. #include <tvision/tv.h>
  16.  
  17. #include <string.h>
  18.  
  19. TTextDevice::TTextDevice( const TRect& bounds,
  20.                           TScrollBar *aHScrollBar,
  21.                           TScrollBar *aVScrollBar) :
  22.     TScroller(bounds,aHScrollBar,aVScrollBar)
  23. {
  24. }
  25.  
  26. TTerminal::TTerminal( const TRect& bounds,
  27.                       TScrollBar *aHScrollBar,
  28.                       TScrollBar *aVScrollBar,
  29.                       ushort aBufSize ) :
  30.     TTextDevice(bounds, aHScrollBar, aVScrollBar),
  31.     queFront( 0 ),
  32. #ifndef __UNPATCHED
  33.     queBack( 0 ),
  34.     curLineWidth( 0 )       // Added for horizontal cursor tracking.
  35. #else
  36.     queBack( 0 )
  37. #endif
  38. {
  39.     growMode = gfGrowHiX + gfGrowHiY;
  40.     bufSize = min( 32000U, aBufSize );
  41.     buffer = new char[ bufSize ];
  42.     setLimit( 0, 1 );
  43.     setCursor( 0, 0 );
  44.     showCursor();
  45. }
  46.  
  47.  
  48. TTerminal::~TTerminal()
  49. {
  50.     delete buffer;
  51. }
  52.  
  53. void TTerminal::bufDec( ushort& val )
  54. {
  55.     if (val == 0)
  56.         val = bufSize - 1;
  57.     else
  58.         val--;
  59. }
  60.  
  61. void TTerminal::bufInc( ushort& val )
  62. {
  63.     if( ++val >= bufSize )
  64.         val = 0;
  65. }
  66.  
  67. Boolean TTerminal::canInsert( ushort amount )
  68. {
  69.     long T = (queFront < queBack) ?
  70.         ( queFront +  amount ) :
  71.         ( long(queFront) - bufSize + amount);   // cast needed so we get
  72.                                                 // signed comparison
  73.     return Boolean( queBack > T );
  74. }
  75.  
  76. void TTerminal::draw()
  77. {
  78.     short  i;
  79.     ushort begLine, endLine;
  80. #ifndef __UNPATCHED
  81.     char s[ maxViewWidth+1 ];  // KRW: Bug Fix/Enhancement: 95/01/05
  82.                                // Do *NOT* attempt to display more
  83.                                // than maxViewWidth chars
  84.                                // ** assume size.x <= maxViewWidth **
  85. #else
  86.     char s[256];
  87. #endif
  88.     ushort bottomLine;
  89.  
  90.     bottomLine = size.y + delta.y;
  91.     if( limit.y > bottomLine )
  92.         {
  93.         endLine = prevLines( queFront, limit.y - bottomLine );
  94.         bufDec( endLine );
  95.         }
  96.     else
  97.         endLine = queFront;
  98.  
  99.     if( limit.y > size.y )
  100.         i = size.y - 1;
  101.     else
  102.         {
  103.         for( i = limit.y; i <= size.y - 1; i++ )
  104.             writeChar(0, i, ' ', 1, size.x);
  105.         i =  limit.y -  1;
  106.         }
  107.  
  108.     for( ; i >= 0; i-- )
  109.         {
  110. #ifndef __UNPATCHED
  111.         // KRW: Bug fix/enhancement - handle any length line by only copying
  112.         //   to s those characters to be displayed, which we assume will
  113.         //   be < maxViewWidth
  114.         //  This whole block rewritten
  115.         memset( s, ' ', size.x ); // must display blanks if no characters!
  116.         begLine = prevLines(endLine, 1);
  117.         if (endLine >= begLine)
  118.         {
  119.             // Entire string to be displayed is in one fragment, not
  120.             // wrapped around the end of the buffer
  121.         int fragmentLength = int( endLine - begLine );
  122.             if (fragmentLength > delta.x)
  123.                 {
  124.                 fragmentLength -= delta.x;
  125.                 fragmentLength = min( size.x, fragmentLength );
  126.                 memcpy( s, &buffer[begLine+delta.x], fragmentLength );
  127.                 }
  128.         }
  129.         else
  130.         {
  131.             // Extract first fragment into s
  132.             int deltaLeft = delta.x;
  133.             int firstFragmentLength = int( bufSize - begLine );
  134.             if (firstFragmentLength > delta.x)
  135.             {
  136.                 deltaLeft = 0;
  137.                 firstFragmentLength -= delta.x;
  138.                 firstFragmentLength  = min( size.x, firstFragmentLength );
  139.                 memcpy( s, &buffer[begLine+delta.x], firstFragmentLength );
  140.             }
  141.             else
  142.             {
  143.                 deltaLeft -= firstFragmentLength;
  144.         firstFragmentLength = 0;
  145.         }
  146.             // Extract second fragment into s
  147.         if ((endLine > deltaLeft) && (firstFragmentLength < size.x))
  148.             {
  149.                 int secondFragmentLength = endLine - deltaLeft;
  150.                 secondFragmentLength =
  151.                     min(size.x-firstFragmentLength,secondFragmentLength);
  152.             memcpy( &s[ firstFragmentLength ], &buffer[ deltaLeft ],
  153.                     secondFragmentLength );
  154.             }
  155.         }
  156.  
  157.         s[ size.x ] = EOS;
  158.         writeStr( 0, i, s, 1 );
  159.  
  160.         endLine = begLine;
  161.         bufDec( endLine );
  162. #else
  163.         begLine = prevLines(endLine, 1);
  164.         if (endLine >= begLine)
  165.             {
  166.             int T = int( endLine - begLine );
  167.             memcpy( s, &buffer[begLine], T );
  168.             s[T] = EOS;
  169.             }
  170.         else
  171.             {
  172.             int T = int( bufSize - begLine);
  173.             memcpy( s, &buffer[begLine], T );
  174.             memcpy( s+T, buffer, endLine );
  175.             s[T+endLine] = EOS;
  176.             }
  177.         if( delta.x >= strlen(s) )
  178.             *s = EOS;
  179.         else
  180.             strcpy( s, &s[delta.x] );
  181.  
  182.         writeStr( 0, i, s, 1 );
  183.         writeChar( strlen(s), i, ' ', 1, size.x );
  184.         endLine = begLine;
  185.         bufDec( endLine );
  186. #endif
  187.         }
  188. }
  189.  
  190. ushort TTerminal::nextLine( ushort pos )
  191. {
  192.     if( pos != queFront )
  193.         {
  194.         while( buffer[pos] != '\n' && pos != queFront )
  195.             bufInc(pos);
  196.         if( pos != queFront )
  197.             bufInc( pos );
  198.         }
  199.     return pos;
  200. }
  201.  
  202. int TTerminal::do_sputn( const char *s, int count )
  203. {
  204. #ifndef __UNPATCHED
  205.     ushort screenWidth = limit.x;
  206.     ushort screenLines = limit.y;
  207.  
  208.     // BUG FIX - Mon 07/25/94 - EFW: Made TTerminal adjust horizontal
  209.     // scrollbar limit too.
  210.  
  211.     /* SS: stupid thing */
  212.  
  213. //    for(ushort i = 0; i < count; i++, curLineWidth++)
  214.     ushort i;
  215.     for(i = 0; i < count; i++, curLineWidth++)
  216.         if(s[i] == '\n')
  217.         {
  218.             screenLines++;
  219.  
  220.             // Check width when an LF is seen.
  221.             if(curLineWidth > screenWidth)
  222.                 screenWidth = curLineWidth;
  223.  
  224.             // Reset width for the next line.
  225.             curLineWidth = 0;
  226.         }
  227.  
  228.     // One last check for width for cases where whole lines aren't
  229.     // received, maybe just a character or two.
  230.     if(curLineWidth > screenWidth)
  231.         screenWidth = curLineWidth;
  232. #else
  233.     ushort screenLines = limit.y;
  234.     for( ushort i = 0; i < count; i++ )
  235.         if( s[i] == '\n' )
  236.             screenLines++;
  237. #endif
  238.  
  239.     while( !canInsert( count ) )
  240.         {
  241.         queBack = nextLine( queBack );
  242.         screenLines--;
  243.         }
  244.  
  245.     if( queFront + count >= bufSize )
  246.         {
  247.         i = bufSize - queFront;
  248.         memcpy( &buffer[queFront], s, i );
  249.         memcpy( buffer, &s[i], count - i );
  250.         queFront = count - i;
  251.         }
  252.     else
  253.         {
  254.         memcpy( &buffer[queFront], s, count );
  255.         queFront += count;
  256.         }
  257.  
  258. #ifndef __UNPATCHED
  259.     setLimit( screenWidth, screenLines );
  260. #else
  261.     setLimit( limit.x, screenLines );
  262. #endif
  263.     scrollTo( 0, screenLines + 1 );
  264.     i = prevLines( queFront, 1 );
  265.     if( i <= queFront )
  266.         i = queFront - i;
  267.     else
  268.         i = bufSize - (i - queFront);
  269.     setCursor( i, screenLines - delta.y - 1 );
  270.     drawView();
  271.     return count;
  272. }
  273.  
  274. Boolean TTerminal::queEmpty()
  275. {
  276.     return Boolean( queBack == queFront );
  277. }
  278.  
  279. TerminalBuf::TerminalBuf(TTerminal *tt): term(tt)
  280. {
  281. }
  282.  
  283. int TerminalBuf::overflow(int c)
  284. {
  285. #ifdef __OS2__
  286.     int n = pptr() - pbase();
  287. #else
  288.     streamsize n = pptr() - pbase();
  289. #endif
  290.  
  291.     if (n > 0 && sync() == EOF) return EOF;
  292.     if (c != EOF)
  293.     {
  294.         char b = c;
  295.  
  296.         term->do_sputn(&b, sizeof(b));
  297.     }
  298.     pbump(-n);
  299.     return 0;
  300. }
  301.  
  302. int TerminalBuf::sync()
  303. {
  304. #ifdef __OS2__
  305.     int n = pptr() - pbase();
  306. #else
  307.     streamsize n = pptr() - pbase();
  308. #endif
  309.     if (n > 0) term->do_sputn(pbase(), n);
  310.     return 0;
  311. }
  312.  
  313. otstream::otstream( TTerminal *tt ): buf(tt), ostream(&buf)
  314. {
  315. }
  316.