home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume2 / xbrowser / part01 / search.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-03  |  12.4 KB  |  544 lines

  1. /* Systems Sciences Laboratory, Webster Research Center */
  2.  
  3. static char *PROGRAM_information[] =
  4. {
  5.     "Copyright (c) 1988 Xerox Corporation.  All rights reserved.",
  6.     "$Header$",
  7.     "$Locker$"
  8. }
  9. ;
  10.  
  11. /*
  12.  * Copyright protection claimed includes all forms and matters of copyrightable
  13.  * material and information now allowed by statutory or judicial lay or
  14.  * herinafter granted, including without limitation, material generated from
  15.  * the software programs which are displayed on the screen such as icons,
  16.  * screen display looks, etc.
  17.  */
  18. static int errornum;
  19. static int hitfilesize;
  20.  
  21. #define MAXDISPLAY 256
  22. #define BLKSIZE 8192
  23. #define ESIZE 1024
  24.  
  25. #define INIT   register char *sp = instring;
  26. #define GETC() (*sp++)
  27. #define PEEKC()     (*sp)
  28. #define UNGETC(c)   (--sp)
  29. #define RETURN(c)   return;
  30. #define ERROR(c)    { errornum = c; return; }
  31.  
  32. #include <regexp.h>
  33. #include <sys/file.h>
  34. #include <ctype.h>
  35. #include "xfilebrowser.h"
  36.  
  37.  
  38. static short recursion = 1;
  39.         /* 1 no recursive search of directories
  40.            2 search one level of directories
  41.            3 search all levels of directories */
  42.  
  43. static Widget searchshell = NULL;
  44. static Widget searchoption;    /* option for sorting files */
  45. static Widget optioncaller;
  46. static Widget caseoption;    /* togglewidget selecting case sensitive */
  47.  
  48. static short disp_option = 0;
  49.  
  50. static Boolean filefound = False;
  51. static char *searchbuf;
  52. static int blksize;
  53. static Boolean recursive = False;
  54. static XtState ignore_case = XtToggleOff;    /* is grep case insensitive */
  55.  
  56.  
  57. extern char *re_comp();
  58.  
  59.  
  60.  
  61.  
  62. /*************************************
  63. **    build options dialog for search
  64. **************************************/
  65.  
  66. check_search()
  67. {
  68.     return disp_option;
  69. }
  70.  
  71. static void DoApply()
  72. {
  73.     recursion = XtOptionGetSelection(searchoption);
  74.  
  75.     ignore_case = GetToggle(caseoption);
  76.  
  77.     disp_option = 0;
  78.     change_sensitive(optioncaller, TRUE);
  79.     XtPopdown(searchshell);
  80. }
  81.  
  82. static void DoCancel()
  83. {
  84.     XtState toggle;
  85.  
  86.     /* reset the option dialog window */
  87.     if ( !(recursion == XtOptionGetSelection(searchoption)) ) 
  88.         /* sorting was modified by user */
  89.        XtOptionSetSelection(searchoption, recursion);
  90.  
  91.     SetToggle(caseoption, ignore_case);
  92.  
  93.     disp_option = 0;
  94.     change_sensitive(optioncaller, TRUE);
  95.     XtPopdown(searchshell);
  96. }
  97.  
  98. build_searchoptions()
  99. {
  100.     Arg popargs[1];
  101.     Widget listpane, listrow1, listrow2;
  102.  
  103.     static Arg paneargs[] = {
  104.        { XtNallowResize, (XtArgVal)True },
  105.     };
  106.  
  107.     static Arg toggleargs[] = {
  108.        { XtNstate, (XtArgVal)XtToggleOff },
  109.     };
  110.     
  111.     static Arg optionargs[] = { 
  112.        { XtNlabel, (XtArgVal)NULL },
  113.        { XtNorientation,(XtArgVal)XtorientVertical },
  114.        { XtNfromHoriz, (XtArgVal) NULL },
  115.        { XtNfromVert, (XtArgVal) NULL },
  116.        { XtNleft, (XtArgVal) XtChainLeft },
  117.        { XtNright, (XtArgVal) XtChainLeft },
  118.        { XtNtop, (XtArgVal) XtChainTop },
  119.        { XtNbottom, (XtArgVal) XtChainTop }
  120.  
  121.     };
  122.  
  123.     XtSetArg( popargs[0], XtNborderWidth, 2 );
  124.     
  125.     searchshell = XtCreatePopupShell("searchshell",
  126.                overrideShellWidgetClass,
  127.             toplevel, popargs, XtNumber(popargs));
  128.  
  129.     listpane = XtCreateManagedWidget( "vpaned", vPanedWidgetClass, 
  130.             searchshell, paneargs , XtNumber(paneargs) );
  131.     listrow1 = XtCreateManagedWidget("row1", boxWidgetClass, 
  132.             listpane, NULL,0);
  133.     listrow2 = XtCreateManagedWidget("row2", boxWidgetClass, 
  134.             listpane, NULL,0);
  135.     makeCommandButton(listrow1, "Apply", DoApply);
  136.     makeCommandButton(listrow1, "Cancel", DoCancel);
  137.  
  138.         /* define option menu for searching directories */
  139.     optionargs[0].value = (XtArgVal)"Select Search Option:";
  140.     searchoption = XtCreateManagedWidget("searching", optionWidgetClass, 
  141.         listrow2, optionargs, XtNumber(optionargs));
  142.     XtOptionAddOption(searchoption, "skip directories", TRUE);
  143.     XtOptionAddOption(searchoption, "search next-level directory", FALSE);
  144.     XtOptionAddOption(searchoption, "search all directories", FALSE);
  145.  
  146.         /* define toggle for selecting case sensitivity */
  147.     caseoption = XtCreateManagedWidget("case insensitive search",
  148.         toggleWidgetClass,
  149.         listrow2, toggleargs, XtNumber(toggleargs));
  150.  
  151.     XtSetMappedWhenManaged(searchshell, FALSE);
  152.     XtRealizeWidget(searchshell);
  153. }
  154.  
  155.  
  156. display_searchoptions(caller)
  157. Widget caller;
  158. {
  159.     if (searchshell == NULL) {
  160.        build_searchoptions();
  161.        optioncaller = caller;
  162.     }
  163.  
  164.     disp_option = 1;
  165.     move_popup(searchshell, caller);
  166.     change_sensitive(caller, FALSE);
  167.     XtMapWidget(searchshell);
  168.     XtPopup(searchshell, XtGrabNonexclusive);
  169. }
  170.  
  171. /**********************************************
  172. **    build data file structure for grep files
  173. ***********************************************/
  174.  
  175. free_hitfiles()
  176. {
  177.     register int i;
  178.     register LineElement *p, *tmp;
  179.  
  180.     if (hitfiles != (SearchElement **)NULL) {
  181.        for (i = 0; i < numhitfiles; i++) {
  182.         p = hitfiles[i]->lines;
  183.         while (p != (LineElement *)NULL) {
  184.            tmp = p->next;
  185.            XtFree(p);
  186.            p = tmp;
  187.         }
  188.         XtFree(hitfiles[i]);
  189.        }
  190.        numhitfiles = 0;
  191.     }
  192. }
  193.  
  194. LineElement *add_line(pos1, pos2, line, next)
  195. XtTextPosition pos1, pos2;
  196. int line;
  197. LineElement *next;
  198. {
  199.     register LineElement *p;
  200.  
  201.     p = (LineElement *)XtMalloc(sizeof(LineElement));
  202.     p->pa = pos1;
  203.     p->pe = pos2;
  204.     p->linenumber = line;
  205.     p->next = next;
  206.     return p;    
  207. }
  208.  
  209. add_file(fname, pos1, pos2, linenr)
  210. char *fname;
  211. XtTextPosition pos1, pos2;
  212. int linenr;
  213. {
  214.     SearchElement *selem;
  215.     if (numhitfiles == hitfilesize) {
  216.        hitfilesize += (numfiles > 64) ? (2 * numfiles): 128;
  217.        if (hitfiles != (SearchElement **)NULL)
  218.            hitfiles = (SearchElement **)XtRealloc(hitfiles, 
  219.                hitfilesize * sizeof(SearchElement *));
  220.        else 
  221.         hitfiles = 
  222.         (SearchElement **)XtMalloc(hitfilesize*sizeof(SearchElement *));
  223.     }
  224.  
  225.     if ( numhitfiles <= 0 || 
  226.             strcmp(fname, hitfiles[numhitfiles-1]->name) ) {
  227.        selem = (SearchElement *)XtMalloc(sizeof(SearchElement));
  228.        selem->pos1 = pos1;
  229.        selem->pos2 = pos2;
  230.        selem->lines = add_line(pos1, pos2, linenr, (LineElement *)NULL);
  231.        strcpy(selem->name, fname);
  232.        hitfiles[numhitfiles] = (SearchElement *)selem;
  233.  
  234.        numhitfiles++;
  235.     }
  236.     else {
  237.        hitfiles[numhitfiles-1]->lines = 
  238.            add_line(pos1, pos2, linenr, hitfiles[numhitfiles-1]->lines);
  239.        hitfiles[numhitfiles-1]->pos2 = pos2;
  240.     }
  241. }
  242.  
  243. disp_searchline(file, line, linenr)
  244. char *file, *line;
  245. int linenr;
  246. {
  247.     XtTextBlock text;
  248.     XtTextPosition pos;
  249.  
  250.     text.length = strlen(line);
  251.     text.ptr = line;
  252.     text.firstPos = 0;
  253.     allowedit = 1;
  254.  
  255.     pos = (*grepsource->Scan)(grepsource, 0, XtstAll, XtsdRight, 1, 0);
  256.  
  257.     XtTextReplace(grepwidget, pos, pos, &text);
  258.     allowedit = 0;
  259.     add_file(file, pos, (pos + text.length + 1), linenr);
  260. }
  261.  
  262. det_surround(file, start, end, linenr)
  263. char *file, *start, *end;
  264. int linenr;
  265. {
  266.     int i, len;
  267.     char tmpline[MAXDISPLAY + 1];
  268.  
  269.     sprintf(tmpline, "%s: ", file);
  270.     len = MAXDISPLAY - strlen(tmpline) - 2;
  271.     if ( (end - start) < len ) 
  272.        strcat(tmpline, start);
  273.     else if ( (i = loc2 - start) < len) {
  274.        strncat(tmpline, start, i);
  275.        tmpline[i] = '\0';
  276.     }
  277.     else {
  278.        strncat(tmpline, loc1, len);
  279.        tmpline[MAXDISPLAY - 2] = '\0';
  280.     }
  281.     strcat(tmpline, "\n");
  282.     disp_searchline(file, tmpline, linenr);
  283.     filefound = True;
  284. }
  285.  
  286. int check_textfile(p)
  287. char *p;
  288. {
  289.     switch (*(int *)p) {
  290.     case 0177555:
  291.     case 0177545:
  292.     case 070707:    return(-1);
  293.     }
  294.     switch (*(short *)(p+2)) {
  295.     case 0407: 
  296.     case 0413:    return(-1);
  297.     }
  298.  
  299.     if (strncmp(p, "Interpress", 10) == 0) return(-1);
  300.     else if (strncmp(p, "\037\036", 2) == 0) return(-1);
  301.     else if (strncmp(p, "\377\037", 2) == 0) return(-1);
  302.     else if (strncmp(p, "\037\235", 2) == 0) return(-1);
  303.     return(0);
  304. }
  305.  
  306. int search_file(filelist, index, expbuf, stop)
  307. struct afile **filelist;
  308. int index;
  309. char *expbuf;
  310. Boolean stop;
  311. {
  312.     int fp, first = 1;
  313.     int count = 0, i, j;
  314.     int linenr = 0;
  315.     char *p;
  316.     char *q, *h;
  317.     char *linebuf;
  318.     struct stat statbuf;
  319.  
  320.     char *filename = filelist[index]->d_name;
  321.  
  322.         /* check file type */
  323.     switch (filelist[index]->d_type) {
  324.     case 'b':
  325.     case 'c':
  326.     case 's':    return(-1);
  327.     case 'd':    /* handle directories */
  328.        {
  329.         struct afile **dirfiles;
  330.         int numdirfiles, i;
  331.         
  332.         if ( (recursion == 1) ||
  333.             (recursion == 2 && recursive) ) return(-1);
  334.         recursive = True;
  335.         setup_filepattern("*");
  336.         if (prepare_list(filename, 0, &dirfiles, &numdirfiles,
  337.                 filename))
  338.            return(-1);
  339.         setup_filepattern(filepattern);
  340.  
  341.         for (i = 0; (i < numdirfiles && (!stop || !filefound) ); i++)
  342.            search_file(dirfiles, i, expbuf, stop);
  343.         free_direct(&dirfiles, &numdirfiles);
  344.         recursive = False;
  345.         return(0);
  346.        }
  347.     default:    break;
  348.     }
  349.         /* check if file pattern matches */
  350.     if (! re_exec(filename)) return(-1);    
  351.     if ( (fp = open(filename, O_RDONLY)) < 0) {
  352.        disp_message("\nSearch: cannot open file %s", filename);
  353.        return(-1);
  354.     }
  355.     if (fstat(fp, &statbuf) == -1) { close(fp); return(-1); }
  356.     else if ( !(statbuf.st_mode & S_IFREG )) {
  357.        disp_message("\nSearch: %s not regular file!", filename);
  358.        close(fp);
  359.        return(-1);
  360.     }
  361.  
  362.     if (searchbuf == NULL) {
  363.        if (statbuf.st_blksize > 0)
  364.         blksize = statbuf.st_blksize;
  365.        else    blksize = BLKSIZE;
  366.        searchbuf = (char *)XtMalloc(blksize+ (2*MAXDISPLAY));
  367.     }
  368.     p = searchbuf;
  369.     while ( (i = read(fp, p, blksize)) > 0) {
  370.               if (first) {
  371.            /* check if file can be scanned */
  372.         if (check_textfile(p) == -1) {
  373.            disp_message("\nSearch: %s does not contain text!",
  374.              filename);
  375.            close(fp);
  376.               return(-1);
  377.         }
  378.         first = 0;
  379.        }
  380.  
  381.        if (count == 0) {
  382.         while (*p == '\n') { i--; p++; linenr++; }
  383.         if (i == 0) continue; else count = i;
  384.        }
  385.        else count += i;
  386. NEXT:
  387.        linebuf = p;  p++;  j = 1;
  388.        while ( (j < min(MAXDISPLAY, count)) && *p != '\n' )
  389.         { p++; j++; }
  390.        if ( j < MAXDISPLAY && *p != '\n' ) {
  391.         q = searchbuf; h = linebuf; j = 1;
  392.         while (j++ <= count) *q++ = *h++;
  393.         linebuf = searchbuf;
  394.         p = linebuf + count;
  395.         continue;
  396.        }
  397.  
  398.        if (*p == '\n') linenr++;
  399.        *p = '\0'; 
  400.        if (step(linebuf, expbuf)) 
  401.         det_surround(filename, linebuf, p, linenr);
  402.        count -= j + 1;
  403.        if (count == 0) { p = searchbuf; continue; }
  404.        else {
  405.         p++;
  406.            while (*p == '\n' && count > 0) { p++; count--; linenr++; }
  407.        }
  408.        if (count > 0) goto NEXT; else { p = searchbuf; continue; }
  409.     }
  410.  
  411.     if (count > 0) {
  412.         *(p+1) = '\0';
  413.         if (step(linebuf, expbuf)) 
  414.         det_surround(filename, linebuf, p, linenr);
  415.     }
  416.     close(fp);
  417.     return(0);
  418. }
  419.  
  420. int examine_files(fstart, fend, stop)
  421. int fstart, fend;
  422. Boolean stop;
  423. {
  424.     int i;
  425.     char expbuf[ESIZE+1];
  426.     char *greppattern;
  427.     char *setup_search();
  428.  
  429.     greppattern = setup_search(searchpattern);
  430.     errornum = 0;
  431.     compile(greppattern, expbuf, &expbuf[ESIZE], '\0');
  432.     XtFree(greppattern);
  433.     if (errornum != 0) {
  434.        switch (errornum) {
  435.        case 50: 
  436.         disp_message("\nSearch: Regular expression overflow");
  437.         break;
  438.        case 49:
  439.         disp_message("\nSearch: [ ] imbalance");
  440.         break;
  441.        case 46:
  442.         disp_message("\nSearch: First number exceeds second in \\{ \\}");
  443.         break;
  444.        case 45:
  445.         disp_message("\nSearch: } expected after \\");
  446.         break;
  447.        case 44:
  448.         disp_message("\nSearch: More than 2 numbers given in \\{ \\}");
  449.         break;
  450.        case 43:
  451.         disp_message("\nSearch: Too many \\(");
  452.         break;
  453.        case 42:
  454.         disp_message("\nSearch: \\( \\) imbalance");
  455.         break;
  456.        case 36:
  457.         disp_message("\nSearch: Illegal or missing delimiter");
  458.         break;
  459.  
  460.        default:
  461.         disp_message("\nSearch: search pattern failure %d", errornum);
  462.        }
  463.        return(-1);
  464.     }
  465.  
  466.     setup_filepattern(filepattern);
  467.     filefound = False;
  468.     for (i = fstart; (i <= fend && (!stop || !filefound) ); i++)
  469.        search_file(files, i, expbuf, stop);
  470.     return(0);
  471. }
  472.  
  473. /**********************************************
  474. **    search utility routines
  475. ***********************************************/
  476.  
  477. int setup_filepattern(pattern)
  478. char *pattern;
  479. {
  480.     char tmppattern[64];
  481.     char *error;
  482.  
  483.     setup_pattern(pattern, tmppattern);
  484.     if (error = re_comp(tmppattern)) {
  485.        disp_message("\nsearch pattern for files %s?", error);
  486.        return(-1);
  487.     }
  488.     return(0);
  489. }
  490.  
  491. char *setup_search(s)
  492. char *s;
  493. {
  494.     char *target, *src = s, *dest;
  495.     char c;
  496.  
  497.     if (ignore_case == XtToggleOff) {
  498.        target = XtMalloc(strlen(s) + 1);
  499.        strcpy(target, s);
  500.     }
  501.     else {
  502.         /* allocate maximum memory */
  503.        target = XtMalloc(4 * strlen(s) + 1);
  504.        dest = target;
  505.  
  506.        while (c = *src++) {
  507.            if (isalpha(c)) {
  508.               *dest++ = '[';
  509.               *dest++ = c;
  510.               *dest++ = ',';
  511.  
  512.               if (islower(c))     *dest++ = toupper(c); 
  513.            else         *dest++ = tolower(c); 
  514.  
  515.            *dest++ = ']';
  516.            }
  517.            else *dest++ = c;
  518.        }
  519.        *dest = '\0';
  520.     }
  521.     return(target);
  522. }
  523.  
  524. int select_searchfile(start, end, line)
  525. int start, end;
  526. int *line;
  527. {
  528.     int i = 0;
  529.     register LineElement *p;
  530.  
  531.     while (i < numhitfiles && hitfiles[i]->pos1 <= start) i++; 
  532.     if ( (hitfiles[i-1]->pos2 + 1) < end) { *line = 0; return(-1); }
  533.     else {
  534.        p = hitfiles[i-1]->lines;
  535.        while (p != (LineElement *)NULL && (p->pa > start) ) p = p->next;
  536.  
  537.        if (p == (LineElement *)NULL) 
  538.            *line = 0; 
  539.        else *line = p->linenumber;
  540.  
  541.        return(i-1);
  542.     }
  543. }
  544.