home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / tvision / tfldex / tfield.cpp next >
Encoding:
C/C++ Source or Header  |  1992-01-24  |  15.2 KB  |  571 lines

  1. /*------------------------------------------------------------*/
  2. /* filename -       tfield.cpp                                */
  3. /*                                                            */
  4. /* function(s)                                                */
  5. /*                  TField member functions                   */
  6. /*------------------------------------------------------------*/
  7.  
  8. /*------------------------------------------------------------*/
  9. /*                                                            */
  10. /*    Turbo Vision -  Version 1.0                             */
  11. /*    Turbo Vision Extensions -- Version 1.0.0                */
  12. /*                                                            */
  13. /*                                                            */
  14. /*    Portions Copyright (c) 1991 by Borland International    */
  15. /*    All Rights Reserved.                                    */
  16. /*                                                            */
  17. /*    TV Extensions are Copyright (c) 1992 by Michael Bonner  */
  18. /*    These extensions may be freely used by any programmer   */
  19. /*    including royalty free inclusion in any commercial      */
  20. /*    application, but any commercial rights to the source    */
  21. /*    code or object files of the Extensions are reserved.    */
  22. /*                                                            */
  23. /*------------------------------------------------------------*/
  24.  
  25. #define Uses_TKeys
  26. #define Uses_TView
  27. #define Uses_TDrawBuffer
  28. #define Uses_TEvent
  29. #define Uses_opstream
  30. #define Uses_ipstream
  31. #define Uses_TField
  32. #include <tv.h>
  33. #include "tfield.h"
  34.  
  35. #if !defined( __CTYPE_H )
  36. #include <ctype.h>
  37. #endif  // __CTYPE_H
  38.  
  39. #if !defined( __STRING_H )
  40. #include <String.h>
  41. #endif  // __STRING_H
  42.  
  43. #if !defined( __DOS_H )
  44. #include <Dos.h>
  45. #endif  // __DOS_H
  46.  
  47. #if !defined( __MEM_H )
  48. #include <Mem.h>
  49. #endif  // __MEM_H
  50.  
  51.  
  52. const int CONTROL_Y = 25;
  53.  
  54. char hotKey( const char *s )
  55. {
  56.      char *p;
  57.  
  58.      if( (p = strchr( s, '~' )) != 0 )
  59.           return toupper(p[1]);
  60.      else
  61.           return 0;
  62. }
  63.  
  64. #define cpField "\x13\x13\x14\x15"
  65.  
  66.  
  67. const char * const near TField::name = "TField";
  68. const char near TField::rightArrow = '\x10';
  69. const char near TField::leftArrow = '\x11';
  70.  
  71.  
  72. TField::TField( const TRect& bounds, int aMaxLen ) :
  73.      TView(bounds),
  74.      data( new char[aMaxLen] ),
  75.      maxLen( aMaxLen-1 ),
  76.      curPos( 0 ),
  77.      firstPos( 0 ),
  78.      selStart( 0 ),
  79.      selEnd( 0 )
  80. {
  81.      state |= sfCursorVis;
  82.      options |= ofSelectable | ofFirstClick;
  83.      *data = EOS;
  84.      //
  85.      // 1/16/92 -- MBB
  86.      // Added support for the scrollState variable in the constructor.
  87.      // scrollState is initialized to True by default, which enables scrolling.
  88.      // Call the function setScroll( False ) to disable scrolling.
  89.      //
  90.      scrollState = True;
  91.      //
  92.      // 1/17/92 -- MBB
  93.      // Added support for the justification variable in the constructor.
  94.      // justification is initialized to jLeft by default.
  95.      //
  96.      justification = jLeft;
  97.  
  98. }
  99.  
  100. TField::~TField()
  101. {
  102.      delete data;
  103. }
  104.  
  105. Boolean TField::canScroll( int delta )
  106. {
  107.     //
  108.     // 1/16/92 -- MBB
  109.     // Added check of scrollState before allowing scrolling.  If scrollState
  110.     // is 0 then no scrolling can occur and this routine returns False
  111.     // always.  If scrollState is not 0 then this routine works like it did
  112.     // in TInputLine.
  113.     //
  114.     if( scrollState) {
  115.         //
  116.         // scrollState is not 0, process the scroll request
  117.         //
  118.         if( delta < 0 )
  119.             return Boolean( firstPos > 0 );
  120.         else
  121.             if( delta > 0 )
  122.                 return Boolean( strlen(data) - firstPos + 2 > size.x );
  123.             else
  124.                 return False;
  125.         }
  126.     else
  127.         //
  128.         // scrollState is 0, return false
  129.         //
  130.         return False;
  131. }
  132.  
  133. ushort TField::dataSize()
  134. {
  135.      return maxLen+1;
  136. }
  137.  
  138. void TField::draw()
  139. {
  140.     //************************************************************************
  141.     // 1/23/92 -- MBB
  142.     // Rewrote section to provide support to enable/disable scrolling and
  143.     // to handle right justification
  144.     //************************************************************************
  145.  
  146.     const int bufferSize = 256;
  147.  
  148.     int     selectFirst = 0,             // formerly l,
  149.                                             // used to calc position of the first
  150.                                             // selected character in the TDrawBuffer
  151.             selectLast = 0,            // formerly r,
  152.                                             // used to calc position of the last
  153.                                             // selected character in the TDrawBuffer
  154.             dataLen = strlen(data),    // holds the length of the data string
  155.             cursorPosition = 0,        // holds the new cursor postion
  156.             displaySize = size.x,    // holds the # characters of the current
  157.                                             // TRect which will be used to display data
  158.             dataOffset = firstPos,    // holds the offset into the data string
  159.             bufOffset = 0,                // holds the offset into the buf buffer
  160.                                             // used w/ jRight to add leading spaces
  161.             bOffset = 0;                // holds the offset into the b buffer
  162.                                             // used w/ scrollState to leave room for
  163.                                             // leftArrow
  164.  
  165.     TDrawBuffer b;
  166.  
  167.     //
  168.     // decide if we use the focused or not-focused color
  169.     //
  170.     uchar color = (state & sfFocused) ? getColor( 2 ) : getColor( 1 );
  171.  
  172.     //
  173.     // clear the display buffer
  174.     //
  175.     b.moveChar( 0, ' ', color, size.x );
  176.  
  177.     char buf[bufferSize];             // create a temporary character buffer
  178.     memset(buf, ' ', size.x);        // clear the portion of the buffer we'll use
  179.     // ^^^^^^^^^^^^^^^^^^^^^^
  180.     // This could be a problem if size.x > bufferSize, but since this routine
  181.     // is called frequently, I want to keep the overhead down as much as
  182.     // possible, so I won't perform error checking.  Be aware of this if you
  183.     // change the bufferSize variable!
  184.     //
  185.  
  186.     //************************************************************************
  187.     // 1/23/92 -- MBB
  188.     // rewrote this section to compute all offsets and positions based on the
  189.     // current state of scrollState and justification.
  190.     //************************************************************************
  191.     if (scrollState) {
  192.         //
  193.         // Compute offsets and positions to allow for scrolling
  194.         // (ie. leave room for arrows)
  195.         //
  196.         bOffset = 1;                     // leave room for the left arrow at the
  197.                                             // start of the line
  198.         displaySize -= 2;             // adjust display size to leave room for
  199.                                             // two arrows on the line
  200.  
  201.         //
  202.         // Put the arrows in the buffer if they are needed
  203.         //
  204.         if( (state & sfSelected) != 0 ) {
  205.             if( ((state & sfSelected) != 0) && (canScroll(1)) )
  206.                 b.moveChar( size.x-1, rightArrow, getColor(4), 1 );
  207.             if( ((state & sfSelected) != 0) && (canScroll(-1)) )
  208.                 b.moveChar( 0, leftArrow, getColor(4), 1 );
  209.         };
  210.     }
  211.     else {
  212.         //
  213.         // Compute the offsets and positions that ignore scrolling
  214.         //
  215.         //dataOffset = 0;
  216.     };
  217.  
  218.     if ( (state & sfSelected) != 0 )
  219.     {
  220.         //
  221.         // calculate offset for right justification
  222.         //
  223.         if ( (justification == jRight) && (dataLen <= displaySize) ) {
  224.             bufOffset = displaySize - dataLen;
  225.             //
  226.             // Add an additional character to the end of the field
  227.             // unless the data just fits the field
  228.             //
  229.             if (maxLen < displaySize)
  230.                 bufOffset--;
  231.         };
  232.         //
  233.         // Calculate the selected positions and cursor position
  234.         //
  235.         selectFirst = selStart - firstPos;
  236.         selectLast = selEnd - firstPos;
  237.         selectFirst = max( 0, selectFirst ) + bufOffset;
  238.         selectLast = min( displaySize, selectLast ) + bufOffset;
  239.         cursorPosition = curPos - firstPos + bOffset + bufOffset;
  240.     };
  241.  
  242.  
  243.     //************************************************************************
  244.     // 1/23/92 -- MBB
  245.     // rewrote this section to update the display based on the computed
  246.     // offsets and positions (cleaned up multiple if's & case structures
  247.     // so code would be easier to maintain.)
  248.     //************************************************************************
  249.  
  250.     //
  251.     // Copy from the data string to the buf string
  252.     //
  253.     strncpy( buf+bufOffset, data+dataOffset, min(displaySize, dataLen) );
  254.     //
  255.     // set the last character in buf to end of string to keep display clean
  256.     //
  257.     if (bufOffset > 0)
  258.         buf[ displaySize ] = EOS;
  259.     else
  260.         buf[ min(displaySize, dataLen) ] = EOS;
  261.     //
  262.     // move characters from the buf into the TDrawBuffer b
  263.     //
  264.     b.moveStr( bOffset, buf, color );
  265.     //
  266.     // change the color of any selected text
  267.     //
  268.     if (selectFirst <  selectLast)
  269.         b.moveChar( selectFirst + bOffset, 0, getColor(3),
  270.                         min(selectLast - selectFirst, dataLen) );
  271.     //
  272.     // write the buffer to the form
  273.     //
  274.     writeLine( 0, 0, size.x, size.y, b );
  275.     //
  276.     // reposition the cursor
  277.     //
  278.     setCursor( cursorPosition, 0);
  279.  
  280. }
  281.  
  282. void TField::getData( void *rec )
  283. {
  284.      memcpy( rec, data, dataSize() );
  285. }
  286.  
  287. TPalette& TField::getPalette() const
  288. {
  289.      static TPalette palette( cpField, sizeof( cpField )-1 );
  290.      return palette;
  291. }
  292.  
  293. int TField::mouseDelta( TEvent& event )
  294. {
  295.      TPoint mouse = makeLocal( event.mouse.where );
  296.  
  297.      if( mouse.x <= 0 )
  298.           return -1;
  299.      else
  300.           if( mouse.x >= size.x - 1 )
  301.                 return 1;
  302.           else
  303.                 return 0;
  304. }
  305.  
  306. int TField::mousePos( TEvent& event )
  307. {
  308.  
  309.     TPoint mouse = makeLocal( event.mouse.where );
  310.     int pos;
  311.  
  312.     //************************************************************************
  313.     // 1/24/92 -- MBB
  314.     // Compute offsets to handle the scrollState and justification stuff
  315.     //************************************************************************
  316.     int    leadArrow = (scrollState ? 1 : 0),// offset for the beginning arrow
  317.             displaySize = (scrollState ? size.x - 2 : size.x),
  318.                                                         // x size used for display
  319.             dataLen = strlen(data),                // length of the data item
  320.             jOffset = 0;                            // justification offset
  321.  
  322.     //
  323.     // Calculate offset when justification is active
  324.     //
  325.     if ( (justification == jRight) && (dataLen <= displaySize) ) {
  326.         jOffset = displaySize - dataLen;
  327.         if (maxLen < displaySize)
  328.             jOffset--;
  329.     };
  330.  
  331.     mouse.x = max( mouse.x, leadArrow );
  332.     pos = mouse.x + firstPos - jOffset - leadArrow;
  333.  
  334.     pos = max( pos, 0 );
  335.     pos = min( pos, strlen(data) + jOffset );
  336.     return pos;
  337. }
  338.  
  339. void  TField::deleteSelect()
  340. {
  341.      if( selStart < selEnd )
  342.           {
  343.           strcpy( data+selStart, data+selEnd );
  344.           curPos = selStart;
  345.           }
  346. }
  347.  
  348. void  TField::handleEvent( TEvent& event )
  349. {
  350.      TView::handleEvent(event);
  351.  
  352.      int delta, anchor, i;
  353.      if( (state & sfSelected) != 0 )
  354.           switch( event.what )
  355.                 {
  356.                 case  evMouseDown:
  357.                      if( canScroll(delta = mouseDelta(event)) )
  358.                           do  {
  359.                                 if( canScroll(delta) )
  360.                                      {
  361.                                      firstPos += delta;
  362.                                      drawView();
  363.                                      }
  364.                                 } while( mouseEvent( event, evMouseAuto ) );
  365.                      else if (event.mouse.doubleClick)
  366.                                 selectAll(True);
  367.                      else
  368.                           {
  369.                           anchor =  mousePos(event);
  370.                           do  {
  371.                                 if( event.what == evMouseAuto &&
  372.                                      canScroll( delta = mouseDelta(event) )
  373.                                   )
  374.                                      firstPos += delta;
  375.                                 curPos = mousePos(event);
  376.                                 if( curPos < anchor )
  377.                                      {
  378.                                      selStart = curPos;
  379.                                      selEnd = anchor;
  380.                                      }
  381.                                 else
  382.                                      {
  383.                                      selStart = anchor;
  384.                                      selEnd = curPos;
  385.                                      }
  386.                                 drawView();
  387.                                 } while (mouseEvent(event, evMouseMove | evMouseAuto));
  388.                           }
  389.                      clearEvent(event);
  390.                      break;
  391.                 case  evKeyDown:
  392.                      switch( ctrlToArrow(event.keyDown.keyCode) )
  393.                           {
  394.                           case kbLeft:
  395.                                 if( curPos > 0 )
  396.                                      curPos--;
  397.                                 break;
  398.                           case kbRight:
  399.                                 if( curPos < strlen(data) )
  400.                                      curPos++;
  401.                                 break;
  402.                           case kbHome:
  403.                                 curPos =  0;
  404.                                 break;
  405.                           case kbEnd:
  406.                                 curPos = strlen(data);
  407.                                 break;
  408.                           case kbBack:
  409.                                 if( curPos > 0 )
  410.                                      {
  411.                                      strcpy( data+curPos-1, data+curPos );
  412.                                      curPos--;
  413.                                      if( firstPos > 0 )
  414.                                           firstPos--;
  415.                                      }
  416.                                 break;
  417.                           case kbDel:
  418.                                 if( selStart == selEnd )
  419.                                      if( curPos < strlen(data) )
  420.                                           {
  421.                                           selStart = curPos;
  422.                                           selEnd = curPos + 1;
  423.                                           }
  424.                                 deleteSelect();
  425.                                 break;
  426.                           case kbIns:
  427.                                 setState(sfCursorIns, Boolean(!(state & sfCursorIns)));
  428.                                 break;
  429.                           default:
  430.                                 if( event.keyDown.charScan.charCode >= ' ' )
  431.                                      {
  432.                                      //
  433.                                      // 1/23/92 -- MBB
  434.                                      // Added fix for overlay mode suggested by
  435.                                      // Martin Keye (CIS 100033,3020) to prevent
  436.                                      // garbage characters at the last position
  437.                                      // when in overstrike mode
  438.                                      // Line read:
  439.                                      //     if ( (state & sfCursorIns ) != 0 )
  440.                                      //
  441.                                      if ( ((state & sfCursorIns ) != 0) &&
  442.                                             (curPos < strlen(data)) )
  443.                                           strcpy( data + curPos, data + curPos + 1 );
  444.                                      else
  445.                                           deleteSelect();
  446.                                      if( strlen(data) < maxLen )
  447.                                           {
  448.                                           if( firstPos > curPos )
  449.                                                 firstPos = curPos;
  450.                                           memmove( data + curPos + 1, data + curPos,
  451.                                                       strlen(data+curPos)+1 );
  452.                                           data[curPos++] =
  453.                                                 event.keyDown.charScan.charCode;
  454.                                           }
  455.                                      }
  456.                                 else if( event.keyDown.charScan.charCode == CONTROL_Y)
  457.                                      {
  458.                                      *data = EOS;
  459.                                      curPos = 0;
  460.                                      }
  461.                                 else
  462.                                      return;
  463.                           }
  464.                           selStart = 0;
  465.                           selEnd = 0;
  466.                           if( firstPos > curPos )
  467.                                 firstPos = curPos;
  468.                           //
  469.                           // 1/23/92 -- MBB
  470.                           // Modified to take scrollState into account
  471.                           //
  472.                           i = curPos - size.x + 1;
  473.                           if (scrollState)
  474.                                 i += 2;
  475.                           if( firstPos < i )
  476.                                 firstPos = i;
  477.                           drawView();
  478.                           clearEvent( event );
  479.                           break;
  480.                 }
  481. }
  482.  
  483. void TField::selectAll( Boolean enable )
  484. {
  485.      selStart = 0;
  486.      if( enable )
  487.           curPos = selEnd = strlen(data);
  488.      else
  489.           curPos = selEnd = 0;
  490.     //************************************************************************
  491.     // 1/24/92 -- MBB
  492.     // Modified to adjust for scrollState and justification
  493.     //************************************************************************
  494.      if (scrollState)
  495.         firstPos = max( 0, curPos-size.x+3 );
  496.      else
  497.         firstPos = max( 0, curPos-size.x+1 );
  498.      drawView();
  499. }
  500.  
  501. void TField::setData( void *rec )
  502. {
  503.      memcpy( data, rec, dataSize()-1 );
  504.      data[dataSize()-1] = EOS;
  505.      selectAll( True );
  506. }
  507.  
  508. void TField::setScroll( Boolean enable )
  509. {
  510.     if( enable )
  511.         scrollState = True;
  512.     else
  513.         scrollState = False;
  514.     //
  515.     // Redisplay the field
  516.     //
  517.     drawView();
  518. }
  519.  
  520. void TField::setJustification( int jValue )
  521. {
  522.     if ( jValue == jRight )
  523.         justification = jRight;
  524.     else
  525.         justification = jLeft;
  526.     //
  527.     // Redisplay the field
  528.     //
  529.     drawView();
  530. }
  531.  
  532. void TField::setState( ushort aState, Boolean enable )
  533. {
  534.      TView::setState( aState, enable );
  535.      if( aState == sfSelected ||
  536.           ( aState == sfActive && (state & sfSelected) != 0 )
  537.         )
  538.           selectAll( enable );
  539. }
  540.  
  541. void TField::write( opstream& os )
  542. {
  543.      TView::write( os );
  544.      os << maxLen << curPos << firstPos
  545.          << selStart << selEnd << scrollState << justification;
  546.      os.writeString( data);
  547. }
  548.  
  549. void *TField::read( ipstream& is )
  550. {
  551.      TView::read( is );
  552.      is >> maxLen >> curPos >> firstPos
  553.          >> selStart >> selEnd >> scrollState >> justification;
  554.      data = new char[maxLen + 1];
  555.      is.readString(data, maxLen);
  556.      state |= sfCursorVis;
  557.      options |= ofSelectable | ofFirstClick;
  558.      return this;
  559. }
  560.  
  561. TStreamable *TField::build()
  562. {
  563.      return new TField( streamableInit );
  564. }
  565.  
  566. TField::TField( StreamableInit ) : TView( streamableInit )
  567. {
  568. }
  569.  
  570.  
  571.