home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / FS191 / FS2.C < prev    next >
C/C++ Source or Header  |  1993-02-24  |  24KB  |  854 lines

  1. /* FS2.C
  2.  * whereis functions, remove dir functions
  3.  * MSC6
  4.  * FS 1.9.1
  5.  * 240293
  6.  * Copyright (C) M. van Breemen, 1993, All rights reserved.
  7.  */
  8.  
  9. #include "FS.H"
  10.  
  11. /* Prototypes */
  12. int whereis(char *searchstring, int *current_page, int *filenumber );
  13. void outtextm( char *string );
  14. void alert( void );
  15. void show_error( char *message );
  16. void wait_sec( int milliseconds );
  17. void clear_left_button_queue( void );
  18. void clear_right_button_queue( void );
  19. int read_left_button_queue( int *row, int *col );
  20. int read_right_button_queue( int *row, int *col );
  21. void init_mouse( void );
  22. void hide_mouse( void );
  23. void show_mouse( void );
  24. int mouse_button_pressed( void );
  25. unsigned int n_kbhit( void );
  26. void movmem(void *src, void *dest, unsigned length);
  27. int getkey(void);
  28. void changecursor(int insmode);
  29. void setcursor(unsigned int shape);
  30. int editstring(int row, int col, char *s, char *illegal, int maxlength);
  31. char *saveScrn(void);
  32. char *restScrn(char *saveArea);
  33. int valid_filename( char *newname);
  34. void shadebox( short r1, short c1, short r2, short c2 );
  35. void shadechar( int row, int col );
  36. int find_in_file( char *filename , char *string, int ignore_case);
  37. int extract_directory( char *searchstring );
  38. char *set_working_drive_and_dir( char *full_filename );
  39. int find_name(char *fname, int *current_page, int *filenumber);
  40.  
  41. extern short int screen_bg_color;
  42. extern short int file_color;
  43. extern short int directory_color;
  44. extern short int cursor_bg_color;
  45. extern short int cursor_file_color;             /* 10 bytes color info */
  46. extern short int cursor_directory_color;
  47. extern short int info_bg_color;
  48. extern short int info_text_color;
  49. extern short int error_text_color;
  50. extern short int prompt_text_color;
  51. extern short int hidden_file_color;
  52. extern short int volume_label_color;
  53. extern short int cursor_hidden_file_color;
  54. extern short int cursor_volume_label_color;
  55.  
  56. /* global variables */
  57.  
  58. extern int number_of_files;    /* number of files found */
  59.  
  60. typedef struct find_t_small {
  61.                 char name [13];
  62.                 char attrib;
  63.                 } FIND_T_SMALL;
  64.  
  65. extern FIND_T_SMALL *find;    /* pointer to the file info structures */
  66. extern int mouse_present;    /* boolean is there a mouse ? */
  67. extern int mouse_row;    /* mouse position, NOT screen rows and columns */
  68. extern int mouse_col;
  69. extern int max_files;           /* maximal number of accessible files per directory or root, defaults to 456 */
  70. extern int dos_error;           /* set by error handler */
  71.  
  72.  
  73. /*---------------------------------------------------------------------------*/
  74. /*   FF    Routines taken from FFF 3.4.5, a public domain program to search files
  75.  *    Author:    Don A. Williams                                             *
  76.  *        CompuServ -                                                 *
  77.  *        Genie      - DON-WILL                                         *
  78. */
  79.  
  80.  
  81. #define U_ESC     1
  82. #define U_SELECT 2
  83. #define U_GOTO 3
  84.  
  85. #define FIND_FIRST(Name,Block,Attrib) _dos_findfirst(Name, Attrib, Block);
  86. #define FIND_NEXT(Block) _dos_findnext(Block);
  87. #define DIR_ENTRY find_t    /* Name of the directory entry structure    */
  88. #define D_ATTRIB attrib        /* Attribute field in directory entry        */
  89. #define D_NAME name        /* File name field in directory entry        */
  90.  
  91.  
  92. typedef struct QueEntry {
  93.               struct QueEntry *Next;
  94.               char    *Body;
  95.             } QUE_ENTRY;
  96.  
  97. typedef struct QueDef {
  98.             QUE_ENTRY *Head, *Current;
  99.             int       Count;
  100.               } QUE_DEF;
  101.  
  102. /* Function prototypes      */
  103.  
  104. int        fff( char *fpattern, char *sstring, int ignore_case);
  105. void        InitQueue (QUE_DEF *Q);
  106. QUE_ENTRY    *Enque (QUE_DEF *Q, void *Body);
  107. int        WalkTree (QUE_DEF * Q, char *sstring , int ignore_case);
  108. int             SearchQ (char *Str);
  109. int             Match (char *Str, char *Pat);
  110. static int    I_Match (char *Str, char *Pat);
  111. static int    S_Match (char *S, char *P, int Anchor);
  112. void        DeleteQueue( QUE_DEF PatQue );
  113.  
  114. void        clean_dir(char *path);
  115. void        do_dir(char *path);
  116.  
  117. /*----------------------------------------------------------------------*/
  118.  
  119. extern QUE_DEF    PatQue;
  120. extern char        T_Path[_MAX_PATH];            /* Temporary directory path to search    */
  121. extern char        V_Path[_MAX_PATH];            /* Selected file */
  122.  
  123. void DeleteQueue( QUE_DEF PatQue )
  124. {
  125.     QUE_ENTRY *t, *u;
  126.     for (t = PatQue.Head; t != NULL;)
  127.     {
  128.     u = t->Next;
  129.     free(t->Body);
  130.     free(t);
  131.     t = u;
  132.     }
  133. }
  134.  
  135. int fff(char *fpattern, char *sstring, int ignore_case)
  136. {
  137.     char        *p, *p2;
  138.     char        scratchfpattern[_MAX_PATH];
  139.     char        CurDir[_MAX_PATH];            /* Full path of the current directory    */
  140.     char        Path[_MAX_PATH];            /* Current directory path to search        */
  141.     char        Devices[16] = "";
  142.     int        Result;
  143.     int        i;
  144.  
  145.     strcpy (scratchfpattern,fpattern);
  146.     InitQueue(&PatQue);
  147.     _getdcwd( _getdrive(), CurDir, _MAX_PATH );
  148.     strupr(CurDir);
  149.     strcpy(Path, "C:\\");
  150.     Devices[0] = (char) (_getdrive() - 1 + 'A');
  151.     Devices[1] = '\0';
  152.  
  153. /*    Interpret fpattern tokens */
  154.     p = strtok( scratchfpattern, " " );    /* Find first token    */
  155.     while( p != NULL )
  156.     {
  157.  
  158.             if ((p2 = strchr(p, ':')) != NULL)  /* process devices */
  159.             {
  160.                 *p2 = '\0';
  161.                 strcpy(Devices, p);
  162.                 p2++;               /* skip NULL */
  163.                 p = p2;            /* remove device */
  164.             }
  165.             if ((p2 = strrchr(p, '\\')) != NULL)  /* process path */
  166.             {
  167.                 *p2 = '\0';
  168.                 if (p[0]=='\\') strcpy(Path,"C:");
  169.                 else strcpy(Path,"C:\\");
  170.                 strcat(Path, p);
  171.                 if (Path[strlen(Path)-1]!='\\') strcat(Path,"\\");
  172.                 p2++;                  /* skip backslash */
  173.                 p = p2;               /* remove path */
  174.             }
  175.             if (strlen(p))
  176.             {
  177.                   if (strlen(p)>12)
  178.                   {
  179.                      DeleteQueue( PatQue );
  180.                      return FAILURE;  /* illegal filename length, abort */
  181.                   }
  182.                   if (!Enque(&PatQue, strupr(p)))
  183.                   {
  184.                     DeleteQueue( PatQue );
  185.                     _settextposition( 8, 3 );
  186.                     outtextm( "Memory exhausted, search aborted");
  187.                     alert();
  188.                     wait_sec(1000);
  189.                     return FAILURE;
  190.                   }
  191.             }
  192.             p = strtok( NULL, " " );    /* Find next token           */
  193.     }
  194.  
  195. /* This does the work by walking the directory structure for each specified    */
  196. /* disk                                                                        */
  197.  
  198.     p = Devices;
  199.     while (*p != '\0') {
  200.         strcpy(T_Path, Path);
  201.         T_Path[0] = *p++;      /* set drive */
  202.         if (Result=WalkTree(&PatQue,sstring,ignore_case)) break;
  203.         }
  204.     if (!Result)
  205.     {
  206.               _settextposition( 6, 3 );
  207.               outtextm("No more matches");
  208.               hide_mouse();
  209.               for (i=15;i<=63;i++) _outtext(" ");
  210.               show_mouse();
  211.     }
  212.  
  213.     DeleteQueue( PatQue );
  214.     return (Result);
  215. }
  216.  
  217. /*----------------------------------------------------------------------*/
  218. /* WalkTree is a recursive routine that walks the directory structure    */
  219. /* specifed by the external T_Path.  It bypasses Volume IDs and builds    */
  220. /* a linked list queue of directories that is processed after all of    */
  221. /* the file entries have been processed.                                */
  222.  
  223. int WalkTree (QUE_DEF *Q, char *sstring, int ignore_case)
  224. {
  225.     int        Status;
  226.     char    Reply;
  227.     QUE_DEF    Direc;
  228.     QUE_ENTRY    *t, *u;
  229.     char    *p;
  230.     struct DIR_ENTRY  DirBlk;        /* Directory Entry structure            */
  231.     int        TotalFiles = 0;        /* Total files processed            */
  232.     int        TotalMatch = 0;        /* Count of all files matched            */
  233.     int operator_intervention=FALSE;
  234.     register int i;
  235.     int mouse_row, mouse_col;
  236.     int ulc_row, ulc_col, dummy;    /* upper left corner row and column of window */
  237.  
  238.     _gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy);    /* mouse coordinates are absolute! */
  239.     InitQueue(&Direc);
  240.     strcat(T_Path, "*.*");
  241.  
  242.     Status = FIND_FIRST(T_Path, &DirBlk, 0xFF);
  243.  
  244.     *(strrchr(T_Path, '\\') + 1) = '\0';
  245.     _settextposition( 6, 3 );
  246.     outtextm(T_Path);        /* show progress */
  247.     hide_mouse();
  248.     for (i=strlen(T_Path);i<=63;i++) _outtext(" ");
  249.     show_mouse();
  250.  
  251.     while (!Status && !operator_intervention)
  252.     {  /*1*/
  253.      if (n_kbhit() || mouse_button_pressed())  /* operator ESCapes */
  254.      {  /*2*/
  255.          if (n_kbhit()) Reply = (char) getkey();
  256.          else
  257.          {
  258.          if (mouse_present)
  259.          if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  260.          {
  261.              if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66) Reply=0x1B;
  262.              else Reply='\0';
  263.          }
  264.          }
  265.  
  266.          if (Reply == 0x1B)    /* confirm */
  267.          {
  268.          _settextposition( 8, 3 );
  269.          outtextm("Type Y to stop searching completely");
  270.          _settextposition( 1, 1 );
  271.          Reply = (char) getkey();
  272.          _settextposition( 8, 3 );
  273.          outtextm("                                   ");
  274.          if (Reply=='y' || Reply=='Y') operator_intervention=U_ESC;
  275.          }
  276.      } /*2*/
  277.  
  278.      if (!operator_intervention)
  279.      {
  280.          if ((DirBlk.D_ATTRIB & _A_VOLID) != 0)  /* Bypass Volume Label */
  281.          {
  282.          Status = FIND_NEXT(&DirBlk);
  283.          continue;
  284.          }
  285.      }
  286.  
  287.      if (!operator_intervention)
  288.      {  /*3*/
  289.          if ((DirBlk.D_ATTRIB & _A_SUBDIR) != 0) /* Process subdirectory */
  290.          {
  291.          if (DirBlk.D_NAME[0] != '.')
  292.          {
  293.              if (!Enque(&Direc, DirBlk.D_NAME))
  294.              {
  295.              _settextposition( 8, 3 );
  296.              outtextm( "Memory exhausted, search aborted");
  297.              alert();
  298.              wait_sec(1000);
  299.              operator_intervention=FAILURE;
  300.              }
  301.          }
  302.          }
  303.          else
  304.          { /*C*/                /* Process file entry */
  305.          ++TotalFiles;
  306.          if ( SearchQ(DirBlk.D_NAME) )
  307.          {  /*B*/
  308.              strcpy(V_Path, T_Path);
  309.              strcat(V_Path, DirBlk.D_NAME);
  310.              _settextposition( 6, 3 );
  311.              outtextm(V_Path); /* show filename match */
  312.              hide_mouse();
  313.              for (i=strlen(V_Path);i<=63;i++) _outtext(" ");
  314.              show_mouse();
  315.  
  316.              if (strlen(sstring) ? find_in_file(V_Path,sstring, ignore_case) : TRUE)
  317.              { /*A*/
  318.              ++TotalMatch;
  319.              _settextposition( 8, 3);
  320.              outtextm("Next, Select, Goto  ");
  321.              do
  322.              {
  323.                  while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
  324.                  if (n_kbhit()) Reply = (char) getkey();
  325.                  else
  326.                  {
  327.                  Reply='\0';
  328.                  if (mouse_present)
  329.                  if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  330.                  {
  331.                      if ((mouse_col-ulc_col+1)>=3 && (mouse_col-ulc_col+1)<=6)
  332.                      Reply='N';
  333.                      if ((mouse_col-ulc_col+1)>=9 && (mouse_col-ulc_col+1)<=14)
  334.                      Reply='S';
  335.                      if ((mouse_col-ulc_col+1)>=17 && (mouse_col-ulc_col+1)<=20)
  336.                      Reply='G';
  337.                      if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66)
  338.                      Reply=0x1B;
  339.                  }
  340.                  }
  341.                  switch (Reply)
  342.                  {
  343.                  case 0x1B: _settextposition( 8, 3);
  344.                         outtextm("                    ");
  345.                         operator_intervention=U_ESC;
  346.                         break;
  347.                  case 'S':
  348.                  case 's': operator_intervention=U_SELECT;
  349.                        break;
  350.                  case 'G':
  351.                  case 'g': operator_intervention=U_GOTO;
  352.                        break;
  353.                  default: break;
  354.                  }
  355.              } while (Reply!='N' && Reply !='n' && !operator_intervention);
  356.              _settextposition( 8, 3);
  357.              outtextm("                    ");
  358.  
  359.              } /*A*/
  360.          } /*B*/
  361.          } /*C*/
  362.  
  363.  
  364.      } /*3*/
  365.      Status = FIND_NEXT(&DirBlk);
  366.     } /*1*/
  367.  
  368.  
  369.     /* Process any entries in the linked list of subdirectories    */
  370.     if (TRUE)        /* was !operator_intervention */
  371.     {
  372.     p = strrchr(T_Path, '\\') + 1;    /* remove last filename */
  373.     for (t = Direc.Head; t != NULL;) /* was && !operator_intervention;) */
  374.     {
  375.         *p = '\0';
  376.         strcat(T_Path, t->Body);
  377.         strcat(T_Path, "\\");
  378.         if (!operator_intervention)   /* do not expand */
  379.              operator_intervention=WalkTree(Q,sstring,ignore_case);
  380.         u = t->Next;
  381.         free(t->Body);
  382.         free(t);
  383.         t = u;
  384.     }
  385.     }
  386.  
  387.     return (operator_intervention);
  388. }
  389.  
  390. /*----------------------------------------------------------------------*/
  391. /* SearchQ takes a file name as input and matches it against all of the    */
  392. /* patterns in the linked list of patterns built from command line        */
  393. /* arguments.  The pattern list is an external.                            */
  394.  
  395. int SearchQ (char *Str)
  396. {
  397.     extern QUE_DEF    PatQue;
  398.     QUE_ENTRY      *t;
  399.     int             Result;
  400.  
  401.     for (t = PatQue.Head; t != NULL; t = t->Next) {
  402.         Result = Match(Str, t->Body);
  403.         if (Result != 0) return(Result);
  404.         }
  405.     return (0);
  406. }
  407.  
  408.  
  409.  
  410.  
  411. /****************************************************************************
  412.  *  InitQueue initializes a queue for use by the other queue functions.
  413.  ***************************************************************************/
  414.  
  415. void InitQueue (QUE_DEF *Q)
  416. {
  417.     Q->Head = Q->Current = NULL;
  418.     Q->Count = 0;
  419. }
  420.  
  421. /****************************************************************************
  422.  *  Enque  creates a queue entry linked to the other entries in FIFO order
  423.  *  and puts the string passed into the queue entry.  It returns a pointer
  424.  *  to the entry created [NULL if there is not enough memory for the entry.
  425.  ***************************************************************************/
  426.  
  427. QUE_ENTRY *Enque (QUE_DEF *Q, void *Body)
  428. {
  429.     QUE_ENTRY *p;
  430.     if ((p = malloc(sizeof(QUE_ENTRY))) == NULL ) return(NULL);
  431.     p->Next = NULL;
  432.     if ((p->Body = malloc(strlen(Body) + 1)) == NULL) return(NULL);
  433.     strcpy(p->Body, Body);
  434.     if (Q->Head == NULL) Q->Head = p;
  435.     else Q->Current->Next = p;
  436.     Q->Current = p;
  437.     ++Q->Count;
  438.     return(p);
  439. }
  440.  
  441.  
  442.  
  443. int Match (char *Str, char *Pat)
  444. {
  445.     char S_Name[_MAX_PATH], S_Ext[4];
  446.     char P_Name[_MAX_PATH], P_Ext[4];
  447.     char *p1;
  448.     strupr(Pat);
  449.     if ( (p1 = strrchr(Str, '.')) != NULL ) {
  450.         *p1 = '\0';
  451.         strcpy(S_Name, Str);
  452.         strcpy(S_Ext, p1+1);
  453.         *p1 = '.';
  454.         }
  455.     else {
  456.         strcpy(S_Name, Str);
  457.         S_Ext[0] = '\0';
  458.         }
  459.  
  460.     if ( (p1 = strchr(Pat, '.')) != NULL ) {
  461.         *p1 = '\0';
  462.         strcpy(P_Name, Pat);
  463.         strcpy(P_Ext, p1+1);
  464.         *p1 = '.';
  465.         }
  466.     else {
  467.         strcpy(P_Name, Pat);
  468.         strcpy(P_Ext, "*");
  469.         }
  470.  
  471.     if ( !I_Match(S_Name, P_Name) ) return(0);
  472.     if ( (P_Ext[0] == '\0') && (S_Ext[0] != '\0') ) return(0);
  473.     if ( !I_Match(S_Ext, P_Ext) ) return(0);
  474.     return(1);
  475. }
  476.  
  477.  
  478. static int I_Match (char *Str, char *Pat)
  479. {
  480.     char *p, *p1, *p2, Hold;
  481.     int t;
  482.     if ( (p1 = strchr(Pat, '*')) == NULL)
  483.         return( S_Match(Str, Pat, 1) );
  484.     if (Pat[0] != '*') {
  485.         *p1 = '\0';
  486.         t = S_Match(Str, Pat, 0);
  487.         *p1 = '*';
  488.         if (!t) return(0);
  489.         }
  490.     if (Pat[strlen(Pat)-1] != '*') {
  491.         p2 = strrchr(Pat, '*') + 1;
  492.         if (strlen(Str) < strlen(p2)) return(0);
  493.         if ( !S_Match(&Str[strlen(Str) - strlen(p2)], p2, 1) )
  494.             return(0);
  495.         }
  496.  
  497.     p = Str;
  498.     while ( (p2 = strchr(++p1, '*')) != NULL ) {
  499.         *p2 = '\0';
  500.         Hold = p1[0];
  501.         while ( (p = strchr(p, Hold)) != NULL ) {
  502.             if ( S_Match(p, p1, 0) ) break;
  503.             ++p;
  504.             }
  505.         if (p == NULL) return(0);
  506.         p += strlen(p1);
  507.         *p2 = '*';
  508.         p1 = p2;
  509.         }
  510.     return(1);
  511. }
  512.  
  513.  
  514. static int S_Match (char *S, char *P, int Anchor)
  515. {
  516.     while ( (*P != '\0') && (*S != '\0') ) {
  517.         if ( (*S == *P) || (*P == '?') ) {
  518.             S++;
  519.             P++;
  520.             }
  521.         else return(0);
  522.         }
  523.     if (*P != '\0') return(0);
  524.     if ( Anchor && (*S != '\0') ) return(0);
  525.     return(1);
  526. }
  527.  
  528. /***************************************************************************
  529.  Handles 'where is' screen
  530. */
  531. int whereis(char *searchstring, int *current_page, int *filenumber)
  532. {
  533.     static char fpattern[_MAX_PATH]={'\0'};
  534.     static char org_sstring[50]={'\0'};
  535.     char sstring[50]={'\0'};
  536.  
  537.     short x,y;
  538.     char b[(9*69)+10]={              /* Buffer for string */
  539.         "╔══════════════════════════════════════════════════════════════════╗\n"
  540.         "║                   WHERE IS FILE CONTAINING WHAT                  ║\n"
  541.         "╟──────────────────────────────────────────────────────────────────╢\n"
  542.         "║ Filename pattern:                                                ║\n"
  543.         "║    Search string:                                                ║\n"
  544.         "║                                                                  ║\n"
  545.         "╟──────────────────────────────────────────────────────────────────╢\n"
  546.         "║                                                    ESC to cancel ║\n"
  547.         "╚══════════════════════════════════════════════════════════════════╝\n"
  548.  
  549.               };
  550.  
  551.     char *savedscreen;
  552.     int result,result2;
  553.     int i;
  554.     char *slash;
  555.     int ignore_case=FALSE;
  556.  
  557.     if (!strlen(fpattern)) strcpy(fpattern,searchstring);
  558.  
  559.     savedscreen=saveScrn();
  560.  
  561.     y = ((25 - 9) / 2) + 1;     /* 9 lines */
  562.     x =  (80 - 68) / 2;         /* 68 visible characters per line */
  563.  
  564.     _settextcolor( (short) info_text_color );
  565.     _setbkcolor( (long) info_bg_color );
  566.  
  567.     /* Use text window to place output in middle of screen. */
  568.     _settextwindow( y, x, y + 9, x + 68 );
  569.     shadebox( y, x, y + 9 - 1, x + 68 - 1 );
  570.     outtextm( b );
  571.     _settextposition( 4, 21 );
  572.     outtextm(fpattern);
  573.     _settextposition( 5, 21 );
  574.     outtextm(org_sstring);
  575.     do
  576.     {
  577.     _settextposition( 8, 3 );
  578.     outtextm("Enter a filename pattern, hit Return");
  579.     if (!(result=editstring(4, 21, fpattern, "+=[];|,<>/?\"", 46))) break;
  580.  
  581.     _settextposition( 6, 3 );
  582.     outtextm("Append /I to the string to ignore case");
  583.     _settextposition( 8, 3 );
  584.     outtextm("Enter string, empty to skip IN search, hit Return");
  585.     if (!(result=editstring(5, 21, org_sstring, "", 46))) break;
  586.     _settextposition( 8, 3 );
  587.     for (i=3;i<=52;i++) _outtext(" ");
  588.     _settextposition( 6, 3 );
  589.     for (i=3;i<=52;i++) _outtext(" ");
  590.  
  591.     /* default ignore_case = FALSE */
  592.     strcpy(sstring,org_sstring);
  593.     if (slash=strstr(sstring,"/I"))
  594.     {
  595.         if (slash[2]=='\0')   /* sstring ENDS with /I option, otherwise part of sstring */
  596.         {
  597.            ignore_case=TRUE;
  598.            *slash='\0';
  599.         }
  600.     }
  601.     if (slash=strstr(sstring,"/i"))
  602.     {
  603.         if (slash[2]=='\0')   /* sstring ENDS with /I option, otherwise part of sstring */
  604.         {
  605.            ignore_case=TRUE;
  606.            *slash='\0';
  607.         }
  608.     }
  609.  
  610.     switch (result=fff(fpattern,sstring,ignore_case))     /* result in V_Path */
  611.     {
  612.           case U_ESC: _settextposition( 6, 3 );
  613.               outtextm("Last search canceled");
  614.               hide_mouse();
  615.               for (i=20;i<=63;i++) _outtext(" ");
  616.               show_mouse();
  617.               break;
  618.           case U_SELECT:
  619.           case U_GOTO: slash=set_working_drive_and_dir(V_Path); /* make drive & dir default */
  620.                                     /* and find filename */
  621.                if (!slash)
  622.                {
  623.                  result=FAILURE;
  624.                  break;
  625.                }
  626.  
  627.                /* first try original searchstring */
  628.                if (!Match(slash,searchstring))
  629.                {
  630.                  _settextposition( 8, 3 );
  631.                  outtextm( "Mask changed to *.*" );
  632.                  wait_sec(1000);
  633.                  strcpy(searchstring,"*.*");       /* this should match */
  634.                  extract_directory(searchstring);
  635.                  result2=find_name(slash, current_page, filenumber);
  636.                } else
  637.                  {
  638.                    extract_directory(searchstring);
  639.                    result2=find_name(slash, current_page, filenumber);
  640.                  }
  641.                if (result2==FAILURE)      /* find array might be full */
  642.                {
  643.                    _settextcolor( (short) info_text_color );
  644.                    _setbkcolor( (long) info_bg_color );
  645.                    _settextposition( 8, 3 );
  646.                    outtextm( "Mask changed to " );
  647.                    outtextm( slash );
  648.                    wait_sec(1000);
  649.                    strcpy(searchstring,slash);  /* this should work always */
  650.                    extract_directory(searchstring);
  651.                    result2=find_name(slash, current_page, filenumber);
  652.                }
  653.                if (result2==FAILURE) result=FAILURE;
  654.                break;
  655.           default: break;
  656.     }
  657.     } while (result!=U_SELECT && result!=U_GOTO && result!=FAILURE);
  658.  
  659.     _settextwindow( 3, 1, 23, 80 );
  660.     _setbkcolor( (long) screen_bg_color );
  661.     savedscreen=restScrn(savedscreen);
  662.     return result;
  663. }
  664.  
  665. /***************************************************************************
  666.  Find a string IN a file
  667. */
  668. int find_in_file( char *filename , char *string, int ignore_case)
  669. {
  670.     char *buff;         /* Pointer to data buffer */
  671.     int fn;            /* file handle */
  672.     long fl;            /* file length */
  673.     unsigned int count=0x7fff;    /* buffer size */
  674.     int  found;         /* True if string found */
  675.     long rsize;         /* Amount of data read into buffer */
  676.     register long offset;    /* Position where string code found */
  677.     char progress_char[]={ "/-\\|"};
  678.     static int progress_nr=0;
  679.     char progress_str[]={ "/\0" };
  680.     int Reply;
  681.  
  682.     if (ignore_case) strupr(string);
  683.     if( (fn = open( filename, O_BINARY | O_RDONLY )) == - 1 )
  684.     {
  685.       show_error("Cannot open file ");
  686.       return FALSE;
  687.     }
  688.     /* Get size of file */
  689.     fl = filelength(fn);
  690.     if( fl <  (long) count )
  691.     count = (unsigned int) fl;
  692.  
  693.     /* Dynamically allocate a large file buffer. If there's not enough
  694.      * memory for it, find the largest amount available on the near heap
  695.      */
  696.     if( (buff = (char *)malloc( (size_t)count )) == NULL )
  697.     {
  698.     count = _memmax();
  699.     if( (buff = (char *)malloc( (size_t)count )) == NULL )
  700.     {
  701.          show_error("Can't allocate memory for FIF");
  702.          close(fn);
  703.          return FALSE;
  704.     }
  705.     }
  706.  
  707.     found = FALSE;
  708.     while ( !eof(fn) && !found)
  709.     {
  710.       if( (rsize = (long) read( fn, buff, count )) == FAILURE )
  711.       {
  712.          show_error("Read error ");
  713.          close(fn);
  714.          free(buff);
  715.          return FALSE;
  716.       }
  717.  
  718.       if (ignore_case)
  719.       {
  720.       for (offset=0L; offset < rsize; offset++)
  721.           if (isalpha((int) buff[offset]))
  722.          buff[offset]=(char) toupper((int) buff[offset]);
  723.       }
  724.  
  725.       for (offset=0L; offset <= rsize-strlen(string); offset++)
  726.       {
  727.      if (!(offset%5120L))    /* do checks after 5kb */
  728.      { /*B*/
  729.        if (fl > 5120L)    /* wheel */
  730.        {
  731.            if (progress_nr==3) progress_nr=0;
  732.            else progress_nr++;
  733.            progress_str[0]=progress_char[progress_nr];
  734.            _settextposition( 8, 3);
  735.            outtextm( progress_str );
  736.        }
  737.  
  738.        if (n_kbhit())
  739.        {  /*A*/
  740.          Reply=getkey();
  741.          if (Reply==0x1B)
  742.          {
  743.          _settextposition( 8, 3);
  744.          outtextm("Canceled, skipping this file");
  745.          wait_sec(500);
  746.          _settextposition( 8, 3);
  747.          outtextm("                            ");
  748.  
  749.          close(fn);
  750.          free(buff);
  751.          return FALSE;
  752.          }
  753.        }  /*A*/
  754.      } /*B*/
  755.  
  756.        if (!strncmp(&buff[offset], string, strlen(string) ))
  757.        {
  758.       found = TRUE;
  759.       break;         /* escape from FOR loop */
  760.        }
  761.       }
  762.  
  763.       if (!found && !eof(fn))     /* reposition back strlen(string)-1 to recover from split search string */
  764.       {
  765.     if (lseek (fn, 1L - ((long) (strlen(string))), SEEK_CUR)==FAILURE)
  766.     {
  767.          show_error("Seek error ");
  768.          close(fn);
  769.          free(buff);
  770.          return FALSE;
  771.     }
  772.       }
  773.     }
  774.  
  775.     if (fl > 2048L) /* erase wheel */
  776.     {
  777.     _settextposition( 8, 3);
  778.     outtextm( " " );
  779.     }
  780.  
  781.     free(buff);
  782.     close(fn);
  783.  
  784.     if (!found) return FALSE;    /* String not found */
  785.     else return TRUE;      /* String found */
  786. }
  787.  
  788. /*
  789. **  Remove all files and subdirectories
  790. **  Slow but small code
  791. **  from a public domain demo by Bob Stout
  792. */
  793.  
  794. /*
  795. **  Clean all files from a directory
  796. */
  797.  
  798. void clean_dir(char *path)
  799. {
  800.       char rmpath[_MAX_PATH], *rmfile;
  801.       char scratch[_MAX_PATH];
  802.       struct find_t fbuf;
  803.  
  804.       strcpy(rmpath, path);
  805.       if ('\\' != (rmpath[strlen(rmpath) - 1]))
  806.             strcat(rmpath, "\\");
  807.       rmfile = &rmpath[strlen(rmpath)];
  808.       strcpy(rmfile, "*.*");
  809.       if (!_dos_findfirst(rmpath, _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY |    _A_SYSTEM, &fbuf)) do
  810.       {
  811.         strcpy(rmfile, fbuf.name);
  812.         if (remove(rmpath))
  813.         {
  814.          strcpy(scratch,"Can't delete file ");
  815.          strcat(scratch,rmpath);
  816.          show_error(scratch);
  817.         }
  818.       } while (!_dos_findnext(&fbuf));
  819. }
  820.  
  821. /*
  822. **  Process directories
  823.  * PLEASE PLEASE don't call with do_dir("..")
  824.  * it works fine (I know for sure): cleans up parent directory,
  825.  * which could be your complete harddisk
  826. */
  827.  
  828. void do_dir(char *path)
  829. {
  830.       char search[_MAX_PATH], new[_MAX_PATH];
  831.       char scratch[_MAX_PATH];
  832.       struct find_t ff;
  833.  
  834.       strcpy(search, path);
  835.       if ('\\' != (search[strlen(search) - 1]))
  836.             strcat(search, "\\");
  837.       strcat(search, "*.*");
  838.       if (!_dos_findfirst(search, 0xffff, &ff)) do
  839.       {
  840.             if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
  841.             {
  842.                   strcat(strcat(strcpy(new, path), "\\"), ff.name);
  843.                   do_dir(new);
  844.             }
  845.       } while (!_dos_findnext(&ff));
  846.       clean_dir(path);
  847.       if (rmdir(path))
  848.       {
  849.      strcpy(scratch,"Can't delete directory ");
  850.      strcat(scratch,path);
  851.      show_error(scratch);
  852.       }
  853. }
  854.