home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vos2-121.zip / v / srcos2 / vtextcnv.cpp < prev    next >
C/C++ Source or Header  |  1999-02-18  |  20KB  |  627 lines

  1. //===============================================================
  2. // vtextcnv.cpp - TextCanvasPane, terminal like Text Drawing Canvas
  3. //
  4. // Copyright (C) 1995,1996,1997,1998  Bruce E. Wampler
  5. //
  6. // This file is part of the V C++ GUI Framework, and is covered
  7. // under the terms of the GNU Library General Public License,
  8. // Version 2. This library has NO WARRANTY. See the source file
  9. // vapp.cxx for more complete information about license terms.
  10. //===============================================================
  11. #include <v/vos2.h>        // for OS/2 stuff
  12. #include <v/vtextcnv.h>
  13.  
  14. // this is used to track what window, if any, has the cursor
  15. // at any given time
  16. static HWND caretWin = 0;
  17.  
  18. //================>>> vTextCanvasPane::vTextCanvasPane <<<====================
  19.   vTextCanvasPane::vTextCanvasPane() : vCanvasPane(P_TextCanvas)
  20.   {
  21.     SysDebug(Constructor, "vTextCanvasPane::vTextCanvasPane() constructor \n")
  22.  
  23.     screen = new dChar[MAX_ROWS*MAX_COLS];
  24.     rowsAllocated = MAX_ROWS;
  25.     colsAllocated = MAX_COLS;
  26.  
  27.     for (int row = 0 ; row < MAX_ROWS ; ++row)
  28.       for (int col = 0 ; col < MAX_COLS ; ++col)
  29.       {
  30.         ScrChar(row,col) = 0;
  31.         ScrAttr(row,col) = 0;
  32.       }
  33.  
  34.     cHeight = 0; cWidth = 0;
  35.     curRow = 0; curCol = 0;
  36.  
  37.     maxRows = -1; maxCols = -1;        // We don't know this yet
  38.     _cursorSet = 0;
  39.   }
  40.  
  41. //================>>> vTextCanvasPane::initialize <<<=========================
  42.   void vTextCanvasPane::initialize(vWindow* pWindow, HWND pWidget)
  43.   {
  44.     vCanvasPane::initialize(pWindow,pWidget);
  45.     SysDebug1(Constructor,
  46.       "vTextCanvasPane::initialize() (_drawCanvas=%u)\n", _drawCanvas)
  47.     caretOn = 0;
  48.   }
  49.  
  50. //================>>> vTextCanvasPane::vTextCanvasPane <<<====================
  51.   vTextCanvasPane::vTextCanvasPane(const vTextCanvasPane& t)
  52.   {
  53.     vSysError("vTextCanvasPane - V semantics do not support copy constructors!");
  54.   }
  55.  
  56. //================>>> vTextCanvasPane::~vTextCanvasPane <<<====================
  57.   vTextCanvasPane::~vTextCanvasPane()
  58.   {
  59.     SysDebug(Destructor,"vTextCanvasPane::~vTextCanvasPane() desstructor\n")
  60.     WinShowCursor (_drawCanvas, FALSE);
  61.     WinDestroyCursor (_drawCanvas);
  62.     caretOn = 0;
  63. //    SysDebug1(OS2Dev,"                  DestroyCursor (hWnd=%u)\n", _drawCanvas)
  64.     delete [] screen;
  65.   }
  66.  
  67. //================>>> vTextCanvasPane::SetBackground <<<====================
  68.   void vTextCanvasPane::SetBackground(vColor& color)
  69.   {
  70.     DrawTextCursor(-curRow, -curCol);  // turn the cursor off
  71.     vCanvasPane::SetBackground(color);   // set the background color
  72.     GotoRC(curRow, curCol);        // reset the cursor
  73.   }
  74.  
  75. //======================>>> vTextCanvasPane::Clear <<<======================
  76.   void vTextCanvasPane::Clear(void)
  77.   {
  78.     // Clear screen - including memory contents
  79.     SysDebug(Text,"vTextCanvasPane::Clear\n")
  80.     for (int row = 0 ; row < rowsAllocated ; ++row)
  81.       for (int col = 0 ; col < colsAllocated ; ++col)
  82.       {
  83.         ScrChar(row,col) = 0 ; ScrAttr(row,col) = ChNormal;
  84.       }
  85.     DrawTextCursor(-1,-1);  // turn the cursor off
  86.     vCanvasPane::Clear();   // wipe the canvas clean
  87.     GotoRC(0,0);            // Go to home Row & Column
  88.   }
  89.  
  90. //=================>>> vTextCanvasPane::ClearRow <<<======================
  91.   void vTextCanvasPane::ClearRow(const int r, const int c)
  92.   {
  93.     // Clear screen row - including the text memory contents
  94.     // leaves cursor wherevever it was and puts blanks
  95.     // before cursor from the left margin
  96.     SysDebug2(Text,"vTextCanvasPane::ClearRow(r:%d, c: %d)\n",r,c)
  97.  
  98.     GotoRC(r,c);            // update cursor for sure
  99.  
  100.     // Clearing implies that the previous part of the row should
  101.     // have valid characters, so change them to blanks if now 0
  102.     for (int cc = 0 ; cc < c ; ++cc)
  103.     {
  104.       if (ScrChar(r,cc) == 0)
  105.       {
  106.         ScrChar(r,cc) = ' '; ScrAttr(r,cc) = ChNormal;
  107.       }
  108.     }
  109.     // Now clear the rest of the row
  110.     for (int col = c ; col < maxCols ; ++col)
  111.     {
  112.       ScrChar(r,col) = 0 ; ScrAttr(r,col) = ChNormal;
  113.     }
  114.  
  115.     ClearRowDisplay(r,c);  // wipe out char(r,c) on screen
  116.     GotoRC(r,c);
  117.   }
  118.  
  119. //=============>>> vTextCanvasPane::ClearRowDisplay <<<======================
  120.   void vTextCanvasPane::ClearRowDisplay(const int r, const int c)
  121.   {
  122.     // this function clears the specified row on the
  123.     // screen only, starting at column c to right edge
  124.     // it does not alter the copy of text in memory
  125.     int x, y;
  126.     x = ColToX(c);
  127.     y = RowToY(r);
  128.  
  129.     ClearRect(x, y-cHeight+1, _width - x, cHeight);
  130.   }
  131.  
  132. //=================>>> vTextCanvasPane::ClearToEnd <<<======================
  133.   void vTextCanvasPane::ClearToEnd(const int r, const int c)
  134.   {
  135.     // Clear text from r,c down to end of screen
  136.     SysDebug2(Text,"vTextCanvasPane::ClearToEnd(r:%d, c: %d)\n",r,c)
  137.  
  138.     ClearRow(r,c);
  139.     for (int row = r+1 ; row < maxRows ; ++row)
  140.       ClearRow(row,0);
  141.  
  142.     GotoRC(r,c);
  143.   }
  144.  
  145. //=================>>> vTextCanvasPane::DrawTextCursor <<<=================
  146. // cursor management
  147.   void vTextCanvasPane::DrawTextCursor(int r, int c)
  148.   {
  149.     // if window doesn't have focus then cursors don't work
  150.     // and we just have to set the caretOn flag
  151.     if (WinQueryFocus(HWND_DESKTOP) != _drawCanvas)
  152.     {
  153.       // window does not have focus so only update cursor status
  154.       if (r < 0 )     // This is how to turn off the cursor
  155.         caretOn = 0;
  156.       else
  157.         caretOn = 1;
  158.     }
  159.     else
  160.     {
  161.       // window has focus
  162.       // check if it has been created, punt if it hasn't
  163.       if ( caretWin != 0 )
  164.       {
  165.         // kill cursor if in another window
  166.         if ( caretWin != _drawCanvas )
  167.         {
  168.           WinShowCursor (caretWin, FALSE);
  169.           WinDestroyCursor(caretWin);
  170.           caretWin = 0;
  171.         }
  172.       }
  173.  
  174.       // create cursor for pane if doesn't exist
  175.       // but make sure pane has the focus
  176.       if ( caretWin == 0 )
  177.       {
  178.         int tw = TextWidth("X");
  179. #ifdef UNDERSCORE_CARET
  180.         WinCreateCursor(_drawCanvas, 0, 0, tw, 3, CURSOR_FRAME | CURSOR_FLASH, NULL);
  181. #else
  182.         WinCreateCursor(_drawCanvas, 0, 0, tw, 3, CURSOR_SOLID | CURSOR_FLASH, NULL);
  183. #endif
  184.         caretWin = _drawCanvas;
  185.         caretOn = 0;  // cursor is initially invisible
  186.       }
  187.  
  188.       if (r < 0 )     // This is how to turn off the cursor
  189.       {
  190.         if (caretOn)      // we will turn caret off, but only once
  191.         {
  192.           WinShowCursor (_drawCanvas, FALSE);
  193.       caretOn = 0;
  194.         }
  195.         return;
  196.       }
  197.  
  198.       if (!caretOn)       // we will turn caret on, but only once
  199.       {
  200.         caretOn = 1;
  201.         WinShowCursor (_drawCanvas, TRUE);
  202.       }
  203.  
  204.       // we need to convert the target coords which are in V Space
  205.       // to OS/2 Device Space
  206.       POINTL XY = {ColToX(c), RowToY(r)};
  207. /*
  208.       HPS _hdc = _cpDC->handleDC();
  209.       // (HPS, source, target, num points, array of points)
  210.       GpiConvert(_hdc, CVTC_WORLD, CVTC_DEVICE, 1, &XY);
  211. */
  212.       _cpDC->MapToOS2(&XY);
  213.  
  214.       WinCreateCursor (_drawCanvas, XY.x, XY.y,
  215.         0, 0, CURSOR_SETPOS, NULL);
  216.     }
  217.   }
  218.  
  219.   //======================>>> vTextCanvasPane::DrawChar <<<======================
  220.   void vTextCanvasPane::DrawChar(const char chr, const ChrAttr attr)
  221.   {
  222.     // Overwrite a char at current cursor, incr cursor
  223.     char copy[2];    // for a copy
  224.     copy[0] = chr; copy[1] = 0;
  225.     SysDebug1(Text,"vTextCanvasPane::DrawChar(chr:%c)\n",chr)
  226.  
  227.     ScrChar(curRow,curCol) = chr ;
  228.     ScrAttr(curRow,curCol) = attr;
  229.  
  230.     // for now, assume just reverse or normal on WHOLE row
  231.     if (attr != ChNormal)        // normal or with attributes?
  232.       vCanvasPane::DrawAttrText(ColToX(curCol), RowToY(curRow), copy, attr);
  233.     else
  234.       vCanvasPane::DrawText(ColToX(curCol), RowToY(curRow), copy);
  235.  
  236.     if (++curCol >= maxCols)
  237.       curCol = maxCols - 1;
  238.     GotoRC(curRow, curCol);
  239.   }
  240.  
  241. //======================>>> vTextCanvasPane::DrawText <<<======================
  242.   void vTextCanvasPane::DrawText(const char* text)
  243.   {
  244.     DoDrawText(text, ChNormal);    // Draw normal text
  245.   }
  246.  
  247. //======================>>> vTextCanvasPane::DrawAttrText <<<======================
  248.   void vTextCanvasPane::DrawAttrText(const char* text, const ChrAttr attr)
  249.   {
  250.     DoDrawText(text, attr);    // Draw reverse text
  251.   }
  252.  
  253. //======================>>> vTextCanvasPane::DoDrawText <<<======================
  254.   void vTextCanvasPane::DoDrawText(const char* text, const ChrAttr attr)
  255.   {
  256.     // Draw scrolling  text starting at current r,c
  257.     if (!text || !*text)
  258.       return;
  259.  
  260.     int startC = curCol;
  261.     int needsFinalDraw = 0;
  262.     SysDebug3(Text,"vTextCanvasPane::DrawText(%s)[r=%d,c=%d]\n",text,curRow,startC)
  263.  
  264.     for (int cc = 0 ; cc < curCol ; ++cc)  // change 0's to blanks if in middle of row
  265.     {
  266.       if (ScrChar(curRow,cc) == 0)
  267.       {
  268.         ScrChar(curRow,cc) = ' ';
  269.         ScrAttr(curRow,cc) = ChNormal;
  270.       }
  271.     }
  272.  
  273.     for (const char* cp = text ; *cp != 0 ; ++cp)
  274.     {
  275.       if (*cp == '\n')        // new lines take special treatment
  276.       {
  277.         // Terminate current row with 0
  278.         ScrChar(curRow,curCol) = 0;
  279.         ScrAttr(curRow,curCol) = attr;
  280.         // And draw row on the screen!
  281.         DrawTextScr(curRow, startC, ScrAddr(curRow,startC));
  282.         startC = curCol = 0;        // reset column to 0
  283.         ++curRow;            // move to the next row
  284.         needsFinalDraw = 0;        // Don't need final draw
  285.         // Next row is empty
  286.         ScrChar(curRow,curCol) = 0;
  287.         ScrAttr(curRow,curCol) = ChNormal;
  288.         if (curRow >= maxRows)    // see if off bottom
  289.         {
  290.           ScrollText(1);        // scroll up 1 row
  291.     }
  292.       }
  293.       else if (curCol < maxCols)    // overwrite current line
  294.       {
  295.         ScrChar(curRow,curCol) = *cp;
  296.         ScrAttr(curRow,curCol) = attr;
  297.         ++curCol;
  298.         needsFinalDraw = 1;        // need final draw
  299.       }
  300.     }
  301.  
  302.     if (needsFinalDraw)
  303.       DrawTextScr(curRow,startC,ScrAddr(curRow,startC));
  304.  
  305.     GotoRC(curRow,curCol);
  306.   }
  307.  
  308. //======================>>> vTextCanvasPane::DrawTextScr <<<======================
  309.   void vTextCanvasPane::DrawTextScr(int r, int c, dChar* txt)
  310.   {
  311.     char copy[MAX_COLS];    // for a copy
  312.     char* to = copy;
  313.     ChrAttr curAttr = txt->attr;  // initial attribute
  314.     int curCol = c;
  315.     int startCol = c;
  316.  
  317.     for (dChar* dcp = txt ; dcp->chr != 0 ; ++dcp)
  318.     {
  319.       if (dcp->attr != curAttr)    // changing attr - need to show what
  320.       {                // we've built so far
  321.         *to = 0;            // terminate
  322.         if (curAttr != ChNormal)    // normal or with attributes?
  323.         {
  324.           vCanvasPane::DrawAttrText(ColToX(startCol), RowToY(r),
  325.         copy, curAttr);
  326.     }
  327.     else
  328.     {
  329.       vCanvasPane::DrawText(ColToX(startCol), RowToY(r), copy);
  330.     }
  331.     // Now resetup for next portion of the row
  332.     to = copy;            // restart buffer
  333.     curAttr = dcp->attr;        // new attribute
  334.     startCol = curCol;        // and new start column
  335.     // fall through for rest of the row
  336.       }
  337.       *to++ = dcp->chr;
  338.       curCol++;
  339.     }
  340.     *to = 0;
  341.     // write rest of the row
  342.     if (copy[0] != 0)            // don't bother with empty row
  343.     {
  344.       if (curAttr != ChNormal)    // normal or with attributes?
  345.       {
  346.         vCanvasPane::DrawAttrText(ColToX(startCol), RowToY(r),
  347.           copy, curAttr);
  348.       }
  349.       else
  350.       {
  351.         vCanvasPane::DrawText(ColToX(startCol), RowToY(r), copy);
  352.       }
  353.     }
  354.   }
  355.  
  356. //=====================>>> vTextCanvasPane::EnterEV <<<==========================
  357.   void vTextCanvasPane::EnterEV()
  358.   {
  359.     SysDebug2(CmdEvents,"vTextCanvasPane::EnterEV RC(%u,%u))\n", curRow,curCol)
  360.     // when gaining focus, we need to show the cursor if it was previously
  361.     // set since the cursor was destroyed when the window lost focus
  362.     _hasFocus = 1;
  363.     if (caretOn)
  364.     {
  365.       DrawTextCursor(curRow,curCol);
  366.     }
  367.     EnterFocus();        // call the virtual function
  368.   }
  369.  
  370. //=====================>>> vCanvasPane::LeaveEV <<<==========================
  371.   void vTextCanvasPane::LeaveEV(void)
  372.   {
  373.     SysDebug2(CmdEvents,"vTextCanvasPane::LeaveEV RC(%u,%u))\n", curRow,curCol)
  374.  
  375.     if (!_hasFocus)       // don't double leave focus
  376.       return;
  377.  
  378.     _hasFocus = 0;
  379.  
  380.     if (caretWin == _drawCanvas)   // We have a created caret
  381.     {
  382.       WinShowCursor (_drawCanvas, FALSE);
  383.       WinDestroyCursor (_drawCanvas);
  384.       caretWin = 0;
  385.     }
  386.  
  387.     LeaveFocus();   // call the virtual function
  388.   }
  389.  
  390. //======================>>> vTextCanvasPane::FontChanged <<<======================
  391.   void vTextCanvasPane::FontChanged(VCONST vFont& newfont)
  392.   {
  393.     // The font has changed, so we must recalculate everything
  394.  
  395. //1.18?    Clear();            // 1.18 - match X version
  396.     ResizeText();
  397.   }
  398.  
  399. //======================>>> vTextCanvasPane::GotoRC <<<======================
  400. // Move cursor to row, col
  401.   void vTextCanvasPane::GotoRC(const int r, const int c)
  402.   {
  403.     // First, a sanity check
  404.     int row = (r < 0) ? 0 : r;
  405.     int col = (c < 0) ? 0 : c;
  406.  
  407.     if (row >= maxRows)
  408.       row = maxRows - 1;
  409.     if (col >= maxCols)
  410.       col = maxCols - 1;
  411.  
  412.     curRow = row;
  413.     curCol = col;
  414.  
  415.     // have to be sure column is blank filled if moved to new column
  416.     for (int cc = 0 ; cc < col ; ++cc)
  417.     {
  418.       if (ScrChar(row,cc) == 0)
  419.       {
  420.         ScrChar(row,cc) = ' ';
  421.         ScrAttr(row,cc) = ChNormal;
  422.       }
  423.     }
  424.     DrawTextCursor(curRow, curCol);        // draw the cursor to here
  425.   }
  426.  
  427. //======================>>> vTextCanvasPane::MouseDown <<<======================
  428.   void vTextCanvasPane::MouseDown(int x, int y, int button)
  429.   {
  430.     // Map xy to text positions, call alternate mouse down
  431.     TextMouseDown(YToRow(y), XToCol(x), button);
  432.   }
  433.  
  434. //========================>>> vTextCanvasPane::MouseUp <<<======================
  435.   void vTextCanvasPane::MouseUp(int x, int y, int button)
  436.   {
  437.     // Map xy to text positions, call alternate mouse up
  438.     TextMouseUp(YToRow(y), XToCol(x), button);
  439.   }
  440.  
  441. //======================>>> vTextCanvasPane::MouseMove <<<======================
  442.   void vTextCanvasPane::MouseMove(int x, int y, int button)
  443.   {
  444.     // Map xy to text positions, call alternate mouse Move
  445.     TextMouseMove(YToRow(y), XToCol(x), button);
  446.   }
  447.  
  448. //=========================>>> vTextCanvasPane::Redraw <<<======================
  449.   void vTextCanvasPane::Redraw(int x, int y, int width, int height)
  450.   {
  451.     if (maxRows < 0)        // This is the FIRST redraw
  452.       {
  453.     ResizeText();        // resize the text!
  454.     return;            // don't redraw twice!
  455.       }
  456. #ifdef vDEBUG        // Don't have a SysDebug4 macro, so do it by hand
  457.     if (DebugState.WindowEvents && DebugState.System)
  458.     printf("vTextCanvasPane::Redraw(x=%d, y=%d, w=%d, h=%d)\n",
  459.           x,y,width,height);
  460. #endif
  461.     if (!_cursorSet)
  462.       {
  463.     SetCursor(VC_IBar);        // Change here
  464.     _cursorSet = 1;
  465.       }
  466.     // OK, do a REALLY stupid redraw
  467.     for (int r = 0 ; r < maxRows ; ++r)
  468.     DrawTextScr(r,0,ScrAddr(r,0));
  469.   }
  470.  
  471. //===================>>> vTextCanvasPane::ResizeText <<<======================
  472.   void vTextCanvasPane::ResizeText(const int rows, const int cols)
  473.   {
  474.     // This one is overridable so user can pick up new size
  475.     SysDebug2(WindowEvents,"vTextCanvasPane::ResizeText(%d,%d)\n",rows,cols)
  476.   }
  477.  
  478.   //===================>>> vTextCanvasPane::SetTextRowsCols <<<======================
  479.   void vTextCanvasPane::SetTextRowsCols(int rows, int cols)
  480.   {
  481.     int newheight = (rows * cHeight) + (2*MARGIN);
  482.     int newwidth = (cols * cWidth) + (2*MARGIN);
  483.     SetWidthHeight(newwidth, newheight);
  484.   }
  485.  
  486. //===================>>> vTextCanvasPane::ResizeText <<<======================
  487.   void vTextCanvasPane::ResizeText(void)
  488.   {
  489.     // determine how many rows and columns we have
  490.     cHeight = TextHeight(cAscent, cDescent);
  491.     if (cHeight == 0)
  492.       cHeight = 1;
  493.     cWidth  = TextWidth("m");                     // Use "c" as average char
  494.  
  495.     maxRows = (_height-(2*MARGIN)) / cHeight;     // how many rows
  496.     if (maxRows < 1)
  497.       maxRows = 1;
  498.  
  499.     if (maxRows > rowsAllocated)
  500.       maxRows = rowsAllocated;
  501.  
  502.     maxCols = (_width-(2*MARGIN)) / cWidth;
  503.     if (maxCols < 1)
  504.       maxCols = 1;
  505.  
  506.     if (maxCols >= (colsAllocated - 1))
  507.       maxCols = colsAllocated - 2;        // leave room for 0 terminator
  508.  
  509.     if (curRow > maxRows)            // sanity check
  510.       curRow = 0;
  511.     if (curCol > maxCols)
  512.       curCol = 0;
  513.  
  514. // 1.18? Clear();                                 // 1.18 Match X version.
  515.     ResizeText(maxRows,maxCols);
  516.     Redraw(0,0,_width,_height);            // force a redraw
  517.   }
  518.  
  519. //======================>>> vTextCanvasPane::Resize <<<======================
  520.   void vTextCanvasPane::Resize(int w, int h)
  521.   {
  522.     vCanvasPane::Resize(w,h);
  523.     ResizeText();
  524.   }
  525.  
  526. //======================>>> vTextCanvasPane::ScrollText <<<======================
  527.   void vTextCanvasPane::ScrollText(const int lineCount)
  528.   {
  529.     // scroll text on screen up or down by lineCount
  530.     int count = (lineCount < 0) ? -lineCount : lineCount;    // abs val
  531.     if (count >= maxRows)    // see if doing the whole screen
  532.     {
  533.       Clear();
  534.       if (lineCount < 0)
  535.         GotoRC(maxRows-1,0);
  536.     }
  537.  
  538.     if (lineCount > 0)        // Scroll up -- blank lines at bottom
  539.     {
  540.       int r,c, to;
  541.       // Do the scroll: move all the data up count rows
  542.       for (r = count ; r < maxRows ; ++r)
  543.       {
  544.         to = r - count;    // ScrChar is a macro, so need this
  545.         // copy one row up
  546.         for (c = 0 ; c < maxCols ; ++c)
  547.         {
  548.           ScrChar(to,c) = ScrChar(r,c);
  549.       ScrAttr(to,c) = ScrAttr(r,c);
  550.     }
  551.       }
  552.       curRow = maxRows - count;    // set to bottom used row of screen
  553.       curCol = 0;
  554.       // Now, draw the screen with new rows
  555.       for (r = 0 ; r < curRow ; ++r)
  556.       {
  557.         ClearRowDisplay(r,0);
  558.         DrawTextScr(r,0,ScrAddr(r,0));
  559.       }
  560.       // And clear the rest of the screen
  561.       for (r = curRow ; r < maxRows ; ++r)
  562.       {
  563.         ClearRow(r,0);
  564.       }
  565.     }
  566.     else            // scroll down
  567.     {
  568.       int r,c, to;
  569.       int lastRow = maxRows -1;    // the last row on the screen
  570.       // Do the scroll: move all the data down count rows
  571.       for (r = lastRow - count ; r >= 0 ; --r)
  572.       {
  573.         to = r + count;    // ScrChar is a macro, so need this
  574.         // copy one row down
  575.         for (c = 0 ; c < maxCols ; ++c)
  576.         {
  577.           ScrChar(to,c) = ScrChar(r,c);
  578.       ScrAttr(to,c) = ScrAttr(r,c);
  579.     }
  580.       }
  581.       curRow = count;    // set to topmost used row of screen
  582.       curCol = 0;
  583.  
  584.       // Now, draw the screen with new rows
  585.       for (r = curRow ; r < maxRows ; ++r)
  586.       {
  587.         ClearRowDisplay(r,0);
  588.         DrawTextScr(r,0,ScrAddr(r,0));
  589.       }
  590.       // And clear the top part of the screen
  591.       for (r = 0 ; r < curRow ; ++r)
  592.       {
  593.         ClearRow(r,0);
  594.       }
  595.     }
  596.   }
  597.   
  598. //======================>>> vTextCanvasPane::YToRow <<<======================
  599. // assumes origin is at top left corner
  600.   int vTextCanvasPane::YToRow(int y)
  601.   {
  602.     if (cHeight == 0)
  603.     cHeight = 1;
  604.     int row = (y - MARGIN) / cHeight;
  605.  
  606.     if (row >= maxRows)
  607.     return maxRows - 1;        // adjust for margins
  608.     else if (row < 0)
  609.     return 0;
  610.     else
  611.     return row;
  612.   }
  613.  
  614. //======================>>> vTextCanvasPane::XToCol <<<======================
  615.   int vTextCanvasPane::XToCol(int x)
  616.   {
  617.     if (cWidth == 0)
  618.     cWidth = 1;
  619.     int col = (x - MARGIN) / cWidth;
  620.     if (col >= maxCols)
  621.     return maxCols - 1;        // adjust for margins
  622.     else if (col < 0)
  623.     return 0;
  624.     else
  625.     return col;
  626.   }
  627.