home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume17 / tcl-editor / part06 / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-18  |  12.6 KB  |  571 lines

  1. /* $Header: /nfs/unmvax/faculty/crowley/x/pt/RCS/display.c,v 1.7 1992/03/04 17:07:18 crowley Exp crowley $ */
  2.  
  3. #include <math.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include "pt.h"
  7. #include <X11/StringDefs.h>
  8.  
  9. static int maxLineLength = 1;
  10.  
  11. /* character table for fillLine (in windtext.c) */
  12. char charTable[257];
  13.  
  14. /* screen line buffer */
  15. char screenLine[MAXCOLS];
  16.  
  17. void
  18. drawWindowFast(w, firstRow, lastRow, firstCol, lastCol )
  19.     struct window *w;
  20.     int firstRow, lastRow, firstCol, lastCol;
  21. {
  22.     extern int debug;
  23.  
  24.         fillWindow(w, firstRow, lastRow, firstCol, lastCol );
  25.     banner( w, 1 );
  26. }
  27.  
  28. void
  29. drawWindow(w)
  30.     register struct window *w;
  31. {
  32.     extern int debug;
  33.  
  34.     if( w == NULL )
  35.         return;
  36.     fillWindow(w, 0, w->nRows-1, 0, w->nCols-1);
  37.     banner( w, 1 );
  38. }
  39.  
  40. static char *
  41. FormatTitle( format, w, ff )
  42.     char * format;
  43.         struct window *w;
  44.         struct openFile *ff;
  45. {
  46.     extern char textBuffer[];
  47.     extern char msgBuffer[];
  48.     extern int pathNames;
  49.     extern int overType;
  50.     extern int hypertextOn;
  51.         extern struct openFile *files;
  52.  
  53.     char * to = msgBuffer;
  54.     char * copy_in;
  55.     char ch;
  56.  
  57.     while( (ch = *format++) != '\0' ) {
  58.         if( ch != '%' ) {
  59.             *to++ = ch;
  60.             continue;
  61.         }
  62.         /* read a '%' */
  63.         switch( ch = *format++ ) {
  64.         default:    /* anything, including a literal '%' */
  65.             textBuffer[0] = ch;
  66.             textBuffer[1] = '\0';
  67.             copy_in = textBuffer;
  68.             break;
  69.         case 'n':    /* file name */
  70.             copy_in = &((ff->origName)[pathNames?0:w->nameOffset]);
  71.             break;
  72.         case 'N':    /* full path file name */
  73.             copy_in = &((ff->origName)[0]);
  74.             break;
  75.         case 's':    /* short file name */
  76.             copy_in = &((ff->origName)[w->nameOffset]);
  77.             break;
  78.         case 'c':    /* changed  flag */
  79.             {/* get the change indicator string */
  80.                 char * to = textBuffer;
  81.                 char delimiter = *format++;
  82.                 while( 1 ) {
  83.                     ch = *format++;
  84.                     if( ch == delimiter )
  85.                         break;
  86.                     /* allow for missing delimiters */
  87.                     if( ch == '\0' ) {
  88.                         --format;
  89.                         msg(
  90. "Missing change flag in title format", 1 );
  91.                         break;
  92.                     }
  93.                     *to++ = ch;
  94.                 }
  95.                 *to = '\0';
  96.             }
  97.             if( ff->flags&IS_CHANGED ) {
  98.                 copy_in = textBuffer;
  99.             } else
  100.                 copy_in = "";
  101.             break;
  102.         case 'o':    /* overType flag */
  103.             {/* get the overtype indicator string */
  104.                 char * to = textBuffer;
  105.                 char delimiter = *format++;
  106.                 while( 1 ) {
  107.                     ch = *format++;
  108.                     if( ch == delimiter )
  109.                         break;
  110.                     /* allow for missing delimiters */
  111.                     if( ch == '\0' ) {
  112.                         --format;
  113.                         msg(
  114. "Missing overtype flag in title format", 1 );
  115.                         break;
  116.                     }
  117.                     *to++ = ch;
  118.                 }
  119.                 *to = '\0';
  120.             }
  121.             if( overType ) {
  122.                 copy_in = textBuffer;
  123.             } else
  124.                 copy_in = "";
  125.             break;
  126.         case 'r':    /* readOnly flag */
  127.             {/* get the readOnly indicator string */
  128.                 char * to = textBuffer;
  129.                 char delimiter = *format++;
  130.                 while( 1 ) {
  131.                     ch = *format++;
  132.                     if( ch == delimiter )
  133.                         break;
  134.                     /* allow for missing delimiters */
  135.                     if( ch == '\0' ) {
  136.                         --format;
  137.                         msg(
  138. "Missing read only flag in title format", 1 );
  139.                         break;
  140.                     }
  141.                     *to++ = ch;
  142.                 }
  143.                 *to = '\0';
  144.             }
  145.             if( ff->flags&READ_ONLY ) {
  146.                 copy_in = textBuffer;
  147.             } else
  148.                 copy_in = "";
  149.             break;
  150.         case 'l':    /* beginning line number */
  151.             sprintf( textBuffer, "%d", w->numTopline );
  152.             copy_in = textBuffer;
  153.             break;
  154.         case 'L':    /* ending line number */
  155.             sprintf( textBuffer, "%d", w->numBotline - 1 );
  156.             copy_in = textBuffer;
  157.             break;
  158.         case 'p':    /* beginning position number */
  159.             sprintf( textBuffer, "%d", w->posTopline );
  160.             copy_in = textBuffer;
  161.             break;
  162.         case 'P':    /* ending position number */
  163.             sprintf( textBuffer, "%d", w->posBotline - 1 );
  164.             copy_in = textBuffer;
  165.             break;
  166.         case 'S':    /* file size (in bytes) */
  167.             sprintf( textBuffer, "%d", ff->fileSize );
  168.             copy_in = textBuffer;
  169.             break;
  170.         case 'v':    /* beginning column number */
  171.             sprintf( textBuffer, "%d", w->indent + 1 );
  172.             copy_in = textBuffer;
  173.             break;
  174.         case 'V':    /* ending column number */
  175.             sprintf( textBuffer, "%d", w->indent + w->nCols );
  176.             copy_in = textBuffer;
  177.             break;
  178. #ifdef HYPERTEXT
  179.         case 'M':    /* block map name */
  180.             if( w->blockMap!=NULL && hypertextOn )
  181.                 sprintf( textBuffer, "%s", w->blockMap->name );
  182.             else
  183.                 textBuffer[0] = '\0';
  184.             copy_in = textBuffer;
  185.             break;
  186. #endif
  187.         }
  188.         while( *copy_in != '\0' )
  189.             *to++ = *copy_in++;
  190.     }
  191.     *to = '\0';
  192.     
  193.     return msgBuffer;
  194. }
  195.  
  196. void
  197. banner( w, doSlider )
  198.     register struct window *w;
  199.     int doSlider;
  200. {
  201.     extern int msgInTitleLine;
  202.     extern int debug;
  203.     extern char * titleFormat;
  204.     extern char * iconFormat;
  205.  
  206.     long lp;
  207.         struct openFile *ff;
  208.  
  209.     /* remember that we don't have to draw the banner again */
  210.     msgInTitleLine = 0;
  211.  
  212.     /* guard against calls with a NULL argument */
  213.     if( w == NULL )
  214.         return;
  215.  
  216.     if( w->fileId == -1 ) {
  217.         return;
  218.     } else {
  219.         ff = &(files[w->fileId]);
  220.         lp = ff->fileSize;
  221.     }
  222.     
  223.     /* set the window and icon titles */
  224.     sprintf( textBuffer, "wm title %s {%s}", w->tk_pathname,
  225.             FormatTitle( titleFormat, w, ff) );
  226.     (void)ExecTclCommand( textBuffer );
  227.     sprintf( textBuffer,"wm iconname %s {%s}", w->tk_pathname,
  228.             FormatTitle( iconFormat, w, ff) );
  229.     (void)ExecTclCommand( textBuffer );
  230.  
  231.     if( doSlider )
  232.         SetSlider( w, lp );
  233. }
  234.  
  235. void
  236. SetSlider( w, total )
  237.     struct window *w;
  238.     int total;
  239. {
  240.     extern char msgBuffer[];
  241.  
  242.     int inwindow, first, last;
  243.  
  244.     /* set vertical scroll bar */
  245.     if( total == 0 ) /* guard again zerodivide */
  246.         total = 1;
  247.     first = w->posTopline;
  248.     last = w->posBotline - 2;
  249.     if( last < first )
  250.         last = first;
  251.     inwindow = last - first;
  252.     if( inwindow < 0 )
  253.         inwindow = 0;
  254.     sprintf( msgBuffer, "%s.VScrollAndText.VScroll set %d %d %d %d",
  255.         w->tk_pathname, total, inwindow, first, last );
  256.     (void)ExecTclCommand( msgBuffer );
  257.  
  258.     /* set horizontal scroll bar */
  259.     total = w->nCols;
  260.     if( total < maxLineLength )
  261.         total = maxLineLength;
  262.     if( total <= 0 )
  263.         total = 1;
  264.     inwindow = w->nCols;
  265.     first = w->indent;
  266.     if( first >= total )
  267.         first = total - 1;
  268.     last = w->indent+w->nCols-1;
  269.     if( last < first )
  270.         last = first + 1;
  271.     if( last >= total )
  272.         last = total - 1;
  273.     sprintf( msgBuffer, "%s.SplitterAndHScroll.HScroll set %d %d %d %d",
  274.         w->tk_pathname, total, inwindow, first, last );
  275.     (void)ExecTclCommand( msgBuffer );
  276. }
  277.  
  278. void
  279. fillWindow(w, firstRow, lastRow, firstCol, lastCol)
  280.     register struct window *w;
  281.     int firstRow, lastRow, firstCol, lastCol;
  282. {
  283.     extern int debug;
  284.     extern int hypertextOn;
  285.     extern struct window *selWindow;
  286.     extern Display *MainDisplay;
  287.  
  288.     Offset cp;
  289.     int i, y, row, lineNumber;
  290.     int col1, col2;
  291.     struct fontDataStruct *font;
  292.     int fid;
  293.  
  294.     if( w == NULL )
  295.         return;
  296.  
  297. #ifdef HYPERTEXT
  298.     if( w->file != NULL && !hypertextOn )
  299.         /* a hypertext file but not in hypertext mode */
  300.         fid = w->realFileId;
  301.     else
  302. #endif
  303.         fid = w->fileId;
  304.     
  305.     font = &(w->font);
  306.  
  307.     maxLineLength = 1;    /* reset this count */
  308.  
  309.     /* fill the rows one at a time */
  310.  
  311.     /* initialize */
  312.     cp = w->posTopline;
  313.     lineNumber = w->numTopline;
  314.     y = w->topMargin + font->ascent;
  315.  
  316.     /* skip the rows above the ones we are redrawing */
  317.     for( row = 0; row < firstRow; ++row ) {
  318.         i = 1;
  319.         cp = nextLine( fid, cp, &i);
  320.         y += font->height;
  321.         ++lineNumber;
  322.     }
  323.     
  324.     /* clear the area we are redrawing */
  325.     XClearArea(MainDisplay, w->x_window_id, 0, y - font->ascent,
  326.         Tk_Width(w->tk_text), (lastRow - row + 1)*(font->height),
  327.         False );
  328.         /* 0 width => clear the whole width of the window */
  329.         /* False means: do not generate exposure events */
  330.  
  331.     /* rewrite the lines required */
  332.     for( ; row <= lastRow; ++row ) {
  333.         if( row == firstRow )
  334.             col1 = firstCol;
  335.         else
  336.             col1 = 0;
  337.         if( row == lastRow )
  338.             col2 = lastCol;
  339.         else
  340.             col2 = w->nCols - 1;
  341.         cp = fillLine( w, cp, row, col1, col2, y, 1 );
  342.         if( cp == -1 ) {
  343.             ++row;    /* at least the EOF marker printed out */
  344.             break;
  345.         }
  346.         y += font->height;
  347.         ++lineNumber;
  348.     }
  349.  
  350.     /* count down through the rows we are not drawing */
  351.     for( ; row < w->nRows; ++row ) {
  352.         if( cp == -1 )
  353.             break;
  354.         i = 1;
  355.         cp = nextLine( fid, cp, &i);
  356.         ++lineNumber;
  357.     }
  358.  
  359.     /* If we got to the end of the file we want posBotline to be */
  360.     /* the size of the file (which will be one past the last character */
  361.     /* in the file since we start counting at 0) */
  362.     if( cp == -1 )
  363.         cp = fileSize( w->fileId );
  364.     w->posBotline = cp;
  365.     w->numBotline = lineNumber;
  366. }
  367.  
  368. /* I know I shouldn't use global variables for procedure parameters */
  369. /* but these are called for every single character so I am compromising */
  370. struct window *w;
  371. char *sLine;
  372. GC gc, gc_normal;
  373. int x, y;
  374. int inSelection;
  375. int logicalCol;
  376. int row;
  377. int indent;
  378. Offset cp;
  379. struct fontDataStruct *font;
  380.  
  381. void
  382. DrawString()
  383. {
  384.     extern char screenLine[];
  385.     extern int underlineSelection;
  386.     extern Display *MainDisplay;
  387.     extern int debug;
  388.  
  389.     int char_len, pix_len;
  390.  
  391.     *sLine = '\0';
  392.     char_len = sLine - screenLine;
  393.     pix_len = char_len * font->width;
  394.     if( char_len > 0 ) {
  395.         if( inSelection && (underlineSelection > 0) )
  396.             gc = gc_normal;
  397.         XDrawImageString( MainDisplay, w->x_window_id, gc, x, y,
  398.             screenLine, char_len );
  399.         if( inSelection && (underlineSelection > 0) ) {
  400.             int y2 = y + 1;
  401.             XDrawLine(MainDisplay, w->x_window_id, gc, x, y2,
  402.                             x+pix_len-1, y2);
  403.             if( underlineSelection == 2 )
  404.                 XDrawLine( MainDisplay, w->x_window_id, gc,
  405.                         x, y2+1, x+pix_len-1, y2+1 );
  406.         }
  407.         x += pix_len;
  408.     }
  409.     sLine = screenLine;
  410. }
  411.  
  412. Offset
  413. fillLine(w_in, cp_in, row_in, firstCol, lastCol, y_in, fillToEol)
  414.     struct window *w_in;
  415.     Offset cp_in;
  416.     int row_in, firstCol, lastCol, y_in, fillToEol;
  417. {
  418.     extern struct window *selWindow;
  419.     extern char charTable[];
  420.     extern char screenLine[];
  421.     extern int tabWidth;
  422.     extern int eofChar;
  423.     extern Display *MainDisplay;
  424.     extern Offset selBegin, selEnd;
  425.     extern int hypertextOn;
  426.     extern int getSpanSize;
  427.  
  428.     int uch;
  429.     int tabStop;
  430.     int fid;
  431.     unsigned char *firstByte;
  432.     unsigned char *lastByte;
  433.     char *sLineMax;
  434.     
  435.     /* make these values available to DrawString and CheckForSelection */
  436.     cp = cp_in;
  437.     w = w_in;
  438.     y = y_in;
  439.     row = row_in;
  440.     font = &(w->font);
  441.     
  442. #ifdef HYPERTEXT
  443.     if( w->file != NULL && !hypertextOn )
  444.         /* a hypertext file but not in hypertext mode */
  445.         fid = w->realFileId;
  446.     else
  447. #endif
  448.         fid = w->fileId;
  449.  
  450.     /* set up for the loop */
  451.     inSelection = 0;
  452.     gc_normal = font->gc_normal;
  453.     gc = gc_normal;
  454.     logicalCol = 0;
  455.     indent = w->indent;
  456.     lastCol += indent;
  457.     x = w->leftMargin;
  458.     sLine = screenLine;
  459.     sLineMax = sLine + MAXCOLS - 1;
  460.  
  461.     /* set things up so we will call getSpan first thing */
  462.     firstByte = (unsigned char *)1;
  463.     lastByte = (unsigned char *)0;
  464.     
  465.     /* handle line numbering */
  466.     if( w->lineNumbers && firstCol == 0 ) {
  467.         int ln = row + w->numTopline;
  468.         int i;
  469.         char s[12];
  470.         
  471.         sprintf(s, "%4d:", ln);
  472.         for( i = 0; i < 5; ++i )
  473.             *sLine++ = s[i];
  474.     }
  475.  
  476.     /* loop until we get to the end of the line or the window */
  477.     while( logicalCol <= lastCol ) {
  478.         /****Begin CheckForSelection();****/
  479.         if( selBegin <= cp && cp <= selEnd && w == selWindow ) {
  480.             /* we are inside the selection */
  481.             if( !inSelection ) {
  482.                 DrawString();
  483.                 gc = font->gc_selected;
  484.                 inSelection = 1;
  485.             }
  486.         } else {
  487.             /* we are not inside the selection */
  488.             if( inSelection ) {
  489.                 DrawString();
  490.                 gc = font->gc_normal;
  491.                 inSelection = 0;
  492.             }
  493.         }
  494.         /****End CheckForSelection();****/
  495.         if( firstByte > lastByte ) {
  496.             if( getSpan( fid, cp, &firstByte, &lastByte, 0 ) ) {
  497.                 uch = BLOCK_EOF;
  498.                 goto atEOF;
  499.             }
  500.         }
  501. ++getSpanSize;
  502.         uch = (unsigned char)(*firstByte++);
  503.         ++cp;
  504.         /* check limits of line buffer */
  505.         if( sLine > sLineMax )
  506.             sLine = sLineMax;
  507.         switch( charTable[uch] ) {
  508.         
  509.         case 2:        /* end of file */
  510.     atEOF:
  511.             if( eofChar != -1 )
  512.                 *sLine++ = (char)eofChar;
  513.             cp = -1;    /* indicate end of file written */
  514.             goto endLoop;
  515.  
  516.         case 1:        /* newline -- end of line  */
  517.             *sLine++ = ' ';
  518.             goto endLoop;
  519.  
  520.         case 3:    /* tab */
  521.             tabStop = tabWidth - (logicalCol % tabWidth)
  522.                     + logicalCol;
  523.             if( (sLine+tabWidth) > sLineMax )
  524.                 sLine = sLineMax-tabWidth;
  525.             while( ++logicalCol <= tabStop )
  526.                 if( logicalCol >= indent )
  527.                     *sLine++ = ' ';
  528.             --logicalCol;    /* one ++ too many above */
  529.             break;
  530.  
  531.         case 0:    /* other (one char position) character */
  532.             if( logicalCol++ >= indent ) {
  533.                 *sLine++ = uch;
  534.             }
  535.             break;
  536.  
  537.         }
  538.     }
  539. endLoop:
  540.     /* write out the last part of the text */
  541.     DrawString();
  542.     if( fillToEol )
  543.         /* clear to the end of the line */
  544.         XClearArea(MainDisplay, w->x_window_id, x, y - font->ascent,
  545.             0, font->height, False );
  546.             /* 0 width => clear the whole width of the window */
  547.             /* False means: do not generate exposure events */
  548.  
  549.  
  550.     /* find the end of the line */
  551.     /* only look if we have not already gotten to EOF */
  552.     while( uch != '\n' && uch != BLOCK_EOF ) {
  553.             /* NOTE: */
  554.             /* Since we are postincrementing we could move cp */
  555.             /* two past EOF, check if this is a problem in some */
  556.             /* other place that uses the returned value (cp) */
  557.         uch = getFileByte( fid, cp++ );
  558.         if( uch == '\t' )
  559.             logicalCol += tabWidth - (logicalCol % tabWidth) - 1;
  560.         ++logicalCol;
  561.     }
  562.  
  563.     /* adjust for the NL */
  564.     --logicalCol;
  565.     if( logicalCol > maxLineLength )
  566.         maxLineLength = logicalCol;
  567.  
  568.     return cp;
  569. }
  570.  
  571.