home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / mslang / fs24 / fs2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-19  |  38.1 KB  |  1,346 lines

  1.  /* FS2.C
  2.  * whereis functions, remove dir functions
  3.  * MSC7
  4.  * FS 2.4
  5.  * 201093
  6.  * Copyright (C) M. van Breemen, 1992-1993, All rights reserved.
  7.  */
  8.  
  9. #include "FS.H"
  10.  
  11. /* Prototypes */
  12. int copy( char *oldname, char *newname );
  13. int whereis(char *searchstring, int *current_page, int *filenumber );
  14. void outtextm( char *string );
  15. void alert( void );
  16. void show_error( char *message );
  17. void wait_sec( int milliseconds );
  18. void clear_left_button_queue( void );
  19. void clear_right_button_queue( void );
  20. int read_left_button_queue( int *row, int *col );
  21. int read_right_button_queue( int *row, int *col );
  22. void init_mouse( void );
  23. void hide_mouse( void );
  24. void show_mouse( void );
  25. int mouse_button_pressed( void );
  26. unsigned int n_kbhit( void );
  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 __near *saveScrn(void);
  32. char __near *restScrn(char __near *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, int use_soundex);
  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. void construct_search_path( char *linebuf );
  41. char *getpath( int drive, char *buffer, int maxlen );
  42. char __near *show_string(char *string, int bg_color, int text_color);
  43. void paint_box(char *string, int vis_width, int vis_height);
  44. void copy_date_time_attrib( char *source, char *target );
  45. char *soundex(char *instr, char *outstr);
  46. int show_context(char *buffer, long buffersize, long offset, int length);
  47. int contains_nonprintable( char *string);
  48.  
  49. /* global variables */
  50.  
  51. extern int number_of_files;    /* number of files found */
  52.  
  53. extern int order_by;           /* NAME, DATE or SIZE */
  54. extern int order_type;         /* ASCENDING or DESCENDING */
  55.  
  56. extern short int screen_bg_color;
  57. extern short int file_color;
  58. extern short int hidden_file_color;
  59. extern short int directory_color;
  60. extern short int hidden_directory_color;
  61. extern short int volume_label_color;
  62. extern short int cursor_bg_color;
  63. extern short int info_bg_color;
  64. extern short int info_text_color;
  65. extern short int error_text_color;
  66. extern short int error_bg_color;
  67.  
  68. typedef struct find_t_small {
  69.                 char name [13];
  70.                 char attrib;
  71.                 unsigned long datetime_or_size;
  72.                 } FIND_T_SMALL;
  73.  
  74. extern FIND_T_SMALL *find;      /* pointer to the file info structures */
  75. extern int mouse_present;       /* boolean is there a mouse ? */
  76. extern int mouse_row;   /* mouse position, NOT screen rows and columns */
  77. extern int mouse_col;
  78. extern int max_files;           /* maximal number of accessible files per directory or root, defaults to 456 */
  79. extern int dos_error;           /* set by error handler */
  80. extern int dos_retries;         /* set by error handler */
  81. extern int dos_error_auto_fail; /* read by error handler */
  82.  
  83.  
  84. /*---------------------------------------------------------------------------*/
  85. /*   FF Routines taken from FFF 3.4.5, a public domain program to search files
  86.  *      Author: Don A. Williams                                                                                  *
  87.  *              CompuServ -                                                                                              *
  88.  *              Genie     - DON-WILL                                                                             
  89.  *      Customized !!
  90. */
  91.  
  92.  
  93. #define U_ESC    1
  94. #define U_SELECT 2
  95. #define U_GOTO   3
  96. #define U_ERROR  4
  97.  
  98. #define FIND_FIRST(Name,Block,Attrib) _dos_findfirst(Name, Attrib, Block);
  99. #define FIND_NEXT(Block) _dos_findnext(Block);
  100. #define DIR_ENTRY find_t        /* Name of the directory entry structure        */
  101. #define D_ATTRIB attrib         /* Attribute field in directory entry           */
  102. #define D_NAME name             /* File name field in directory entry           */
  103.  
  104.  
  105. typedef struct QueEntry {
  106.               struct QueEntry *Next;
  107.               char  *Body;
  108.             } QUE_ENTRY;
  109.  
  110. typedef struct QueDef {
  111.             QUE_ENTRY *Head, *Current;
  112.             int        Count;
  113.               } QUE_DEF;
  114.  
  115. /* Function prototypes    */
  116.  
  117. int             fff( char *fpattern, char *sstring, int ignore_case, int use_soundex);
  118. void            InitQueue (QUE_DEF *Q);
  119. QUE_ENTRY       *Enque (QUE_DEF *Q, void *Body);
  120. int             WalkTree (QUE_DEF * Q, char *sstring , int ignore_case, int use_soundex);
  121. int             SearchQ (char *Str);
  122. int             Match (char *Str, char *Pat);
  123. static int      I_Match (char *Str, char *Pat);
  124. static int      S_Match (char *S, char *P, int Anchor);
  125. void            DeleteQueue( QUE_DEF PatQue );
  126.  
  127. void            clean_dir(char *path);
  128. void            do_dir(char *path);
  129.  
  130. /*----------------------------------------------------------------------*/
  131.  
  132. extern QUE_DEF  PatQue;
  133. extern char             T_Path[_MAX_PATH];                    /* Temporary directory path to search   */
  134. extern char             V_Path[_MAX_PATH];                    /* Selected file */
  135.  
  136. void DeleteQueue( QUE_DEF PatQue )
  137. {
  138.     QUE_ENTRY *t, *u;
  139.     for (t = PatQue.Head; t != NULL;)
  140.     {
  141.     u = t->Next;
  142.     free(t->Body);
  143.     free(t);
  144.     t = u;
  145.     }
  146. }
  147.  
  148. int fff(char *fpattern, char *sstring, int ignore_case, int use_soundex)
  149. {
  150.     char            *p, *p2;
  151.     char            scratchfpattern[_MAX_PATH];
  152.     char            Path[_MAX_PATH];                              /* Current directory path to search             */
  153.     char            Devices[16] = "";
  154.     int             Result;
  155.     int             i;
  156.  
  157.     strcpy (scratchfpattern,fpattern);
  158.     InitQueue(&PatQue);
  159.     strcpy(Path, "C:\\");
  160.     Devices[0] = (char) (_getdrive() - 1 + 'A');
  161.     Devices[1] = '\0';
  162.  
  163. /*      Interpret fpattern tokens */
  164.     p = strtok( scratchfpattern, " " );     /* Find first token     */
  165.     while( p != NULL )
  166.     {
  167.  
  168.             if ((p2 = strchr(p, ':')) != NULL)  /* process devices */
  169.             {
  170.                 *p2 = '\0';
  171.                 strcpy(Devices, p);
  172.                 p2++;                  /* skip NULL */
  173.                 p = p2;                /* remove device */
  174.             }
  175.             if ((p2 = strrchr(p, '\\')) != NULL)  /* process path */
  176.             {
  177.                 *p2 = '\0';
  178.                 if (p[0]=='\\') strcpy(Path,"C:");
  179.                 else strcpy(Path,"C:\\");
  180.                 strcat(Path, p);
  181.                 if (Path[strlen(Path)-1]!='\\') strcat(Path,"\\");
  182.                 p2++;                         /* skip backslash */
  183.                 p = p2;                       /* remove path */
  184.             }
  185.             if (strlen(p))
  186.             {
  187.                   if (strlen(p)>12)
  188.                   {
  189.                      DeleteQueue( PatQue );
  190.                      return FAILURE;  /* illegal filename length, abort */
  191.                   }
  192.                   if (!Enque(&PatQue, strupr(p)))
  193.                   {
  194.                     DeleteQueue( PatQue );
  195.                     _settextposition( 8, 3 );
  196.                     outtextm( "Memory exhausted, search aborted");
  197.                     alert();
  198.                     wait_sec(1000);
  199.                     return FAILURE;
  200.                   }
  201.             }
  202.             p = strtok( NULL, " " );        /* Find next token             */
  203.     }
  204.  
  205. /* This does the work by walking the directory structure for each specified     */
  206. /* disk                                                                                                                                         */
  207.  
  208.     p = Devices;
  209.     while (*p != '\0') {
  210.         strcpy(T_Path, Path);
  211.         T_Path[0] = *p++;         /* set drive */
  212.         if (Result=WalkTree(&PatQue,sstring,ignore_case,use_soundex)) break;
  213.         }
  214.     if (!Result)
  215.     {
  216.               _settextposition( 6, 3 );
  217.               outtextm("No more matches");
  218.               hide_mouse();
  219.               for (i=15;i<=63;i++) _outtext(" ");
  220.               show_mouse();
  221.     }
  222.  
  223.     DeleteQueue( PatQue );
  224.     return (Result);
  225. }
  226.  
  227. /*----------------------------------------------------------------------*/
  228. /* WalkTree is a recursive routine that walks the directory structure   */
  229. /* specifed by the external T_Path.  It bypasses Volume IDs and builds  */
  230. /* a linked list queue of directories that is processed after all of    */
  231. /* the file entries have been processed.                                                                */
  232.  
  233. int WalkTree (QUE_DEF *Q, char *sstring, int ignore_case, int use_soundex)
  234. {
  235.     int         Status;
  236.     char        Reply;
  237.     QUE_DEF     Direc;
  238.     QUE_ENTRY   *t, *u;
  239.     char        *p;
  240.     struct DIR_ENTRY  DirBlk;           /* Directory Entry structure                    */
  241.     int         TotalFiles = 0;         /* Total files processed                        */
  242.     int         TotalMatch = 0;         /* Count of all files matched                   */
  243.     int operator_intervention=FALSE;
  244.     register int i;
  245.     int mouse_row, mouse_col;
  246.     int ulc_row, ulc_col, dummy;        /* upper left corner row and column of window */
  247.  
  248.     _gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy);    /* mouse coordinates are absolute! */
  249.     InitQueue(&Direc);
  250.     strcat(T_Path, "*.*");
  251.     
  252.     dos_error=0;
  253.     dos_retries=0;
  254.     dos_error_auto_fail=TRUE;
  255.     Status = FIND_FIRST(T_Path, &DirBlk, 0xFF);
  256.     if (dos_error) operator_intervention=U_ERROR;
  257.     dos_error=0;
  258.     dos_retries=0;
  259.     dos_error_auto_fail=FALSE;
  260.     
  261.     *(strrchr(T_Path, '\\') + 1) = '\0';
  262.     _settextposition( 6, 3 );
  263.     outtextm(T_Path);       /* show progress */
  264.     hide_mouse();
  265.     for (i=strlen(T_Path);i<=63;i++) _outtext(" ");
  266.     show_mouse();
  267.  
  268.     while (!Status && !operator_intervention)
  269.     {  /*1*/
  270.      if (n_kbhit() || mouse_button_pressed())  /* operator ESCapes */
  271.      {  /*2*/
  272.          if (n_kbhit()) Reply = (char) getkey();
  273.          else
  274.          {
  275.          if (mouse_present)
  276.          if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  277.          {
  278.              if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66) Reply=0x1B;
  279.              else Reply='\0';
  280.          }
  281.          }
  282.  
  283.          if (Reply == 0x1B)    /* confirm */
  284.          {
  285.          _settextposition( 8, 3 );
  286.          outtextm("Type ESC to stop search, other key to continue");
  287.          _settextposition( 1, 1 );
  288.          Reply = (char) getkey();
  289.          _settextposition( 8, 3 );
  290.          outtextm("                                              ");
  291.          if (Reply==0x1B) operator_intervention=U_ESC;
  292.          }
  293.      } /*2*/
  294.  
  295.      if (!operator_intervention)
  296.      {
  297.          if ((DirBlk.D_ATTRIB & _A_VOLID) != 0)  /* Bypass Volume Label */
  298.          {
  299.          Status = FIND_NEXT(&DirBlk);
  300.          continue;
  301.          }
  302.      }
  303.  
  304.      if (!operator_intervention)
  305.      {  /*3*/
  306.          if ((DirBlk.D_ATTRIB & _A_SUBDIR) != 0) /* Process subdirectory */
  307.          {
  308.          if (DirBlk.D_NAME[0] != '.')
  309.          {
  310.              if (!Enque(&Direc, DirBlk.D_NAME))
  311.              {
  312.              _settextposition( 8, 3 );
  313.              outtextm( "Memory exhausted, search aborted");
  314.              alert();
  315.              wait_sec(1000);
  316.              operator_intervention=FAILURE;
  317.              }
  318.          }
  319.          }
  320.          else
  321.          { /*C*/                            /* Process file entry */
  322.          ++TotalFiles;
  323.          if ( SearchQ(DirBlk.D_NAME) )
  324.          {  /*B*/
  325.              strcpy(V_Path, T_Path);
  326.              strcat(V_Path, DirBlk.D_NAME);
  327.              _settextposition( 6, 3 );
  328.              outtextm(V_Path); /* show filename match */
  329.              hide_mouse();
  330.              for (i=strlen(V_Path);i<=63;i++) _outtext(" ");
  331.              show_mouse();
  332.  
  333.              if (strlen(sstring) ? find_in_file(V_Path,sstring, ignore_case, use_soundex) : TRUE)
  334.              { /*A*/
  335.              ++TotalMatch;
  336.              _settextposition( 8, 3);
  337.              outtextm("Next, Select, Goto  ");
  338.              do
  339.              {
  340.                  while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
  341.                  if (n_kbhit()) Reply = (char) getkey();
  342.                  else
  343.                  {
  344.                  Reply='\0';
  345.                  if (mouse_present)
  346.                  if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  347.                  {
  348.                      if ((mouse_col-ulc_col+1)>=3 && (mouse_col-ulc_col+1)<=6)
  349.                      Reply='N';
  350.                      if ((mouse_col-ulc_col+1)>=9 && (mouse_col-ulc_col+1)<=14)
  351.                      Reply='S';
  352.                      if ((mouse_col-ulc_col+1)>=17 && (mouse_col-ulc_col+1)<=20)
  353.                      Reply='G';
  354.                      if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66)
  355.                      Reply=0x1B;
  356.                  }
  357.                  }
  358.                  switch (Reply)
  359.                  {
  360.                  case 0x1B: _settextposition( 8, 3);
  361.                         outtextm("                    ");
  362.                         operator_intervention=U_ESC;
  363.                         break;
  364.                  case 'S':
  365.                  case 's': operator_intervention=U_SELECT;
  366.                        break;
  367.                  case 'G':
  368.                  case 'g': operator_intervention=U_GOTO;
  369.                        break;
  370.                  default: break;
  371.                  }
  372.              } while (Reply!='N' && Reply !='n' && !operator_intervention);
  373.              _settextposition( 8, 3);
  374.              outtextm("                    ");
  375.  
  376.              } /*A*/
  377.          } /*B*/
  378.          } /*C*/
  379.  
  380.  
  381.      } /*3*/
  382.      Status = FIND_NEXT(&DirBlk);
  383.     } /*1*/
  384.  
  385.  
  386.     /* Process any entries in the linked list of subdirectories */
  387.     if (TRUE)       /* was !operator_intervention */
  388.     {
  389.     p = strrchr(T_Path, '\\') + 1;  /* remove last filename */
  390.     for (t = Direc.Head; t != NULL;) /* was && !operator_intervention;) */
  391.     {
  392.         *p = '\0';
  393.         strcat(T_Path, t->Body);
  394.         strcat(T_Path, "\\");
  395.         if (!operator_intervention)   /* do not expand */
  396.              operator_intervention=WalkTree(Q,sstring,ignore_case, use_soundex);
  397.         u = t->Next;
  398.         free(t->Body);
  399.         free(t);
  400.         t = u;
  401.     }
  402.     }
  403.  
  404.     return (operator_intervention);
  405. }
  406.  
  407. /*----------------------------------------------------------------------*/
  408. /* SearchQ takes a file name as input and matches it against all of the */
  409. /* patterns in the linked list of patterns built from command line              */
  410. /* arguments.  The pattern list is an external.                                                 */
  411.  
  412. int SearchQ (char *Str)
  413. {
  414.     extern QUE_DEF  PatQue;
  415.     QUE_ENTRY      *t;
  416.     int             Result;
  417.  
  418.     for (t = PatQue.Head; t != NULL; t = t->Next) {
  419.         Result = Match(Str, t->Body);
  420.         if (Result != 0) return(Result);
  421.         }
  422.     return (0);
  423. }
  424.  
  425.  
  426.  
  427.  
  428. /****************************************************************************
  429.  *  InitQueue initializes a queue for use by the other queue functions.
  430.  ***************************************************************************/
  431.  
  432. void InitQueue (QUE_DEF *Q)
  433. {
  434.     Q->Head = Q->Current = NULL;
  435.     Q->Count = 0;
  436. }
  437.  
  438. /****************************************************************************
  439.  *  Enque  creates a queue entry linked to the other entries in FIFO order
  440.  *  and puts the string passed into the queue entry.  It returns a pointer
  441.  *  to the entry created [NULL if there is not enough memory for the entry.
  442.  ***************************************************************************/
  443.  
  444. QUE_ENTRY *Enque (QUE_DEF *Q, void *Body)
  445. {
  446.     QUE_ENTRY *p;
  447.     if ((p = malloc(sizeof(QUE_ENTRY))) == NULL ) return(NULL);
  448.     p->Next = NULL;
  449.     if ((p->Body = malloc(strlen(Body) + 1)) == NULL) return(NULL);
  450.     strcpy(p->Body, Body);
  451.     if (Q->Head == NULL) Q->Head = p;
  452.     else Q->Current->Next = p;
  453.     Q->Current = p;
  454.     ++Q->Count;
  455.     return(p);
  456. }
  457.  
  458.  
  459.  
  460. int Match (char *Str, char *Pat)
  461. {
  462.     char S_Name[_MAX_PATH], S_Ext[4];
  463.     char P_Name[_MAX_PATH], P_Ext[4];
  464.     char *p1;
  465.     strupr(Pat);
  466.     if ( (p1 = strrchr(Str, '.')) != NULL ) {
  467.         *p1 = '\0';
  468.         strcpy(S_Name, Str);
  469.         strcpy(S_Ext, p1+1);
  470.         *p1 = '.';
  471.         }
  472.     else {
  473.         strcpy(S_Name, Str);
  474.         S_Ext[0] = '\0';
  475.         }
  476.  
  477.     if ( (p1 = strchr(Pat, '.')) != NULL ) {
  478.         *p1 = '\0';
  479.         strcpy(P_Name, Pat);
  480.         strcpy(P_Ext, p1+1);
  481.         *p1 = '.';
  482.         }
  483.     else {
  484.         strcpy(P_Name, Pat);
  485.         strcpy(P_Ext, "*");
  486.         }
  487.  
  488.     if ( !I_Match(S_Name, P_Name) ) return(0);
  489.     if ( (P_Ext[0] == '\0') && (S_Ext[0] != '\0') ) return(0);
  490.     if ( !I_Match(S_Ext, P_Ext) ) return(0);
  491.     return(1);
  492. }
  493.  
  494.  
  495. static int I_Match (char *Str, char *Pat)
  496. {
  497.     char *p, *p1, *p2, Hold;
  498.     int t;
  499.     if ( (p1 = strchr(Pat, '*')) == NULL)
  500.         return( S_Match(Str, Pat, 1) );
  501.     if (Pat[0] != '*') {
  502.         *p1 = '\0';
  503.         t = S_Match(Str, Pat, 0);
  504.         *p1 = '*';
  505.         if (!t) return(0);
  506.         }
  507.     if (Pat[strlen(Pat)-1] != '*') {
  508.         p2 = strrchr(Pat, '*') + 1;
  509.         if (strlen(Str) < strlen(p2)) return(0);
  510.         if ( !S_Match(&Str[strlen(Str) - strlen(p2)], p2, 1) )
  511.             return(0);
  512.         }
  513.  
  514.     p = Str;
  515.     while ( (p2 = strchr(++p1, '*')) != NULL ) {
  516.         *p2 = '\0';
  517.         Hold = p1[0];
  518.         while ( (p = strchr(p, Hold)) != NULL ) {
  519.             if ( S_Match(p, p1, 0) ) break;
  520.             ++p;
  521.             }
  522.         if (p == NULL) return(0);
  523.         p += strlen(p1);
  524.         *p2 = '*';
  525.         p1 = p2;
  526.         }
  527.     return(1);
  528. }
  529.  
  530.  
  531. static int S_Match (char *S, char *P, int Anchor)
  532. {
  533.     while ( (*P != '\0') && (*S != '\0') ) {
  534.         if ( (*S == *P) || (*P == '?') ) {
  535.             S++;
  536.             P++;
  537.             }
  538.         else return(0);
  539.         }
  540.     if (*P != '\0') return(0);
  541.     if ( Anchor && (*S != '\0') ) return(0);
  542.     return(1);
  543. }
  544.  
  545. /***************************************************************************
  546.  Handles 'where is' screen
  547.  searchstring is the mask without device and path !
  548.  fpattern defaults to device + path + mask
  549. */
  550. int whereis(char *searchstring, int *current_page, int *filenumber)
  551. {
  552.     static char fpattern[_MAX_PATH]={'\0'};
  553.     static char org_sstring[50]={'\0'};
  554.     char sstring[50]={'\0'};
  555.  
  556.     char b[(9*69)+10]={               /* Buffer for string */
  557.         "╔══════════════════════════════════════════════════════════════════╗\n"
  558.         "║                   WHERE IS FILE CONTAINING WHAT                  ║\n"
  559.         "╠══════════════════════════════════════════════════════════════════╣\n"
  560.         "║ Filename pattern:                                                ║\n"
  561.         "║    Search string:                                                ║\n"
  562.         "║                                                                  ║\n"
  563.         "╠══════════════════════════════════════════════════════════════════╣\n"
  564.         "║                                                    ESC to cancel ║\n"
  565.         "╚══════════════════════════════════════════════════════════════════╝\n"
  566.  
  567.               };
  568.  
  569.     char __near *savedscreen;
  570.     int result,result2;
  571.     int i;
  572.     char *slash;
  573.     int ignore_case;
  574.     int use_soundex;
  575.  
  576.     construct_search_path(fpattern);
  577.  
  578.     if (!strlen(fpattern)) strcpy(fpattern,searchstring);
  579.     if (strlen(fpattern)>46) strcpy(fpattern,searchstring);
  580.     savedscreen=saveScrn();
  581.  
  582.  
  583.     _settextcolor( (short) info_text_color );
  584.     _setbkcolor( (long) info_bg_color );
  585.  
  586.     paint_box( b, 68, 9);
  587.  
  588.     _settextposition( 4, 21 );
  589.     outtextm(fpattern);
  590.     _settextposition( 5, 21 );
  591.     outtextm(org_sstring);
  592.     do
  593.     {
  594.  
  595.     _settextposition( 8, 3 );
  596.     outtextm("Enter a filename pattern, hit Return");
  597.     if (!(result=editstring(4, 21, fpattern, "+=[];|,<>/\"", 46))) break;
  598.     if (!strlen(fpattern)) strcpy(fpattern,"*.*");
  599.  
  600.     _settextposition( 6, 3 );
  601.     outtextm("Append /I to the string to ignore case, /S to use soundex");
  602.     _settextposition( 8, 3 );
  603.     outtextm("Enter string, empty to skip IN search, hit Return");
  604.     if (!(result=editstring(5, 21, org_sstring, "", 46))) break;
  605.     _settextposition( 8, 3 );
  606.         hide_mouse();
  607.     for (i=3;i<=52;i++) _outtext(" ");
  608.     _settextposition( 6, 3 );
  609.     for (i=3;i<=62;i++) _outtext(" ");
  610.         show_mouse();
  611.     strcpy(sstring,org_sstring);
  612.  
  613.     /* default ignore_case = FALSE */
  614.     ignore_case=FALSE;
  615.     if (slash=strstr(sstring,"/I"))
  616.     {
  617.         if (slash[2]=='\0')   /* sstring ENDS with /I option, otherwise part of sstring */
  618.         {
  619.            ignore_case=TRUE;
  620.            *(slash)='\0';
  621.         }
  622.     }
  623.     if (slash=strstr(sstring,"/i"))
  624.     {
  625.         if (slash[2]=='\0')   /* sstring ENDS with /I option, otherwise part of sstring */
  626.         {
  627.            ignore_case=TRUE;
  628.            *(slash)='\0';
  629.         }
  630.     }
  631.  
  632.     /* default use_soundex = FALSE */
  633.     use_soundex=FALSE;
  634.     if (slash=strstr(sstring,"/S"))
  635.     {
  636.         if (slash[2]=='\0')   /* sstring ENDS with /S option, otherwise part of sstring */
  637.         {
  638.            use_soundex=TRUE;
  639.            *(slash)='\0';
  640.         }
  641.     }
  642.     if (slash=strstr(sstring,"/s"))
  643.     {
  644.         if (slash[2]=='\0')   /* sstring ENDS with /S option, otherwise part of sstring */
  645.         {
  646.            use_soundex=TRUE;
  647.            *(slash)='\0';
  648.         }
  649.     }
  650.  
  651.     switch (result=fff(fpattern,sstring,ignore_case,use_soundex))     /* result in V_Path */
  652.     {
  653.           case U_ESC: _settextposition( 6, 3 );
  654.               outtextm("Last search canceled");
  655.               hide_mouse();
  656.               for (i=20;i<=63;i++) _outtext(" ");
  657.               show_mouse();
  658.               break;
  659.           case U_ERROR: _settextposition( 6, 3 );
  660.                 outtextm("A disk error occurred");
  661.                 hide_mouse();
  662.                 for (i=20;i<=63;i++) _outtext(" ");
  663.                 show_mouse();
  664.                 break;
  665.           case U_SELECT:
  666.           case U_GOTO: slash=set_working_drive_and_dir(V_Path); /* make drive & dir default */
  667.                                     /* and find filename */
  668.                if (!slash)
  669.                {
  670.                  result=FAILURE;
  671.                  break;
  672.                }
  673.  
  674.                /* first try original searchstring */
  675.                if (!Match(slash,searchstring))
  676.                {
  677.                  _settextposition( 8, 3 );
  678.                  outtextm( "Mask changed to *.*" );
  679.                  wait_sec(1000);
  680.                  strcpy(searchstring,"*.*");       /* this should match */
  681.                  extract_directory(searchstring);
  682.                  result2=find_name(slash, current_page, filenumber);
  683.                } else
  684.                  {
  685.                    extract_directory(searchstring);
  686.                    result2=find_name(slash, current_page, filenumber);
  687.                  }
  688.                if (result2==FAILURE)          /* find array might be full */
  689.                {
  690.                    _settextcolor( (short) info_text_color );
  691.                    _setbkcolor( (long) info_bg_color );
  692.                    _settextposition( 8, 3 );
  693.                    outtextm( "Mask changed to " );
  694.                    outtextm( slash );
  695.                    wait_sec(1000);
  696.                    strcpy(searchstring,slash);  /* this should work always */
  697.                    extract_directory(searchstring);
  698.                    result2=find_name(slash, current_page, filenumber);
  699.                }
  700.                if (result2==FAILURE) result=FAILURE;
  701.                break;
  702.           default: break;
  703.     }
  704.     } while (result!=U_SELECT && result!=U_GOTO && result!=FAILURE);
  705.  
  706.     _settextwindow( 3, 1, 23, 80 );
  707.     _setbkcolor( (long) screen_bg_color );
  708.     savedscreen=restScrn(savedscreen);
  709.     return result;
  710. }
  711.  
  712. /***************************************************************************
  713.  Find a string IN a file
  714. */
  715. int find_in_file( char *filename , char *string, int ignore_case, int use_soundex)
  716. {
  717.     char *buff;                 /* Pointer to data buffer */
  718.     int fn;                     /* file handle */
  719.     long fl;                    /* file length */
  720.     unsigned int count=0x7fff;  /* buffer size */
  721.     int  found;                 /* True if string found */
  722.     long rsize;                 /* Amount of data read into buffer */
  723.     register long offset;       /* Position where string code found */
  724.     char progress_char[]={ "/-\\|"};
  725.     static int progress_nr=0;
  726.     char progress_str[]={ "/\0" };
  727.     int Reply;
  728.     char scratch[50];
  729.     char snd1[50];
  730.     char snd2[50];
  731.  
  732.     if (ignore_case) strupr(string);
  733.  
  734.     if (use_soundex)
  735.     {
  736.      if (soundex(string,snd2)) strupr(snd2);
  737.      else
  738.      {
  739.          strcpy(snd2,"");
  740.          use_soundex=FALSE;
  741.      }
  742.     }
  743.  
  744.     if( (fn = open( filename, O_BINARY | O_RDONLY )) == - 1 )
  745.     {
  746.       show_error("Cannot open file");
  747.       return FALSE;
  748.     }
  749.     /* Get size of file */
  750.     fl = filelength(fn);
  751.     if( fl <  (long) count )
  752.     count = (unsigned int) fl;
  753.  
  754.     /* Dynamically allocate a large file buffer. If there's not enough
  755.      * memory for it, find the largest amount available
  756.      */
  757.     if( (buff = (char *)malloc( (size_t)count )) == NULL )
  758.     {
  759.     count = _memmax();
  760.     if( (buff = (char *)malloc( (size_t)count )) == NULL )
  761.     {
  762.          show_error("Cannot allocate memory for FIF");
  763.          close(fn);
  764.          return FALSE;
  765.     }
  766.     }
  767.  
  768.     found = FALSE;
  769.     while ( !eof(fn) && !found)
  770.     {
  771.       if( (rsize = (long) read( fn, buff, count )) == FAILURE )
  772.       {
  773.          show_error("Read error");
  774.          close(fn);
  775.          free(buff);
  776.          return FALSE;
  777.       }
  778.  
  779.       if (ignore_case)
  780.       {
  781.       for (offset=0L; offset < rsize; offset++)
  782.           if (isalpha((int) buff[offset]))
  783.          buff[offset]=(char) toupper((int) buff[offset]);
  784.       }
  785.  
  786.       for (offset=0L; offset <= rsize-strlen(string); offset++)
  787.       {
  788.      if (!(offset%5120L))   /* do checks after 5kb */
  789.      { /*B*/
  790.        if (fl > 5120L)      /* wheel */
  791.        {
  792.            if (progress_nr==3) progress_nr=0;
  793.            else progress_nr++;
  794.            progress_str[0]=progress_char[progress_nr];
  795.            _settextposition( 8, 3);
  796.            outtextm( progress_str );
  797.        }
  798.  
  799.        if (n_kbhit())
  800.        {  /*A*/
  801.          Reply=getkey();
  802.          if (Reply==0x1B)
  803.          {
  804.          _settextposition( 8, 3);
  805.          outtextm("Canceled, skipping this file");
  806.          wait_sec(500);
  807.          _settextposition( 8, 3);
  808.          outtextm("                            ");
  809.  
  810.          close(fn);
  811.          free(buff);
  812.          return FALSE;
  813.          }
  814.        }  /*A*/
  815.      } /*B*/
  816.  
  817.        if (use_soundex)
  818.        {
  819.       strncpy(scratch,&buff[offset],strlen(string));
  820.       scratch[strlen(string)]='\0';
  821.  
  822.       /* strings should be both alphanum ? */
  823.       if (contains_nonprintable(string) ||
  824.           (!contains_nonprintable(scratch) && !contains_nonprintable(string)))
  825.       {
  826.           if (soundex(scratch,snd1))
  827.           {
  828.         strupr(snd1);                           /* Ignore case */
  829.         if (!strcmp(snd1,snd2))                 /* here is the check */
  830.         {
  831.           found = TRUE;
  832.           if (show_context(buff,rsize,offset,strlen(string))) break;
  833.           else found = FALSE;
  834.         }
  835.           }
  836.       }
  837.        }
  838.        else
  839.        {
  840.      if (!strncmp(&buff[offset], string, strlen(string) ))   /* here is the check */
  841.      {
  842.        found = TRUE;
  843.        if (show_context(buff,rsize,offset,strlen(string))) break; /* escape from FOR loop */
  844.        else found = FALSE;
  845.      }
  846.        }
  847.       }
  848.  
  849.       if (!found && !eof(fn))    /* reposition back strlen(string)-1 to recover from split search string */
  850.       {
  851.     if (lseek (fn, 1L - ((long) (strlen(string))), SEEK_CUR)==FAILURE)
  852.     {
  853.          show_error("Seek error");
  854.          close(fn);
  855.          free(buff);
  856.          return FALSE;
  857.     }
  858.       }
  859.     }
  860.  
  861.     if (fl > 2048L) /* erase wheel */
  862.     {
  863.     _settextposition( 8, 3);
  864.     outtextm( " " );
  865.     }
  866.  
  867.     free(buff);
  868.     close(fn);
  869.  
  870.     if (!found) return FALSE;   /* String not found */
  871.     else return TRUE;     /* String found */
  872. }
  873.  
  874. /*
  875. **  Remove all files and subdirectories
  876. **  Slow but small code
  877. **  from a public domain demo by Bob Stout
  878. */
  879.  
  880. /*
  881. **  Clean all files from a directory
  882. */
  883.  
  884. void clean_dir(char *path)
  885. {
  886.       char rmpath[_MAX_PATH], *rmfile;
  887.       char scratch[_MAX_PATH];
  888.       struct find_t fbuf;
  889.  
  890.       strcpy(rmpath, path);
  891.       if ('\\' != (rmpath[strlen(rmpath) - 1]))
  892.         strcat(rmpath, "\\");
  893.       rmfile = &rmpath[strlen(rmpath)];
  894.       strcpy(rmfile, "*.*");
  895.       if (!_dos_findfirst(rmpath, _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY | _A_SYSTEM, &fbuf)) do
  896.       {
  897.         strcpy(rmfile, fbuf.name);
  898.         if (remove(rmpath))
  899.         {
  900.          strcpy(scratch,"Cannot delete file");
  901.          strcat(scratch,rmpath);
  902.          show_error(scratch);
  903.         }
  904.       } while (!_dos_findnext(&fbuf));
  905. }
  906.  
  907. /*
  908. **  Process directories
  909.  * PLEASE PLEASE don't call with do_dir("..")
  910.  * it works fine (I know for sure): cleans up parent directory,
  911.  * which could be your complete harddisk
  912. */
  913.  
  914. void do_dir(char *path)
  915. {
  916.       char search[_MAX_PATH], new[_MAX_PATH];
  917.       char scratch[_MAX_PATH];
  918.       struct find_t ff;
  919.  
  920.       strcpy(search, path);
  921.       if ('\\' != (search[strlen(search) - 1]))
  922.         strcat(search, "\\");
  923.       strcat(search, "*.*");
  924.       if (!_dos_findfirst(search, 0xffff, &ff)) do
  925.       {
  926.         if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
  927.         {
  928.           strcat(strcat(strcpy(new, path), "\\"), ff.name);
  929.           do_dir(new);
  930.         }
  931.       } while (!_dos_findnext(&ff));
  932.       clean_dir(path);
  933.       if (rmdir(path))
  934.       {
  935.      strcpy(scratch,"Cannot delete directory ");
  936.      strcat(scratch,path);
  937.      show_error(scratch);
  938.       }
  939. }
  940.  
  941.  
  942. /*
  943.  * stripped version of FLOPTEST from William Zentmayer 06-JAN-92
  944.  * parameters:
  945.  * int drive = floppy drive letter to test A=0,B=1
  946.  * returns 0 if ready 
  947.  */
  948.  
  949. int floptest(int drv);
  950. void int13(union REGS *, union REGS *, struct SREGS *);
  951.  
  952. int floptest(int drv)
  953. {
  954.    union REGS InRegs, OutRegs;
  955.    struct SREGS SegRegs;
  956.    char sector_data[512];
  957.    char far *buffer=sector_data;
  958.  
  959.    InRegs.h.al=0x01;                             // number of sectors
  960.    InRegs.h.ch=0x00;                             // cylinder       
  961.    InRegs.h.cl=0x01;                             // sector              
  962.    InRegs.h.dh=0x00;                             // head                 
  963.    InRegs.h.dl=drv;                              // drive number 0=A,1=B,...
  964.    SegRegs.es =FP_SEG(buffer);                   // segment of buffer
  965.    InRegs.x.bx=FP_OFF(buffer);                   // offset of buffer
  966.  
  967.    InRegs.h.ah=0x02;                             // read sector
  968.    int13(&InRegs,&OutRegs,&SegRegs);             // int 13h func 02h
  969.  
  970.    return OutRegs.h.ah;
  971. }
  972.  
  973. void int13(union REGS *InRegs, union REGS *OutRegs, struct SREGS *SegRegs)
  974. {
  975.    register int i;
  976.    int holdreg=InRegs-> h.ah;
  977.  
  978.    for(i=0;i<3;i++)
  979.        {
  980.        InRegs-> h.ah=0x00;                       // reset controller
  981.        int86(0x13,InRegs,OutRegs);               // int 13h func 00h
  982.        if(OutRegs-> h.ah)                        // reset failed     
  983.        break;                                // exit loop - error
  984.  
  985.        InRegs-> h.ah=holdreg;                    // called int 13h function
  986.        int86x(0x13,InRegs,OutRegs,SegRegs);      // interrupt 13h
  987.        if(OutRegs-> h.ah)                        // function failed
  988.        continue;                             // retry
  989.        }
  990. }
  991.  
  992. /**********************************************************************
  993.  * Copies one file to another (both specified by path). Dynamically
  994.  * allocates memory for the file buffer. Prompts before overwriting
  995.  * existing file. Returns 0 if successful, otherwise an error number.
  996.  */
  997. int copy( char *source, char *target )
  998. {
  999.     char __near *buf;
  1000.     char __huge *hbuf;
  1001.     int hsource, htarget, ch;
  1002.     long fsize;
  1003.     unsigned int count;
  1004.     unsigned int blocks;
  1005.     unsigned int last_count_size;
  1006.     unsigned int first_count_size;
  1007.     unsigned int iTel_r;
  1008.     unsigned int iTel_w;
  1009.     char full_source[_MAX_PATH];
  1010.     char full_target[_MAX_PATH];
  1011.     char __near *savedscreen;
  1012.  
  1013.     strupr(source);
  1014.     strupr(target);
  1015.  
  1016.     if (_fullpath( full_source, source, _MAX_PATH ) &&
  1017.     _fullpath( full_target, target, _MAX_PATH ))
  1018.     {
  1019.        if (!strcmp(full_source,full_target))   /* cyclic copy */
  1020.        {
  1021.       show_error("Cannot copy a file to itself");
  1022.       return (-1);
  1023.        }
  1024.     }
  1025.     /* Open source file and create target, overwriting if necessary. */
  1026.     dos_error_auto_fail=TRUE;
  1027.     if( (hsource = _open( source, O_BINARY | O_RDONLY )) == - 1 )
  1028.     return errno;
  1029.  
  1030.     htarget = _open( target, O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
  1031.                 S_IREAD | S_IWRITE );
  1032.     if( errno == EEXIST )
  1033.     {
  1034.     savedscreen=show_string( "Target exists. Overwrite ?", info_bg_color,info_text_color );
  1035.     _settextposition( 1, 1 );        /* prevent scroll-up from dos error */
  1036.     ch = getkey();
  1037.     restScrn(savedscreen);
  1038.     if (ch=='y' || ch=='Y')
  1039.         htarget = _open( target, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
  1040.                     S_IREAD | S_IWRITE );
  1041.     }
  1042.  
  1043.     if( htarget == -1 )
  1044.     {
  1045.     close( hsource );
  1046.     return errno;
  1047.     }
  1048.     dos_error_auto_fail=FALSE;
  1049.  
  1050.     fsize=filelength( hsource );
  1051.  
  1052.     /* first try to allocate memory with _halloc */
  1053.     count=0x8000;                        /* should be power of 2 */
  1054.     blocks=(unsigned int) (fsize/((long) count));
  1055.     if (fsize%((long) count)) blocks++; /* blocks needed */
  1056.     while (blocks && !(hbuf=_halloc((long) blocks, (size_t) count))) blocks--;   /* blocks available */
  1057.     if (blocks)
  1058.     {
  1059.     /* Read-write until there's nothing left. */
  1060.     while( !eof( hsource ) )
  1061.     {
  1062.         /* Read and write input. */
  1063.         first_count_size=0x8000;    /* save normal size of read */ 
  1064.         for (iTel_r=0;iTel_r<blocks;iTel_r++)
  1065.         {
  1066.         if( (last_count_size = (unsigned int) read( hsource, ((char __huge *) hbuf+(((long)iTel_r)*((long)count))), count )) == -1 )
  1067.         {
  1068.             _hfree(hbuf);
  1069.             close( hsource );
  1070.             close( htarget );
  1071.             return errno;
  1072.         }
  1073.         if (eof(hsource))
  1074.         {
  1075.              iTel_r++;     /* this is a tricky one ! */
  1076.              break;
  1077.         }
  1078.         }
  1079.         for (iTel_w=0;iTel_w<iTel_r;iTel_w++)
  1080.         {
  1081.         if (eof(hsource) && iTel_w==(iTel_r-1)) count=last_count_size; /* use size of last read */
  1082.         if( (count = (unsigned int) write( htarget, ((char __huge *) hbuf+(((long)iTel_w)*((long)first_count_size))), count )) == - 1 )
  1083.         {
  1084.             _hfree(hbuf);
  1085.             close( hsource );
  1086.             close( htarget );
  1087.             return errno;
  1088.         }
  1089.         }
  1090.     }
  1091.     /* Close files and release memory. */
  1092.     close( hsource );
  1093.     close( htarget );
  1094.     _hfree( hbuf );
  1095.     }
  1096.     else    /* _halloc failed, try near heap copy */
  1097.     {
  1098.        /* NEAR HEAP
  1099.     * Dynamically allocate a large file buffer. If there's not enough
  1100.     * memory for it, find the largest amount available on the near heap
  1101.     * and allocate that. This can't fail, no matter what the memory model.
  1102.     */
  1103.     count=0xFF00;
  1104.     if( (unsigned int) fsize < count )
  1105.     count = (unsigned int) fsize;
  1106.  
  1107.     buf = (char __near *)_nmalloc( (size_t) count );
  1108.     if ( !buf ) /*  NULL if failed */
  1109.     {
  1110.         count = _memmax();
  1111.         buf = (char __near *)_nmalloc( (size_t) count );
  1112.         if ( !buf ) /*  NULL if failed */
  1113.         {
  1114.         show_error("Cannot allocate near heap memory for copy");
  1115.         close( hsource );
  1116.         close( htarget );
  1117.         return ENOMEM;
  1118.         }
  1119.     }
  1120.  
  1121.     /* Read-write until there's nothing left. */
  1122.     while( !eof( hsource ) )
  1123.     {
  1124.         /* Read and write input. */
  1125.         if( (count = (unsigned) read( hsource, buf, count )) == -1 )
  1126.         {
  1127.         _nfree(buf);
  1128.         close( hsource );
  1129.         close( htarget );
  1130.         return errno;
  1131.         }
  1132.         if( (count = (unsigned) write( htarget, buf, count )) == - 1 )
  1133.         {
  1134.         _nfree(buf);
  1135.         close( hsource );
  1136.         close( htarget );
  1137.         return errno;
  1138.         }
  1139.     }
  1140.     /* Close files and release memory. */
  1141.     close( hsource );
  1142.     close( htarget );
  1143.     _nfree( buf );
  1144.     } /* end near heap */
  1145.  
  1146.     /* make date, time and attributes equal */
  1147.     copy_date_time_attrib( source, target );
  1148.  
  1149.     return 0;
  1150. }
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159. /**********************************************************************
  1160.  * Copies the date ,time and attributes of one file to another
  1161.  */
  1162. void copy_date_time_attrib( char *source, char *target )
  1163. {
  1164.     unsigned fdate, ftime, fattr;
  1165.     int hsource;
  1166.     int htarget;
  1167.  
  1168.     if( _dos_open( source, _O_RDONLY, &hsource ) )
  1169.     {
  1170.     show_error( "Source open error" );
  1171.     return;
  1172.     }
  1173.  
  1174.     /* Get time, date, and attribute of file. */
  1175.     _dos_getftime( hsource, &fdate, &ftime );
  1176.     _dos_close( hsource );
  1177.     _dos_getfileattr( source, &fattr );
  1178.  
  1179.     if( _dos_open( target, _O_RDONLY, &htarget ) )
  1180.     {
  1181.     show_error( "Target open error" );
  1182.     return;
  1183.     }
  1184.  
  1185.     /* Set time, date, and attribute of file. */
  1186.     _dos_setftime( htarget, fdate, ftime );
  1187.     _dos_close( htarget );
  1188.  
  1189.     /* always set archive bit on new file */
  1190.     fattr |= _A_ARCH;
  1191.     _dos_setfileattr( target, fattr );
  1192.  
  1193. }
  1194.  
  1195.  
  1196.  
  1197.  
  1198. char *soundex(char *instr, char *outstr)
  1199. {                   /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
  1200.     char *table = "01230120022455012623010202";
  1201.     register int count = 0;
  1202.  
  1203.     while(!isalpha(instr[0]) && instr[0])
  1204.         ++instr;
  1205.  
  1206.     if(!instr[0])     /* Hey!  Where'd the string go? */
  1207.         return(NULL);
  1208.  
  1209.     if(toupper(instr[0]) == 'P' && toupper(instr[1]) == 'H')
  1210.     {
  1211.         instr[0] = 'F';
  1212.         instr[1] = 'A';
  1213.     }
  1214.  
  1215.     /* I really don't trust this line in the original soundex code
  1216.     *outstr++ = toupper(*instr++);
  1217.     */
  1218.  
  1219.     /* gebruik maximaal 5 medeklinkers */
  1220.     while(*instr && count < 5)
  1221.     {
  1222.         if(isalpha(*instr) && *instr != *(instr-1))
  1223.         {
  1224.             *outstr = table[toupper(instr[0]) - 'A'];
  1225.             if(*outstr != '0')
  1226.             {
  1227.                 ++outstr;
  1228.                 ++count;
  1229.             }
  1230.         }
  1231.         ++instr;
  1232.     }
  1233.  
  1234.     *outstr = '\0';
  1235.     return(outstr);
  1236. }
  1237.  
  1238.  
  1239.  
  1240.  
  1241. int show_context(char *buffer, long buffersize, long offset, int length)
  1242. {
  1243.     char head[35];
  1244.     char scratch[50];
  1245.     char tail[35];
  1246.     char Reply;
  1247.     register size_t i;
  1248.     int surrounding;
  1249.     int mouse_row, mouse_col;
  1250.     int ulc_row, ulc_col, dummy;        /* upper left corner row and column of window */
  1251.  
  1252.     _gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy);    /* mouse coordinates are absolute! */
  1253.  
  1254.     strncpy(scratch,buffer+offset,length);
  1255.     scratch[length]='\0';
  1256.  
  1257.     surrounding=(64-length)/2;
  1258.  
  1259.     _setbkcolor( (long) info_bg_color );
  1260.     _settextcolor( (short) hidden_directory_color );
  1261.     _settextposition( 2, 3 );
  1262.  
  1263.     /* show leading characters */
  1264.     if (offset>surrounding)
  1265.     {
  1266.     strncpy(head,buffer+offset-surrounding,surrounding);
  1267.     head[surrounding]='\0';
  1268.     }
  1269.     else
  1270.     {
  1271.     strncpy(head,buffer,(size_t) offset);
  1272.     head[offset]='\0';
  1273.     }
  1274.     for (i=0;i<(size_t) strlen(head);i++)
  1275.     if (!isprint(head[i])) head[i]='\xFA';
  1276.     outtextm(head);
  1277.  
  1278.     /* show found string */
  1279.     for (i=0;i<(size_t) length;i++)
  1280.     if (!isprint(scratch[i])) scratch[i]='\xFA';
  1281.     _settextcolor( (short) info_text_color );
  1282.     outtextm(scratch);
  1283.  
  1284.     _settextcolor( (short) hidden_directory_color );
  1285.     /* show trailing characters */
  1286.     if ((buffersize-(offset+length))>surrounding)
  1287.     {
  1288.     strncpy(tail,buffer+offset+length,surrounding);
  1289.     tail[surrounding]='\0';
  1290.     }
  1291.     else
  1292.     {
  1293.     strncpy(tail,buffer+offset+length,(size_t) (buffersize-(offset+length)));
  1294.     tail[(buffersize-(offset+length))]='\0';
  1295.     }
  1296.     for (i=0;i<(size_t) strlen(tail);i++)
  1297.     if (!isprint(tail[i])) tail[i]='\xFA';
  1298.     outtextm(tail);
  1299.  
  1300.     _settextcolor( (short) info_text_color );
  1301.     /* blank out line */
  1302.     hide_mouse();
  1303.     for (i=strlen(scratch)+strlen(head)+strlen(tail);i<=63;i++) _outtext(" ");
  1304.     show_mouse();
  1305.     _settextposition( 8, 3);
  1306.     outtextm("Any key for next occurance");
  1307.  
  1308.     do
  1309.     {
  1310.         while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
  1311.         if (n_kbhit()) Reply = (char) getkey();
  1312.         else
  1313.         {
  1314.             Reply='\0';
  1315.         if (mouse_present)
  1316.         if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  1317.         {
  1318.             if ((mouse_col-ulc_col+1)>=3 && (mouse_col-ulc_col+1)<=28)
  1319.                Reply='A';     /* any key would do */
  1320.             if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66)
  1321.                Reply=0x1B;
  1322.         }
  1323.         }
  1324.     } while (!Reply);
  1325.  
  1326.     _settextposition( 8, 3);
  1327.     outtextm("                          ");
  1328.  
  1329.     _settextposition( 2, 3 );
  1330.     outtextm("                  WHERE IS FILE CONTAINING WHAT                 \n");
  1331.  
  1332.     if (Reply==0x1B)    return TRUE;
  1333.     else return FALSE;
  1334.  
  1335. }
  1336.  
  1337.  
  1338. int contains_nonprintable( char *string)
  1339. {
  1340.     register size_t tel;
  1341.  
  1342.     for (tel=0;tel<strlen(string);tel++)
  1343.     if (!isalnum(string[tel])) return TRUE;
  1344.     return FALSE;
  1345. }
  1346.