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

  1. /* $Header: /nfs/unmvax/faculty/crowley/x/pt/RCS/search.c,v 1.7 1992/03/04 17:07:18 crowley Exp crowley $ */
  2.  
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include "pt.h"
  7. #include <X11/StringDefs.h>
  8.  
  9. static char searchString[STRINGSIZE];
  10.  
  11. int
  12. searchFor( w, searchMode, str, update, lof )
  13.     struct window *w;
  14.     int searchMode;
  15.     char * str;
  16.     int update;
  17.     int lof;
  18. {
  19.     extern struct window *selWindow;
  20.     extern Offset selBegin, selEnd;
  21.     extern int selMode;
  22.     extern char msgBuffer[];
  23.     extern int ignoreCase;
  24.     extern int debug;
  25.     extern int underlineSelection;
  26.     extern int wrapAroundSearches;
  27.  
  28.     int n, i, linesFromTop, fileId, nLines;
  29.     int patLength;
  30.     int saveUnderlineSelection;
  31.     int wrappedAround = 0;
  32.     Offset cp, cp2, startCp, stopCp;
  33.     char ch, *p, *limit;
  34.     int fid = w->fileId;
  35.     Offset newSelBegin, newSelEnd;
  36.  
  37.     fileId = w->fileId;
  38.  
  39.         if( str != NULL ) {
  40.                 /* get pointers we can change */
  41.                 p = searchString;
  42.                 limit = searchString + STRINGSIZE;
  43.                 while( 1 ) {
  44.                         ch = *str++;
  45.                         /* case insensitive search? */
  46.                         if( isupper(ch) && ignoreCase )
  47.                                 ch = tolower(ch);
  48.                         if( (*p++ = ch) == '\0' )
  49.                                 break;
  50.                         if( p >= limit ) {
  51.                                 *--p = '\0';
  52.                                 break;
  53.                         }
  54.                 }
  55.         }
  56.  
  57.     /* do not allow searching for the empty string */
  58.     if( searchString[0] == '\0' ) {
  59.         sprintf(msgBuffer, "Search string is empty");
  60.         goto errorExit;
  61.     }
  62.  
  63.     /* avoid overflowing msgBuffer */
  64.     n = strlen( searchString );
  65.     if( n > (STRINGSIZE-64) )
  66.         n = STRINGSIZE - 64;
  67.     /* 64 is enough for "Searching circularly for `%s'" */
  68.     sprintf(msgBuffer, "Searching %s for `%s'",
  69.         ((searchMode == 0) ? "forwards" : "backwards"),
  70.         searchString);
  71.     msg( msgBuffer, 1 );
  72.  
  73.     patLength = strlen(searchString);
  74.     nLines = 0;
  75.     cp = fileSize(w->fileId);
  76.     if( searchMode == 1 ) {
  77.         startCp = 0;
  78.         if( w == selWindow )
  79.             stopCp = selBegin - 1;
  80.         else
  81.             stopCp = cp - 1;
  82.     } else {    /* seachMode == 0 */
  83.         stopCp = cp;
  84.         if( w == selWindow ) {
  85.             startCp = selBegin + 1;
  86.             if( startCp >= stopCp ) {    /* already done? */
  87.                 if( wrapAroundSearches )
  88.                     startCp = 0;
  89.                 else
  90.                     goto notFound;
  91.             }
  92.         } else
  93.             startCp = 0;
  94.     }
  95.     linesFromTop = 0;
  96.     /* adjust the line number */
  97.     /* just put in the two while loops and forget the IF test */
  98.     /* at most one of the WHILE loops will actually loop */
  99.     /* adjust for backwards searching */
  100.     cp2 = w->posTopline;
  101.     if( searchMode == 1 ) {
  102.         cp = stopCp + 1;
  103.         if( cp > fileSize(w->fileId) )
  104.             --cp;
  105.     } else {
  106.         cp = startCp - 1;
  107.         if( cp < 0 )
  108.             cp = 0;
  109.     }
  110.     /* normalize cp to the beginning of its line */
  111.     i = -1;
  112.     cp = prevLine( fid, cp, &i );
  113.     while( cp2 < cp ) {
  114.         ++linesFromTop;
  115.         i = 1;
  116.         cp2 = nextLine( fid, cp2, &i );
  117.     }
  118.     while( cp2 > cp ) {
  119.         --linesFromTop;
  120.         i = 1;
  121.         cp2 = prevLine( fid, cp2, &i );
  122.     }
  123.  
  124.     if( searchMode == 0 ) {
  125.         cp = searchSpans(fileId, startCp, stopCp,
  126.             searchString, patLength, &n);
  127.         nLines += n;
  128.         if( wrapAroundSearches && cp == -1 ) {
  129.             wrappedAround = 1;
  130.             cp = searchSpans(fileId, 0L, startCp,
  131.                 searchString, patLength, &n);
  132.             nLines = n;
  133.             linesFromTop = -(selWindow->numTopline);
  134.         }
  135.     } else {
  136.         cp = searchReverseSpans(fileId, startCp, stopCp,
  137.                 searchString, patLength, &n);
  138.         nLines -= n;
  139.         /* a fix so that backwards search from the backwards */
  140.         /* search command is circular if the normal search */
  141.         /* mode is circular */
  142. /********************* DO NOT DO THIS YET ************
  143.  THE PROBLEM IS GETTING THE LINE NUMBERS TO WORK OUT
  144.  FINISH IT LATER
  145.         if( cp == -1 ) {
  146.             wrappedAround = 1;
  147.             cp = searchReverseSpans(fileId, stopCp,
  148.                 fileSize(w->fileId) - patLength,
  149.                 searchString, patLength, &n);
  150.             nLines = n;
  151.             linesFromTop = -(selWindow->numTopline);
  152.         }
  153. *******************************************************/
  154.     }
  155.  
  156.     if( cp != -1 ) {
  157.         if( selWindow != w ) {
  158.             drawSelection( 1 );
  159.             selWindow = w;
  160.         }
  161.         newSelBegin = cp;
  162.         newSelEnd = newSelBegin + patLength - 1;
  163.         selMode = SELCHAR;
  164.     } else
  165.         goto notFound;
  166.  
  167. if( !update ) {
  168.     selBegin = newSelBegin;
  169.     selEnd = newSelEnd;
  170. } else {
  171.     (void)indentToShowSelection(-1);
  172.     saveUnderlineSelection = underlineSelection;
  173.     underlineSelection = 0;
  174.     if( newSelBegin >= selWindow->posBotline
  175.                 || newSelBegin < selWindow->posTopline ) {
  176.         /* remember where we came from */
  177.         selWindow->rowLastline = selWindow->numTopline;
  178.         selBegin = newSelBegin;
  179.         selEnd = newSelEnd;
  180.          n = -1;
  181.          cp2 = selBegin;
  182.         cp2 = prevLine( fid, cp2, &n);
  183.         /* find the number of lines in the window */
  184.         n = selWindow->nRows;
  185.         if( lof > n )
  186.             /* if lof would place it outside the */
  187.             /* window then put it in the middle of the window */
  188.             n >>= 1;
  189.         else
  190.             /* otherwise put it lof lines down */
  191.             n = lof;
  192.         selWindow->posTopline = cp2;
  193.         selWindow->posTopline = prevLine(fid,selWindow->posTopline,&n);
  194.         selWindow->numTopline += linesFromTop + nLines - n;
  195.         drawWindow(selWindow);
  196.     } else {
  197.         int row1, row2, col1, col2;
  198.         /* the found string is already showing in the window */
  199.         drawSelection( 1 );
  200.         selBegin = newSelBegin;
  201.         selEnd = newSelEnd;
  202.         OffsetToXY( selWindow, selBegin, &row1, &col1 );
  203.         OffsetToXY( selWindow, selEnd, &row2, &col2 );
  204.         drawWindowFast( selWindow, row1, row2, 0, selWindow->nCols );
  205.     }
  206.     underlineSelection = saveUnderlineSelection;
  207. }
  208.  
  209.     AssertSelectionOwnership();
  210.     /* this will erase the "Searching for..." msg in the case where */
  211.     /* the selWindow does not extend to the bottom line */
  212.     if( wrappedAround && update )
  213.         msg(
  214. "Circular search has wrapped around the beginning of the file", 1);
  215.     return selBegin;
  216.  
  217. notFound:
  218.     /* avoid overflowing msgBuffer */
  219.     n = strlen(searchString);
  220.     if( n > (STRINGSIZE-64) )
  221.         n = STRINGSIZE - 64;
  222.     /* 64 is enough for "String `%s' not found." */
  223.     ch = searchString[n];
  224.     searchString[n] = '\0';
  225.     sprintf(msgBuffer, "`%s' not found.", searchString);
  226.     searchString[n] = ch;
  227. errorExit:
  228.     msg(msgBuffer, 1);
  229.     return -1;
  230. }
  231.  
  232.  
  233. int
  234. RegexSearch( w, searchMode, str, update, lof )
  235.     struct window *w;
  236.     int searchMode;
  237.     char * str;
  238.     int update;
  239.     int lof;
  240. {
  241.     extern struct window *selWindow;
  242.     extern Offset selBegin, selEnd;
  243.     extern int selMode;
  244.     extern char msgBuffer[];
  245.     extern char textBuffer[];
  246.     extern int ignoreCase;
  247.     extern int debug;
  248.     extern int underlineSelection;
  249.     extern int wrapAroundSearches;
  250.     extern int regex_bopat[];
  251.     extern int regex_eopat[];
  252.  
  253.     int n, i, linesFromTop, fileId, nLines;
  254.     int saveUnderlineSelection;
  255.     int wrappedAround = 0;
  256.     Offset cp, cp2, startCp, stopCp;
  257.     char ch, *p;
  258.     int fid = w->fileId;
  259.     Offset newSelBegin, newSelEnd;
  260.  
  261.     fileId = w->fileId;
  262.     
  263.     p = re_comp( str );
  264.     if( p != NULL ) {
  265.         sprintf(msgBuffer, "Regular expression error: %s", p);
  266.         printf("%s\n", msgBuffer);
  267.         goto errorExit;
  268.     }
  269.  
  270.     /* avoid overflowing msgBuffer */
  271.     sprintf(textBuffer, "Searching %%s for `%%%ds'", STRINGSIZE-64);
  272.     sprintf(msgBuffer, textBuffer,
  273.         ((searchMode == 0) ? "forwards" : "backwards"), str);
  274.     msg( msgBuffer, 1 );
  275.  
  276.     nLines = 0;
  277.  
  278.     cp = fileSize(w->fileId);
  279.     if( searchMode == 1 ) {
  280.         startCp = 0;
  281.         if( w == selWindow )
  282.             stopCp = selBegin - 1;
  283.         else
  284.             stopCp = cp - 1;
  285.     } else {    /* seachMode == 0 */
  286.         stopCp = cp - 1;
  287.         if( w == selWindow ) {
  288.             startCp = selBegin + 1;
  289.             if( startCp > stopCp ) {    /* already done? */
  290.                 if( wrapAroundSearches )
  291.                     startCp = 0;
  292.                 else
  293.                     goto notFound;
  294.             }
  295.         } else
  296.             startCp = 0;
  297.     }
  298.     linesFromTop = 0;
  299.     /* adjust the line number */
  300.     /* just put in the two while loops and forget the IF test */
  301.     /* at most one of the WHILE loops will actually loop */
  302.     /* adjust for backwards searching */
  303.     cp2 = w->posTopline;
  304.     if( searchMode == 1 ) {
  305.         cp = stopCp + 1;
  306.         if( cp > fileSize(w->fileId) )
  307.             --cp;
  308.     } else {
  309.         cp = startCp - 1;
  310.         if( cp < 0 )
  311.             cp = 0;
  312.     }
  313.     /* normalize cp to the beginning of its line */
  314.     i = -1;
  315.     cp = prevLine( fid, cp, &i );
  316.     while( cp2 < cp ) {
  317.         ++linesFromTop;
  318.         i = 1;
  319.         cp2 = nextLine( fid, cp2, &i );
  320.     }
  321.     while( cp2 > cp ) {
  322.         --linesFromTop;
  323.         i = 1;
  324.         cp2 = prevLine( fid, cp2, &i );
  325.     }
  326.  
  327.     if( searchMode == 0 ) {
  328.         i = re_exec( fileId, startCp, stopCp, &n );
  329.         nLines += n;
  330.         if( wrapAroundSearches && i != 1 ) {
  331.             wrappedAround = 1;
  332.             i = re_exec( fileId, 0L, startCp-1, &n );
  333.             nLines = n;
  334.             linesFromTop = -(selWindow->numTopline);
  335.         }
  336.     } else {
  337.         i = re_exec_reversed( fileId, startCp, stopCp, &n );
  338.         nLines -= n;
  339.         /* a fix so that backwards search from the backwards */
  340.         /* search command is circular if the normal search */
  341.         /* mode is circular */
  342. /********************* DO NOT DO THIS YET ************
  343.  THE PROBLEM IS GETTING THE LINE NUMBERS TO WORK OUT
  344.  FINISH IT LATER
  345.         if( cp == -1 ) {
  346.             wrappedAround = 1;
  347.             cp = searchReverseSpans(fileId, stopCp,
  348.                 fileSize(w->fileId) - patLength,
  349.                 str, patLength, &n);
  350.             nLines = n;
  351.             linesFromTop = -(selWindow->numTopline);
  352.         }
  353. *******************************************************/
  354.     }
  355.  
  356.     if( i < 1 )
  357.         goto notFound;
  358.     if( selWindow != w ) {
  359.         drawSelection( 1 );
  360.         selWindow = w;
  361.     }
  362.     newSelBegin = regex_bopat[0];
  363.     newSelEnd = regex_eopat[0] - 1;
  364.     selMode = SELCHAR;
  365.  
  366. if( !update ) {
  367.     selBegin = newSelBegin;
  368.     selEnd = newSelEnd;
  369. } else {
  370.     (void)indentToShowSelection(-1);
  371.     saveUnderlineSelection = underlineSelection;
  372.     underlineSelection = 0;
  373.     if( newSelBegin >= selWindow->posBotline
  374.                 || newSelBegin < selWindow->posTopline ) {
  375.         /* remember where we came from */
  376.         selWindow->rowLastline = selWindow->numTopline;
  377.         selBegin = newSelBegin;
  378.         selEnd = newSelEnd;
  379.          n = -1;
  380.          cp2 = selBegin;
  381.         cp2 = prevLine( fid, cp2, &n);
  382.         /* find the number of lines in the window */
  383.         n = selWindow->nRows;
  384.         if( lof > n )
  385.             /* if lof would place it outside the */
  386.             /* window then put it in the middle of the window */
  387.             n >>= 1;
  388.         else
  389.             /* otherwise put it lof lines down */
  390.             n = lof;
  391.         selWindow->posTopline = cp2;
  392.         selWindow->posTopline = prevLine(fid,selWindow->posTopline,&n);
  393.         selWindow->numTopline += linesFromTop + nLines - n;
  394.         drawWindow(selWindow);
  395.     } else {
  396.         int row1, row2, col1, col2;
  397.         /* the found string is already showing in the window */
  398.         drawSelection( 1 );
  399.         selBegin = newSelBegin;
  400.         selEnd = newSelEnd;
  401.         OffsetToXY( selWindow, selBegin, &row1, &col1 );
  402.         OffsetToXY( selWindow, selEnd, &row2, &col2 );
  403.         drawWindowFast( selWindow, row1, row2, 0, selWindow->nCols );
  404.     }
  405.     underlineSelection = saveUnderlineSelection;
  406. }
  407.  
  408.     AssertSelectionOwnership();
  409.     /* this will erase the "Searching for..." msg in the case where */
  410.     /* the selWindow does not extend to the bottom line */
  411.     if( wrappedAround && update )
  412.         msg(
  413. "Circular search has wrapped around the beginning of the file", 1);
  414.     return selBegin;
  415.  
  416. notFound:
  417.     /* avoid overflowing msgBuffer */
  418.     n = strlen(str);
  419.     if( n > (STRINGSIZE-64) )
  420.         n = STRINGSIZE - 64;
  421.     /* 64 is enough for "String `%s' not found." */
  422.     ch = str[n];
  423.     str[n] = '\0';
  424.     sprintf(msgBuffer, "`%s' not found.", str);
  425.     str[n] = ch;
  426. errorExit:
  427.     msg(msgBuffer, 1);
  428.     return -1;
  429. }
  430.  
  431.  
  432. #ifdef OLDOLD
  433. int
  434. OldRegexSearch( w, searchMode, str, update, lof )
  435.     struct window *w;
  436.     int searchMode;
  437.     char * str;
  438.     int update;
  439.     int lof;
  440. {
  441.     extern struct window *selWindow;
  442.     extern Offset selBegin, selEnd;
  443.     extern int selMode;
  444.     extern char msgBuffer[];
  445.     extern int ignoreCase;
  446.     extern int debug;
  447.     extern int underlineSelection;
  448.     extern int wrapAroundSearches;
  449.     extern int regex_bopat[];
  450.     extern int regex_eopat[];
  451.  
  452.     int n, i, linesFromTop, fileId, fid2, nLines;
  453.     int patLength;
  454.     int saveUnderlineSelection;
  455.     int ret, answer;
  456.     int wrappedAround = 0;
  457.     Offset cp, cp2, startCp, stopCp;
  458.     char ch, *p, *limit, *from, *to;
  459.     int fid = w->fileId;
  460.     Offset newSelBegin, newSelEnd;
  461.  
  462.     fileId = w->fileId;
  463.  
  464.     p = re_comp( str );
  465.     if( p != NULL ) {
  466.         sprintf(msgBuffer, "RE ERROR: %s", p);
  467.         printf("%s\n", msgBuffer);
  468.         goto errorExit;
  469.     }
  470.  
  471.     /* avoid overflowing msgBuffer */
  472.     n = strlen( str );
  473.     if( n > (STRINGSIZE-64) )
  474.         n = STRINGSIZE - 64;
  475.     /* 64 is enough for "Searching circularly for `%s'" */
  476.     sprintf(msgBuffer, "Searching %s for `%s'",
  477.         ((searchMode == 0) ? "forwards" : "backwards"),
  478.         str);
  479.     msg( msgBuffer, 1 );
  480.  
  481. /******** handle backwards, wrap around, etc. ********/
  482.  
  483.     cp = fileSize(w->fileId);
  484.     stopCp = cp;
  485.     if( w == selWindow ) {
  486.         startCp = selBegin + 1;
  487.         if( startCp >= stopCp ) {    /* already done? */
  488.             if( wrapAroundSearches )
  489.                 startCp = 0;
  490.             else
  491.                 goto notFound;
  492.         }
  493.     } else
  494.         startCp = 0;
  495.  
  496.     n = re_exec( fileId, startCp, stopCp, &i);
  497.  
  498.     if( n < 1 )
  499.         goto notFound;
  500.  
  501.     if( selWindow != w ) {
  502.         drawSelection( 1 );
  503.         selWindow = w;
  504.     }
  505.     newSelBegin = regex_bopat[0];
  506.     newSelEnd = regex_eopat[0] - 1;
  507.     selMode = SELCHAR;
  508.  
  509. if( !update ) {
  510.     selBegin = newSelBegin;
  511.     selEnd = newSelEnd;
  512. } else {
  513.     (void)indentToShowSelection(-1);
  514.     saveUnderlineSelection = underlineSelection;
  515.     underlineSelection = 0;
  516.     if( newSelBegin >= selWindow->posBotline
  517.                 || newSelBegin < selWindow->posTopline ) {
  518.         /* remember where we came from */
  519.         selWindow->rowLastline = selWindow->numTopline;
  520.         selBegin = newSelBegin;
  521.         selEnd = newSelEnd;
  522.          n = -1;
  523.          cp2 = selBegin;
  524.         cp2 = prevLine( fid, cp2, &n);
  525.         /* find the number of lines in the window */
  526.         n = selWindow->nRows;
  527.         if( lof > n )
  528.             /* if lof would place it outside the */
  529.             /* window then put it in the middle of the window */
  530.             n >>= 1;
  531.         else
  532.             /* otherwise put it lof lines down */
  533.             n = lof;
  534.         selWindow->posTopline = cp2;
  535.         selWindow->posTopline = prevLine(fid,selWindow->posTopline,&n);
  536.         selWindow->numTopline += linesFromTop + nLines - n;
  537.         drawWindow(selWindow);
  538.     } else {
  539.         int row1, row2, col1, col2;
  540.         /* the found string is already showing in the window */
  541.         drawSelection( 1 );
  542.         selBegin = newSelBegin;
  543.         selEnd = newSelEnd;
  544.         OffsetToXY( selWindow, selBegin, &row1, &col1 );
  545.         OffsetToXY( selWindow, selEnd, &row2, &col2 );
  546.         drawWindowFast( selWindow, row1, row2, 0, selWindow->nCols );
  547.     }
  548.     underlineSelection = saveUnderlineSelection;
  549. }
  550.  
  551.     AssertSelectionOwnership();
  552.     /* this will erase the "Searching for..." msg in the case where */
  553.     /* the selWindow does not extend to the bottom line */
  554.     if( wrappedAround && update )
  555.         msg(
  556. "Circular search has wrapped around the beginning of the file", 1);
  557.     return selBegin;
  558.  
  559. notFound:
  560.     /* avoid overflowing msgBuffer */
  561.     n = strlen(str);
  562.     if( n > (STRINGSIZE-64) )
  563.         n = STRINGSIZE - 64;
  564.     /* 64 is enough for "String `%s' not found." */
  565.     ch = str[n];
  566.     str[n] = '\0';
  567.     sprintf(msgBuffer, "`%s' not found.", str);
  568.     str[n] = ch;
  569. errorExit:
  570.     msg(msgBuffer, 1);
  571.     return -1;
  572. }
  573. #endif
  574.  
  575.