home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / util / edit / jade / src / render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-09  |  21.1 KB  |  782 lines

  1. /* render.c -- System-independant rendering
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.    If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <assert.h>
  24.  
  25. #ifdef HAVE_AMIGA
  26. # ifdef _DCC
  27. #  define GfxBase_DECLARED
  28. # endif
  29. # include <clib/graphics_protos.h>
  30. # include <graphics/gfxbase.h>
  31. # include <graphics/gfxmacros.h>
  32. extern struct GfxBase *GfxBase;
  33. #endif
  34.  
  35. _PR void cursor(VW *, bool);
  36. _PR void pen_to_line(VW *, long);
  37. _PR void pen_to_pos(VW *, long, long);
  38. _PR void pen_to_glyph_pos(VW *, long, long);
  39. _PR void draw_bit(VW *, int, u_char *, int, long, long);
  40. _PR void draw_line(VW *, LINE *, long);
  41. _PR void redraw_all(VW *);
  42. _PR void redraw_region(VW *, POS *, POS *);
  43. _PR void redraw_lines(VW *, long, long);
  44. _PR void redraw_lines_clr(VW *, long, long);
  45. _PR void redraw_line_from(VW *, long, long);
  46. _PR void redraw_rect(VW *, POS *, POS *, bool);
  47. _PR void cut_paste_lines(VW *, long, long);
  48. _PR void draw_message_line(VW *);
  49. _PR void redraw_message(VW *, u_char *, int);
  50. _PR void redraw_cmd_line(VW *, u_char *, u_char *, long, long);
  51. _PR void redraw_cmd_line_from(VW *, u_char *, u_char *, long, long, long);
  52. _PR void cmd_line_cursor(VW *, bool);
  53.  
  54. /* I hope this is enough!? :-| */
  55. static u_char glyph_buf[512];
  56.  
  57. static void
  58. pen_to_cursor(VW *vw)
  59. {
  60.     register int x, y;
  61.     calc_cursor_offset(vw);
  62.     y = vw->vw_FontStart +
  63.     ((vw->vw_CursorPos.pos_Line - vw->vw_StartLine) * vw->vw_FontY);
  64.     x = vw->vw_XStartPix +
  65.     ((vw->vw_LastCursorOffset - vw->vw_StartCol) * vw->vw_FontX);
  66.     if(x < vw->vw_XStartPix)
  67.     x = vw->vw_XStartPix;
  68.     MOVE(vw, x, y);
  69. }
  70.  
  71. void
  72. pen_to_line(VW *vw, long line)
  73. {
  74.     MOVE(vw, vw->vw_XStartPix,
  75.      vw->vw_FontStart + ((line - vw->vw_StartLine) * vw->vw_FontY));
  76. }
  77.  
  78. void
  79. pen_to_pos(VW *vw, long col, long line)
  80. {
  81.     TX *tx = vw->vw_Tx;
  82.     int x, y;
  83.     y = vw->vw_FontStart + ((line - vw->vw_StartLine) * vw->vw_FontY);
  84.     assert(line < tx->tx_NumLines);
  85.     x = vw->vw_XStartPix + ((glyph_col(tx, col, line) - vw->vw_StartCol)
  86.                 * vw->vw_FontX);
  87.     if(x < vw->vw_XStartPix)
  88.     x = vw->vw_XStartPix;
  89.     MOVE(vw, x, y);
  90. }
  91.  
  92. void
  93. pen_to_glyph_pos(VW *vw, long gcol, long line)
  94. {
  95.     int x, y;
  96.     y = vw->vw_FontStart + ((line - vw->vw_StartLine) * vw->vw_FontY);
  97.     x = vw->vw_XStartPix + ((gcol - vw->vw_StartCol) * vw->vw_FontX);
  98.     if(x < vw->vw_XStartPix)
  99.     x = vw->vw_XStartPix;
  100.     MOVE(vw, x, y);
  101. }
  102.  
  103. void
  104. cursor(VW *vw, bool status)
  105. {
  106.     if((vw->vw_Flags & VWFF_SLEEPING) == 0)
  107.     {
  108.     if(vw->vw_Flags & VWFF_STATUS_CURS)
  109.     {
  110.         PEN_X(vw) = vw->vw_XStartPix
  111.             + ((vw->vw_MessageLen < vw->vw_MaxX)
  112.                ? vw->vw_MessageLen
  113.                : (vw->vw_MaxX - 1)) * vw->vw_FontX;
  114.         PEN_Y(vw) = vw->vw_MessageFontY;
  115.         TEXT(vw, P_BLOCK, " ", 1);
  116.     }
  117.     else
  118.     {
  119.         if(vw->vw_CursorPos.pos_Line < vw->vw_StartLine + vw->vw_MaxY)
  120.         {
  121.         int pencol;
  122.         LINE *line = vw->vw_Tx->tx_Lines + vw->vw_CursorPos.pos_Line;
  123.         long cursoff = vw->vw_CursorPos.pos_Col;
  124.         int inblk = cursor_in_block(vw);
  125.         if((status && inblk) || (!status && !inblk))
  126.             pencol = P_TEXT;
  127.         else
  128.             pencol = P_BLOCK;
  129.         pen_to_cursor(vw);
  130.         if((cursoff + 1) >= line->ln_Strlen)
  131.             TEXT(vw, pencol, " ", 1);
  132.         else
  133.             TEXT(vw, pencol, char_glyphs(vw->vw_Tx,
  134.                          line->ln_Line[cursoff]), 1);
  135.         }
  136.     }
  137.     }
  138. }
  139.  
  140. /*
  141.  * draws a section of a line of bytes, beg and end are x ordinates
  142.  */
  143. void
  144. draw_bit(VW *vw, int colour, u_char *str, int slen, long beg, long end)
  145. {
  146.     long startx = vw->vw_StartCol;
  147.     long endx = vw->vw_MaxX + startx + 1;
  148.     long length;
  149.     if(end < startx)
  150.     return;
  151.     if(beg < startx)
  152.     beg = startx;
  153.     if(end > endx)
  154.     end = endx;
  155.     if((length = end - beg) <= 0)
  156.     return;
  157.     slen -= beg;
  158.     if(slen <= 0)
  159.     return;
  160.     if(slen < length)
  161.     length = slen;
  162.     TEXT(vw, colour, str + beg, length);
  163. }
  164.  
  165. static void
  166. draw_block_line(VW *vw, long blockStartCol, long blockEndCol,
  167.         long drawEndCol, bool useBEC)
  168. {
  169.     int xend = ((drawEndCol - vw->vw_StartCol) * vw->vw_FontX)
  170.            + vw->vw_XStartPix;
  171.     if(PEN_X(vw) < vw->vw_XEndPix)
  172.     {
  173.     int rectblocks = vw->vw_Flags & VWFF_RECTBLOCKS;
  174.     if(useBEC || rectblocks)
  175.     {
  176.         int xblkend = ((blockEndCol - vw->vw_StartCol)
  177.                * vw->vw_FontX) + vw->vw_XStartPix;
  178.         if(rectblocks)
  179.         {
  180.         if((((PEN_X(vw) - vw->vw_XStartPix) / vw->vw_FontX)
  181.             + vw->vw_StartCol) < blockStartCol)
  182.         {
  183.             PEN_X(vw) = ((blockStartCol - vw->vw_StartCol)
  184.                  * vw->vw_FontX) + vw->vw_XStartPix;
  185.         }
  186.         }
  187.         if(xblkend >= xend)
  188.         xblkend = xend;
  189.         if(xblkend > PEN_X(vw))
  190.         {
  191.         SET_AREA(vw, PEN_X(vw), PEN_Y(vw) - FONT_ASCENT(vw),
  192.              xblkend - PEN_X(vw), vw->vw_FontY);
  193.         }
  194.     }
  195.     else
  196.     {
  197.         SET_AREA(vw, PEN_X(vw), PEN_Y(vw) - FONT_ASCENT(vw),
  198.                xend - PEN_X(vw), vw->vw_FontY);
  199.     }
  200.     }
  201. }
  202.  
  203. /*
  204.  * pen should be at start of line to draw (line should be cleared first)
  205.  */
  206. void
  207. draw_line(VW *vw, LINE *line, long lineNum)
  208. {
  209.     long glyphs = make_glyph_array(vw->vw_Tx, line->ln_Line, 0,
  210.                    line->ln_Strlen-1, glyph_buf,
  211.                    vw->vw_StartCol, vw->vw_MaxX);
  212.     if(vw->vw_BlockStatus != 0)
  213.     TEXT(vw, P_TEXT, glyph_buf, glyphs);
  214.     else
  215.     {
  216.     long block0col = glyph_col(vw->vw_Tx, vw->vw_BlockS.pos_Col,
  217.                    vw->vw_BlockS.pos_Line);
  218.     long block1col = glyph_col(vw->vw_Tx, vw->vw_BlockE.pos_Col,
  219.                    vw->vw_BlockE.pos_Line);
  220.     u_char *glyph_line = glyph_buf - vw->vw_StartCol;
  221.     long abs_glyphs = glyphs + vw->vw_StartCol;
  222.     if(vw->vw_Flags & VWFF_RECTBLOCKS)
  223.     {
  224.         if(block0col > block1col)
  225.         {
  226.         long tmp;
  227.         tmp = block0col;
  228.         block0col = block1col;
  229.         block1col = tmp;
  230.         }
  231.     }
  232.     switch(line_in_block(vw, lineNum))
  233.     {
  234.     case 0: /* none of line in block */
  235.         TEXT(vw, P_TEXT, glyph_buf, glyphs);
  236.         break;
  237.     case 1: /* whole of line in block */
  238.         TEXT(vw, P_BLOCK, glyph_buf, glyphs);
  239.         draw_block_line(vw, block0col, block1col,
  240.                 vw->vw_StartCol + vw->vw_MaxX, FALSE);
  241.         break;
  242.     case 2: /* start of line in block */
  243.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, 0, block1col);
  244.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
  245.              abs_glyphs);
  246.         draw_block_line(vw, block0col, block1col,
  247.                 vw->vw_StartCol + vw->vw_MaxX, TRUE);
  248.         break;
  249.     case 3: /* end of line in block */
  250.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, 0, block0col);
  251.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
  252.              abs_glyphs);
  253.         draw_block_line(vw, block0col, block1col,
  254.                 vw->vw_StartCol + vw->vw_MaxX, FALSE);
  255.         break;
  256.     case 4: /* middle of line in block */
  257.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, 0, block0col);
  258.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
  259.              block1col);
  260.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
  261.              abs_glyphs);
  262.         draw_block_line(vw, block0col, block1col,
  263.                 vw->vw_StartCol + vw->vw_MaxX, TRUE);
  264.         break;
  265.     }
  266.     }
  267. }
  268.  
  269. /*
  270.  * pen should be at first draw position, draws from character XSTART to the
  271.  * end of the line.
  272.  */
  273. static void
  274. draw_line_part(VW *vw, LINE *line, long lineNum, long xStart,
  275.            long glyph_xStart)
  276. {
  277.     u_char *src = line->ln_Line + xStart;
  278.     u_long srclen = (line->ln_Strlen - 1) - xStart;
  279.     long glyphs = make_glyph_array(vw->vw_Tx, src, glyph_xStart, srclen,
  280.                    glyph_buf, 0,
  281.                    (vw->vw_StartCol+vw->vw_MaxX)-glyph_xStart);
  282.     if(vw->vw_BlockStatus != 0)
  283.     TEXT(vw, P_TEXT, glyph_buf, glyphs);
  284.     else
  285.     {
  286.     long block0col = glyph_col(vw->vw_Tx, vw->vw_BlockS.pos_Col,
  287.                    vw->vw_BlockS.pos_Line);
  288.     long block1col = glyph_col(vw->vw_Tx, vw->vw_BlockE.pos_Col,
  289.                    vw->vw_BlockE.pos_Line);
  290.     u_char *glyph_line = glyph_buf - glyph_xStart;
  291.     long abs_glyphs = glyphs + glyph_xStart;
  292.     if(vw->vw_Flags & VWFF_RECTBLOCKS)
  293.     {
  294.         if(block0col > block1col)
  295.         {
  296.         long tmp;
  297.         tmp = block0col;
  298.         block0col = block1col;
  299.         block1col = tmp;
  300.         }
  301.     }
  302.     switch(line_in_block(vw, lineNum))
  303.     {
  304.     case 0: /* none of line in block */
  305.         TEXT(vw, P_TEXT, glyph_buf, glyphs);
  306.         break;
  307.     case 1: /* whole of line in block */
  308.         TEXT(vw, P_BLOCK, glyph_buf, glyphs);
  309.         draw_block_line(vw, block0col, block1col,
  310.                 vw->vw_MaxX + vw->vw_StartCol, FALSE);
  311.         break;
  312.     case 2: /* start of line in block */
  313.         if(glyph_xStart < block1col)
  314.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, glyph_xStart,
  315.              block1col);
  316.         else
  317.         block1col = glyph_xStart;
  318.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
  319.              abs_glyphs);
  320.         draw_block_line(vw, block0col, block1col,
  321.                 vw->vw_MaxX + vw->vw_StartCol, TRUE);
  322.         break;
  323.     case 3: /* end of line in block */
  324.         if(glyph_xStart < block0col)
  325.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, glyph_xStart,
  326.              block0col);
  327.         else
  328.         block0col = glyph_xStart;
  329.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
  330.              abs_glyphs);
  331.         draw_block_line(vw, block0col, block1col,
  332.                 vw->vw_MaxX + vw->vw_StartCol, FALSE);
  333.         break;
  334.     case 4: /* middle of line in block */
  335.         if(glyph_xStart < block0col)
  336.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, glyph_xStart,
  337.              block0col);
  338.         else
  339.         block0col = glyph_xStart;
  340.         if(block0col < block1col)
  341.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
  342.              block1col);
  343.         else
  344.         block1col = block0col;
  345.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
  346.              abs_glyphs);
  347.         draw_block_line(vw, block0col, block1col,
  348.                 vw->vw_MaxX + vw->vw_StartCol, TRUE);
  349.         break;
  350.     }
  351.     }
  352. }
  353.  
  354. #ifdef HAVE_X11
  355. /*
  356.  * pen should be at first draw position
  357.  * The XSTART and XEND are *glyph* indexes -- the physical position on the
  358.  * screen.
  359.  */
  360. static void
  361. draw_line_glyph_length(VW *vw, LINE *line, long lineNum, long xStart, long xEnd)
  362. {
  363.     long glyphs;
  364.     if(xStart < vw->vw_StartCol)
  365.     xStart = vw->vw_StartCol;
  366.     if(xEnd >= (vw->vw_StartCol + vw->vw_MaxX))
  367.     xEnd = (vw->vw_StartCol + vw->vw_MaxX) - 1;
  368.     glyphs = make_glyph_array(vw->vw_Tx, line->ln_Line, 0, line->ln_Strlen-1,
  369.                   glyph_buf, xStart, xEnd - xStart);
  370.     if(vw->vw_BlockStatus != 0)
  371.     TEXT(vw, P_TEXT, glyph_buf, glyphs);
  372.     else
  373.     {
  374.     long block0col = glyph_col(vw->vw_Tx, vw->vw_BlockS.pos_Col,
  375.                    vw->vw_BlockS.pos_Line);
  376.     long block1col = glyph_col(vw->vw_Tx, vw->vw_BlockE.pos_Col,
  377.                    vw->vw_BlockE.pos_Line);
  378.     u_char *glyph_line = glyph_buf - xStart;
  379.     long abs_glyphs = glyphs + xStart;
  380.     if(vw->vw_Flags & VWFF_RECTBLOCKS)
  381.     {
  382.         if(block0col > block1col)
  383.         {
  384.         long tmp;
  385.         tmp = block0col;
  386.         block0col = block1col;
  387.         block1col = tmp;
  388.         }
  389.     }
  390.     switch(line_in_block(vw, lineNum))
  391.     {
  392.     case 0: /* none of line in block */
  393.         TEXT(vw, P_TEXT, glyph_buf, glyphs);
  394.         break;
  395.     case 1: /* whole of line in block */
  396.         TEXT(vw, P_BLOCK, glyph_buf, glyphs);
  397.         draw_block_line(vw, block0col, block1col, xEnd, FALSE);
  398.         break;
  399.     case 2: /* start of line in block */
  400.         if(xStart < block1col)
  401.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, xStart,
  402.              block1col);
  403.         else
  404.         block1col = xStart;
  405.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
  406.              abs_glyphs);
  407.         draw_block_line(vw, block0col, block1col, xEnd, TRUE);
  408.         break;
  409.     case 3: /* end of line in block */
  410.         if(xStart < block0col)
  411.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, xStart,
  412.              block0col);
  413.         else
  414.         block0col = xStart;
  415.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
  416.              abs_glyphs);
  417.         draw_block_line(vw, block0col, block1col, xEnd, FALSE);
  418.         break;
  419.     case 4: /* middle of line in block */
  420.         if(xStart < block0col)
  421.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, xStart,
  422.              block0col);
  423.         else
  424.         block0col = xStart;
  425.         if(block0col < block1col)
  426.         draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
  427.              block1col);
  428.         else
  429.         block1col = block0col;
  430.         draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
  431.              abs_glyphs);
  432.         draw_block_line(vw, block0col, block1col, xEnd, TRUE);
  433.         break;
  434.     }
  435.     }
  436. }
  437. #endif /* HAVE_X11 */
  438.  
  439. void
  440. redraw_all(VW *vw)
  441. {
  442.     long linenum = vw->vw_StartLine;
  443.     LINE *line = vw->vw_Tx->tx_Lines + linenum;
  444.     short y = 0;
  445.     CLR_RECT(vw, vw->vw_XStartPix, vw->vw_YStartPix,
  446.          vw->vw_XEndPix, vw->vw_YEndPix);
  447.     while((y < vw->vw_MaxY) && (linenum < vw->vw_Tx->tx_NumLines))
  448.     {
  449.     pen_to_line(vw, linenum);
  450.     draw_line(vw, line, linenum);
  451.     y++;
  452.     linenum++;
  453.     line++;
  454.     }
  455. }
  456.  
  457. void
  458. redraw_region(VW *vw, POS *start, POS *end)
  459. {
  460.     long linenum = start->pos_Line;
  461.     LINE *line = vw->vw_Tx->tx_Lines + linenum;
  462.     short y = linenum - vw->vw_StartLine;
  463.     short yend = end->pos_Line - vw->vw_StartLine + 1;
  464.     int yord = (y * vw->vw_FontY) + vw->vw_YStartPix;
  465.     if(POS_EQUAL_P(start, end))
  466.     return;
  467.     if(yend > vw->vw_MaxY)
  468.     yend = vw->vw_MaxY;
  469.     if((y >= 0) && (y < yend))
  470.     {
  471.     long gcol = glyph_col(vw->vw_Tx, start->pos_Col, start->pos_Line);
  472.     long tmp = gcol - vw->vw_StartCol;
  473.     if(tmp < 0)
  474.     {
  475.         gcol = vw->vw_StartCol;
  476.         start->pos_Col = char_col(vw->vw_Tx, gcol, start->pos_Line);
  477.         tmp = 0;
  478.     }
  479.     CLR_RECT(vw, (tmp * vw->vw_FontX) + vw->vw_XStartPix,
  480.          yord, vw->vw_XEndPix, yord + vw->vw_FontY);
  481.     if(linenum < vw->vw_Tx->tx_NumLines)
  482.     {
  483.         pen_to_glyph_pos(vw, gcol, linenum);
  484.         draw_line_part(vw, line, linenum, start->pos_Col, gcol);
  485.     }
  486.     line++;
  487.     linenum++;
  488.     y++;
  489.     yord += vw->vw_FontY;
  490.     }
  491.     else
  492.     {
  493.     y = 0;
  494.     yord = vw->vw_YStartPix;
  495.     linenum = vw->vw_StartLine;
  496.     line = vw->vw_Tx->tx_Lines + linenum;
  497.     }
  498.     if(y < yend)
  499.     {
  500.     CLR_RECT(vw, vw->vw_XStartPix, yord, vw->vw_XEndPix,
  501.           vw->vw_YStartPix + (yend * vw->vw_FontY));
  502.     while((y < yend) && (linenum < vw->vw_Tx->tx_NumLines))
  503.     {
  504.         pen_to_line(vw, linenum);
  505.         draw_line(vw, line, linenum);
  506.         y++;
  507.         linenum++;
  508.         line++;
  509.     }
  510.     }
  511. }
  512.  
  513. /*
  514.  * DOES NOT clear the drawing area
  515.  */
  516. void
  517. redraw_lines(VW *vw, long startLine, long endLine)
  518. {
  519.     LINE *line = vw->vw_Tx->tx_Lines;
  520.     short y;
  521.     if(startLine < vw->vw_StartLine)
  522.     startLine = vw->vw_StartLine;
  523.     y = startLine - vw->vw_StartLine;
  524.     line += startLine;
  525.     if(endLine > vw->vw_Tx->tx_NumLines)
  526.     endLine = vw->vw_Tx->tx_NumLines;
  527.     endLine -= vw->vw_StartLine;
  528.     if(endLine > vw->vw_MaxY)
  529.     endLine = vw->vw_MaxY;
  530.     while(y < endLine)
  531.     {
  532.     pen_to_line(vw, startLine);
  533.     draw_line(vw, line, startLine);
  534.     startLine++;
  535.     y++;
  536.     line++;
  537.     }
  538. }
  539.  
  540. void
  541. redraw_lines_clr(VW *vw, long startLine, long endLine)
  542. {
  543.     LINE *line = vw->vw_Tx->tx_Lines;
  544.     short y;
  545.     endLine++;
  546.     if((endLine <= vw->vw_StartLine)
  547.        || (startLine > (vw->vw_StartLine + vw->vw_MaxY)))
  548.     {
  549.     return;
  550.     }
  551.     if(startLine < vw->vw_StartLine)
  552.     startLine = vw->vw_StartLine;
  553.     y = startLine - vw->vw_StartLine;
  554.     line += startLine;
  555.     if(endLine > vw->vw_Tx->tx_NumLines)
  556.     endLine = vw->vw_Tx->tx_NumLines;
  557.     endLine -= vw->vw_StartLine;
  558.     if(endLine > vw->vw_MaxY)
  559.     endLine = vw->vw_MaxY;
  560.     CLR_RECT(vw, vw->vw_XStartPix, (y * vw->vw_FontY) + vw->vw_YStartPix,
  561.           vw->vw_XEndPix, (endLine * vw->vw_FontY) + vw->vw_YStartPix);
  562.     while(y < endLine)
  563.     {
  564.     pen_to_line(vw, startLine);
  565.     draw_line(vw, line, startLine);
  566.     startLine++;
  567.     y++;
  568.     line++;
  569.     }
  570. }
  571.  
  572. void
  573. redraw_line_from(VW *vw, long col, long lineNum)
  574. {
  575.     if((lineNum >= vw->vw_StartLine)
  576.        && (lineNum < vw->vw_StartLine + vw->vw_MaxY))
  577.     {
  578.     long gcol = glyph_col(vw->vw_Tx, col, lineNum);
  579.     int yord = ((lineNum - vw->vw_StartLine) * vw->vw_FontY)
  580.            + vw->vw_YStartPix;
  581.     long tmp = gcol - vw->vw_StartCol;
  582.     if(tmp < 0)
  583.     {
  584.         gcol = vw->vw_StartCol;
  585.         col = char_col(vw->vw_Tx, gcol, lineNum);
  586.         tmp = 0;
  587.     }
  588.     CLR_RECT(vw, vw->vw_XStartPix + (tmp * vw->vw_FontX),
  589.          yord, vw->vw_XEndPix, yord + vw->vw_FontY);
  590.     pen_to_glyph_pos(vw, gcol, lineNum);
  591.     draw_line_part(vw, vw->vw_Tx->tx_Lines + lineNum, lineNum, col, gcol);
  592.     }
  593. }
  594.  
  595. #ifdef HAVE_X11
  596. /*
  597.  * Assumes (start, end) is valid AND totally viewable (ie, no checks, no
  598.  * clipping). Should be ok since this is meant for Expose type events
  599.  * start is probably trashed
  600.  * `gapBlank' says whether or not I need to clear the space I'm drawing into.
  601.  * These coordinates are *GLYPH* coordinates.
  602.  */
  603. void
  604. redraw_rect(VW *vw, POS *start, POS *end, bool gapBlank)
  605. {
  606.     TX *tx = vw->vw_Tx;
  607.     LINE *line = tx->tx_Lines + start->pos_Line;
  608.     int yord = ((start->pos_Line - vw->vw_StartLine) * vw->vw_FontY)
  609.            + vw->vw_YStartPix;
  610.     end->pos_Col++;
  611.     end->pos_Line++;
  612.     if(!gapBlank)
  613.     {
  614.     CLR_RECT(vw,
  615.           vw->vw_XStartPix + ((start->pos_Col - vw->vw_StartCol)
  616.                       * vw->vw_FontX),
  617.           yord,
  618.           vw->vw_XStartPix + ((end->pos_Col - vw->vw_StartCol)
  619.                       * vw->vw_FontX),
  620.           ((end->pos_Line - vw->vw_StartLine)
  621.            * vw->vw_FontY) + vw->vw_YStartPix);
  622.     }
  623.     if(end->pos_Line > tx->tx_NumLines)
  624.     end->pos_Line = tx->tx_NumLines;
  625.     while(end->pos_Line > start->pos_Line)
  626.     {
  627.     pen_to_glyph_pos(vw, start->pos_Col, start->pos_Line);
  628.     draw_line_glyph_length(vw, line, start->pos_Line, start->pos_Col,
  629.                    end->pos_Col + 1);
  630.     line++;
  631.     start->pos_Line++;
  632.     }
  633. }
  634. #endif /* HAVE_X11 */
  635.  
  636. /*
  637.  * Copies from srcLine to bottom of screen to dstLine
  638.  */
  639. void
  640. cut_paste_lines(VW *vw, long srcLine, long dstLine)
  641. {
  642.     int xsrc, ysrc, xwth, yht, xdst, ydst;
  643.     int ybottom = vw->vw_YStartPix + (vw->vw_MaxY * vw->vw_FontY);
  644.     long lastline = vw->vw_StartLine + vw->vw_MaxY;
  645.     /* number of lines which are not blank. */
  646.     int lastdisp = (vw->vw_Tx->tx_NumLines - vw->vw_Tx->tx_ModDelta)
  647.            - vw->vw_LastDisplayOrigin.pos_Line;
  648.     if(srcLine < vw->vw_StartLine)
  649.     srcLine = vw->vw_StartLine;
  650.     if(dstLine < vw->vw_StartLine)
  651.     dstLine = vw->vw_StartLine;
  652. #if 0
  653.     if(srcLine >= lastline)
  654.     srcLine = lastline - 1;
  655. #endif
  656.     if(dstLine >= lastline)
  657.     return;
  658.     if(srcLine == dstLine)
  659.     return;
  660.     xsrc = vw->vw_XStartPix;
  661.     xwth = vw->vw_XWidthPix;
  662.     xdst = vw->vw_XStartPix;
  663.     ysrc = vw->vw_YStartPix + ((srcLine - vw->vw_StartLine) * vw->vw_FontY);
  664.     ydst = vw->vw_YStartPix + ((dstLine - vw->vw_StartLine) * vw->vw_FontY);
  665.     if(ysrc > ydst)
  666.     {
  667.     if(lastdisp >= vw->vw_MaxY)
  668.         yht = ybottom - ysrc;
  669.     else
  670.     {
  671.         yht = (vw->vw_YStartPix + (lastdisp * vw->vw_FontY)) - ydst;
  672.         /* I'm not sure about this? should `ysrc' be replaced by `ydst'? */
  673.         if((yht + ysrc) > ybottom)
  674.         yht = ybottom - ysrc;
  675.     }
  676.     }
  677.     else
  678.     {
  679.     if(lastdisp >= vw->vw_MaxY)
  680.         yht = ybottom - ydst;
  681.     else
  682.     {
  683.         yht = (vw->vw_YStartPix + (lastdisp * vw->vw_FontY)) - ysrc;
  684.         if((yht + ydst) > ybottom)
  685.         yht = ybottom - ydst;
  686.     }
  687.     }
  688.     if((xwth > 0) && (yht > 0))
  689.     COPY_AREA(vw, xsrc, ysrc, xwth, yht, xdst, ydst);
  690.     if(ysrc > ydst)
  691.     {
  692.     /* stuff we weren't able to blit.  */
  693.     long firstline = lastline - (srcLine - dstLine);
  694.     if(firstline < vw->vw_Tx->tx_NumLines)
  695.     {
  696.         redraw_lines_clr(vw, firstline, lastline);
  697.         if(lastline > vw->vw_Tx->tx_NumLines)
  698.         {
  699.         CLR_RECT(vw, vw->vw_XStartPix,
  700.              (vw->vw_YStartPix + (vw->vw_FontY
  701.                           * (vw->vw_Tx->tx_NumLines
  702.                          - vw->vw_StartLine))),
  703.              vw->vw_XEndPix, ybottom);
  704.         }
  705.     }
  706.     else
  707.     {
  708.         CLR_RECT(vw, vw->vw_XStartPix,
  709.              (vw->vw_YStartPix + (vw->vw_FontY
  710.                       * (firstline
  711.                          - vw->vw_StartLine))),
  712.              vw->vw_XEndPix, ybottom);
  713.     }
  714.     }
  715. }
  716.  
  717. void
  718. draw_message_line(VW *vw)
  719. {
  720.     DRAW_LINE(vw, vw->vw_XStartPix, vw->vw_MessageLineY,
  721.           vw->vw_XEndPix, vw->vw_MessageLineY);
  722. }
  723.  
  724. void
  725. redraw_message(VW *vw, u_char *str, int len)
  726. {
  727.     if(len >= vw->vw_MaxX - 1)
  728.     len = vw->vw_MaxX - 1;
  729.     MOVE(vw, vw->vw_XStartPix, vw->vw_MessageFontY);
  730.     TEXT(vw, P_TEXT, str, len);
  731.     if(len != vw->vw_MaxX - 1)
  732.     {
  733.     CLR_AREA(vw, PEN_X(vw), vw->vw_MessageFontY - FONT_ASCENT(vw),
  734.          vw->vw_XEndPix - PEN_X(vw), vw->vw_FontY);
  735.     }
  736. }
  737.  
  738. void
  739. redraw_cmd_line(VW *vw, u_char *prompt, u_char *cmdLine, long promptLen,
  740.         long cmdLen)
  741. {
  742.     CLR_AREA(vw, vw->vw_XStartPix, vw->vw_MessageFontY - FONT_ASCENT(vw),
  743.          vw->vw_XWidthPix, vw->vw_FontY);
  744.     MOVE(vw, vw->vw_XStartPix, vw->vw_MessageFontY);
  745.     draw_bit(vw, P_TEXT, prompt, 100000, 0, promptLen);
  746.     draw_bit(vw, P_TEXT, cmdLine - promptLen, 100000, promptLen,
  747.         cmdLen + promptLen);
  748. }
  749.  
  750. void
  751. redraw_cmd_line_from(VW *vw, u_char *prompt, u_char *cmdLine, long promptLen,
  752.              long cmdLen, long startPos)
  753. {
  754.     if(startPos < vw->vw_StartCol)
  755.     startPos = vw->vw_StartCol;
  756.     if(startPos < (vw->vw_StartCol + vw->vw_MaxX))
  757.     {
  758.     int xord = vw->vw_XStartPix + (startPos * vw->vw_FontX);
  759.     CLR_AREA(vw, xord, vw->vw_MessageFontY - FONT_ASCENT(vw),
  760.          vw->vw_XEndPix - xord, vw->vw_FontY);
  761.     MOVE(vw, xord, vw->vw_MessageFontY);
  762.     if(startPos < promptLen)
  763.     {
  764.         draw_bit(vw, P_TEXT, prompt, 100000, startPos, promptLen);
  765.         draw_bit(vw, P_TEXT, cmdLine - promptLen, 100000, promptLen,
  766.             cmdLen + promptLen);
  767.     }
  768.     else
  769.         draw_bit(vw, P_TEXT, cmdLine - promptLen, 100000, startPos,
  770.             cmdLen + promptLen);
  771.     }
  772. }
  773.  
  774. void
  775. cmd_line_cursor(VW *vw, bool status)
  776. {
  777.     PEN_X(vw) = vw->vw_XStartPix
  778.     + ((vw->vw_CursorPos.pos_Col - vw->vw_StartCol) * vw->vw_FontX);
  779.     PEN_Y(vw) = vw->vw_MessageFontY;
  780.     TEXT(vw, (status == CURS_ON) ? P_BLOCK : P_TEXT, " ", 1);
  781. }
  782.