home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / mslang / fs25 / fs2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-27  |  52.4 KB  |  1,807 lines

  1.  /* FS2.C
  2.  * whereis functions, remove dir functions
  3.  * MSC8 (VC++ 1.5)
  4.  * FS 2.5
  5.  * 270594
  6.  * Copyright (C) M. van Breemen, 1992-1994, All rights reserved.
  7.  */
  8.  
  9. #include "FS.H"
  10.  
  11. /* Prototypes */
  12. void working( int mode );
  13. int edit(char *title, char *string, int length , char *legal_illegal, int legalmode);
  14. void show_pages(FILE *stream, long *pages, unsigned int last_page_nr );
  15. void show_pages_status_line(int tabwidth, int wrap,
  16.                             unsigned int page_nr, unsigned int last_page_nr,
  17.                             char *horizontal_position);
  18. int copy( char *oldname, char *newname );
  19. int whereis(char *searchstring, int *current_page, int *filenumber );
  20. void outtextm( char *string );
  21. void alert( void );
  22. void show_error( char *message );
  23. void show_message( char *message );
  24. void wait_sec( int milliseconds );
  25. void clear_left_button_queue( void );
  26. void clear_right_button_queue( void );
  27. int read_left_button_queue( int *row, int *col );
  28. int read_right_button_queue( int *row, int *col );
  29. void init_mouse( void );
  30. void hide_mouse( void );
  31. void show_mouse( void );
  32. int mouse_button_pressed( void );
  33. unsigned int n_kbhit( void );
  34. int getkey(void);
  35. void changecursor(int insmode);
  36. void setcursor(unsigned int shape);
  37. int editstring(int row, int col, char *s, char *legal_illegal, int legalmode, int maxlength);
  38. char __near *saveScrn(void);
  39. char __near *restScrn(char __near *saveArea);
  40. int valid_filename( char *newname);
  41. void shadebox( short r1, short c1, short r2, short c2 );
  42. void shadechar( int row, int col );
  43. int find_in_file( char *filename , char *string, int ignore_case, int use_soundex);
  44. int extract_directory( char *searchstring );
  45. char *set_working_drive_and_dir( char *full_filename );
  46. int find_name(char *fname, int *current_page, int *filenumber);
  47. void construct_search_path( char *linebuf );
  48. char *getpath( int drive, char *buffer, int maxlen );
  49. char __near *show_string(char *string, int bg_color, int text_color);
  50. void paint_box(char *string, int vis_width, int vis_height);
  51. void copy_date_time_attrib( char *source, char *target );
  52. char *soundex(char *instr, char *outstr);
  53. int show_context(char *buffer, long buffersize, long offset, int length);
  54. int contains_nonprintable( char *string);
  55. int show_file(char *filename);
  56. int old_show_file(char *filename);
  57. int TabExpand (char *to, char *from, int ntabsp, unsigned int max_length);
  58. int getdiskfree( int lastdrive, long *freebytes );
  59.  
  60. /* global variables */
  61.  
  62. extern int number_of_files;    /* number of files found */
  63.  
  64. extern int order_by;           /* NAME, DATE or SIZE */
  65. extern int order_type;         /* ASCENDING or DESCENDING */
  66.  
  67. extern short int screen_bg_color;
  68. extern short int file_color;
  69. extern short int hidden_file_color;
  70. extern short int directory_color;
  71. extern short int hidden_directory_color;
  72. extern short int volume_label_color;
  73. extern short int cursor_bg_color;
  74. extern short int info_bg_color;
  75. extern short int info_text_color;
  76. extern short int error_text_color;
  77. extern short int error_bg_color;
  78.  
  79. typedef struct find_t_small {
  80.                 char name [13];
  81.                 char attrib;
  82.                 unsigned long datetime_or_size;
  83.                 } FIND_T_SMALL;
  84.                           
  85. extern FIND_T_SMALL *find;      /* pointer to the file info structures */
  86. extern int mouse_present;       /* boolean is there a mouse ? */
  87. extern int mouse_row;   /* mouse position, NOT screen rows and columns */
  88. extern int mouse_col;
  89. extern int max_files;           /* maximal number of accessible files per directory or root, defaults to 456 */
  90. extern int dos_error;           /* set by error handler */
  91. extern int dos_retries;         /* set by error handler */
  92. extern int dos_error_auto_fail; /* read by error handler */
  93.  
  94.  
  95. /*---------------------------------------------------------------------------*/
  96. /*   FF Routines taken from FFF 3.4.5, a public domain program to search files
  97.  *      Author: Don A. Williams                                                                                  *
  98.  *              CompuServ -                                                                                              *
  99.  *              Genie     - DON-WILL                                                                             
  100.  *      Customized !!
  101. */
  102.  
  103.  
  104. #define U_ESC    1
  105. #define U_SELECT 2
  106. #define U_GOTO   3
  107. #define U_ERROR  4
  108.  
  109. #define FIND_FIRST(Name,Block,Attrib) _dos_findfirst(Name, Attrib, Block);
  110. #define FIND_NEXT(Block) _dos_findnext(Block);
  111. #define DIR_ENTRY find_t        /* Name of the directory entry structure        */
  112. #define D_ATTRIB attrib         /* Attribute field in directory entry           */
  113. #define D_NAME name             /* File name field in directory entry           */
  114.  
  115.  
  116. typedef struct QueEntry {
  117.               struct QueEntry *Next;
  118.               char  *Body;
  119.             } QUE_ENTRY;
  120.  
  121. typedef struct QueDef {
  122.             QUE_ENTRY *Head, *Current;
  123.             int        Count;
  124.               } QUE_DEF;
  125.  
  126. /* Function prototypes    */
  127.  
  128. int             fff( char *fpattern, char *sstring, int ignore_case, int use_soundex);
  129. void            InitQueue (QUE_DEF *Q);
  130. QUE_ENTRY       *Enque (QUE_DEF *Q, void *Body);
  131. int             WalkTree (QUE_DEF * Q, char *sstring , int ignore_case, int use_soundex);
  132. int             SearchQ (char *Str);
  133. int             Match (char *Str, char *Pat);
  134. static int      I_Match (char *Str, char *Pat);
  135. static int      S_Match (char *S, char *P, int Anchor);
  136. void            DeleteQueue( QUE_DEF PatQue );
  137.  
  138. void            clean_dir(char *path);
  139. void            do_dir(char *path);
  140.  
  141. /*----------------------------------------------------------------------*/
  142.  
  143. extern QUE_DEF  PatQue;
  144. extern char             T_Path[_MAX_PATH];                    /* Temporary directory path to search   */
  145. extern char             V_Path[_MAX_PATH];                    /* Selected file */
  146.  
  147. void DeleteQueue( QUE_DEF PatQue )
  148. {
  149.     QUE_ENTRY *t, *u;
  150.     for (t = PatQue.Head; t != NULL;)
  151.     {
  152.     u = t->Next;
  153.     free(t->Body);
  154.     free(t);
  155.     t = u;
  156.     }
  157. }
  158.  
  159. int fff(char *fpattern, char *sstring, int ignore_case, int use_soundex)
  160. {
  161.     char            *p, *p2;
  162.     char            scratchfpattern[_MAX_PATH];
  163.     char            Path[_MAX_PATH];                              /* Current directory path to search             */
  164.     char            Devices[16] = "";
  165.     int             Result;
  166.     int             i;
  167.  
  168.     strcpy (scratchfpattern,fpattern);
  169.     InitQueue(&PatQue);
  170.     strcpy(Path, "C:\\");
  171.     Devices[0] = (char) (_getdrive() - 1 + 'A');
  172.     Devices[1] = '\0';
  173.  
  174. /*      Interpret fpattern tokens */
  175.     p = strtok( scratchfpattern, " " );     /* Find first token     */
  176.     while( p != NULL )
  177.     {
  178.  
  179.             if ((p2 = strchr(p, ':')) != NULL)  /* process devices */
  180.             {
  181.                 *p2 = '\0';
  182.                 strcpy(Devices, p);
  183.                 p2++;                  /* skip NULL */
  184.                 p = p2;                /* remove device */
  185.             }
  186.             if ((p2 = strrchr(p, '\\')) != NULL)  /* process path */
  187.             {
  188.                 *p2 = '\0';
  189.                 if (p[0]=='\\') strcpy(Path,"C:");
  190.                 else strcpy(Path,"C:\\");
  191.                 strcat(Path, p);
  192.                 if (Path[strlen(Path)-1]!='\\') strcat(Path,"\\");
  193.                 p2++;                         /* skip backslash */
  194.                 p = p2;                       /* remove path */
  195.             }
  196.             if (strlen(p))
  197.             {
  198.                   if (strlen(p)>12)
  199.                   {
  200.                      DeleteQueue( PatQue );
  201.                      return FAILURE;  /* illegal filename length, abort */
  202.                   }
  203.                   if (!Enque(&PatQue, strupr(p)))
  204.                   {
  205.                     DeleteQueue( PatQue );
  206.                     _settextposition( 8, 3 );
  207.                     outtextm( "Memory exhausted, search aborted");
  208.                     alert();
  209.                     wait_sec(1000);
  210.                     return FAILURE;
  211.                   }
  212.             }
  213.             p = strtok( NULL, " " );        /* Find next token             */
  214.     }
  215.  
  216. /* This does the work by walking the directory structure for each specified     */
  217. /* disk                                                                                                                                         */
  218.  
  219.     p = Devices;
  220.     while (*p != '\0') {
  221.         strcpy(T_Path, Path);
  222.         T_Path[0] = *p++;         /* set drive */
  223.         if (Result=WalkTree(&PatQue,sstring,ignore_case,use_soundex)) break;
  224.         }
  225.     if (!Result)
  226.     {
  227.               _settextposition( 6, 3 );
  228.               outtextm("No more matches");
  229.               hide_mouse();
  230.               for (i=15;i<=63;i++) _outtext(" ");
  231.               show_mouse();
  232.     }
  233.  
  234.     DeleteQueue( PatQue );
  235.     return (Result);
  236. }
  237.  
  238. /*----------------------------------------------------------------------*/
  239. /* WalkTree is a recursive routine that walks the directory structure   */
  240. /* specifed by the external T_Path.  It bypasses Volume IDs and builds  */
  241. /* a linked list queue of directories that is processed after all of    */
  242. /* the file entries have been processed.                                                                */
  243.  
  244. int WalkTree (QUE_DEF *Q, char *sstring, int ignore_case, int use_soundex)
  245. {
  246.     int         Status;
  247.     char        Reply;
  248.     QUE_DEF     Direc;
  249.     QUE_ENTRY   *t, *u;
  250.     char        *p;
  251.     struct DIR_ENTRY  DirBlk;           /* Directory Entry structure                    */
  252.     int         TotalFiles = 0;         /* Total files processed                        */
  253.     int         TotalMatch = 0;         /* Count of all files matched                   */
  254.     int operator_intervention=FALSE;
  255.     register int i;
  256.     int mouse_row, mouse_col;
  257.     int ulc_row, ulc_col, dummy;        /* upper left corner row and column of window */
  258.  
  259.     _gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy);    /* mouse coordinates are absolute! */
  260.     InitQueue(&Direc);
  261.     strcat(T_Path, "*.*");
  262.     
  263.     dos_error=0;
  264.     dos_retries=0;
  265.     dos_error_auto_fail=TRUE;
  266.     Status = FIND_FIRST(T_Path, &DirBlk, 0xFF);
  267.     if (dos_error) operator_intervention=U_ERROR;
  268.     dos_error=0;
  269.     dos_retries=0;
  270.     dos_error_auto_fail=FALSE;
  271.     
  272.     *(strrchr(T_Path, '\\') + 1) = '\0';
  273.     _settextposition( 6, 3 );
  274.     outtextm(T_Path);       /* show progress */
  275.     hide_mouse();
  276.     for (i=strlen(T_Path);i<=63;i++) _outtext(" ");
  277.     show_mouse();
  278.  
  279.     while (!Status && !operator_intervention)
  280.     {  /*1*/
  281.      if (n_kbhit() || mouse_button_pressed())  /* operator ESCapes */
  282.      {  /*2*/
  283.          if (n_kbhit()) Reply = (char) getkey();
  284.          else
  285.          {
  286.          if (mouse_present)
  287.          if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  288.          {
  289.              if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66) Reply=0x1B;
  290.              else Reply='\0';
  291.          }
  292.          }
  293.  
  294.          if (Reply == 0x1B)    /* confirm */
  295.          {
  296.          _settextposition( 8, 3 );
  297.          outtextm("Type ESC to stop search, other key to continue");
  298.          _settextposition( 1, 1 );
  299.          Reply = (char) getkey();
  300.          _settextposition( 8, 3 );
  301.          outtextm("                                              ");
  302.          if (Reply==0x1B) operator_intervention=U_ESC;
  303.          }
  304.      } /*2*/
  305.  
  306.      if (!operator_intervention)
  307.      {
  308.          if ((DirBlk.D_ATTRIB & _A_VOLID) != 0)  /* Bypass Volume Label */
  309.          {
  310.          Status = FIND_NEXT(&DirBlk);
  311.          continue;
  312.          }
  313.      }
  314.  
  315.      if (!operator_intervention)
  316.      {  /*3*/
  317.          if ((DirBlk.D_ATTRIB & _A_SUBDIR) != 0) /* Process subdirectory */
  318.          {
  319.          if (DirBlk.D_NAME[0] != '.')
  320.          {
  321.              if (!Enque(&Direc, DirBlk.D_NAME))
  322.              {
  323.              _settextposition( 8, 3 );
  324.              outtextm( "Memory exhausted, search aborted");
  325.              alert();
  326.              wait_sec(1000);
  327.              operator_intervention=FAILURE;
  328.              }
  329.          }
  330.          }
  331.          else
  332.          { /*C*/                            /* Process file entry */
  333.          ++TotalFiles;
  334.          if ( SearchQ(DirBlk.D_NAME) )
  335.          {  /*B*/
  336.              strcpy(V_Path, T_Path);
  337.              strcat(V_Path, DirBlk.D_NAME);
  338.              _settextposition( 6, 3 );
  339.              outtextm(V_Path); /* show filename match */
  340.              hide_mouse();
  341.              for (i=strlen(V_Path);i<=63;i++) _outtext(" ");
  342.              show_mouse();
  343.  
  344.              if (strlen(sstring) ? find_in_file(V_Path,sstring, ignore_case, use_soundex) : TRUE)
  345.              { /*A*/
  346.              ++TotalMatch;
  347.              _settextposition( 8, 3);
  348.              outtextm("Next, Select, Goto  ");
  349.              do
  350.              {
  351.                  while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
  352.                  if (n_kbhit()) Reply = (char) getkey();
  353.                  else
  354.                  {
  355.                  Reply='\0';
  356.                  if (mouse_present)
  357.                  if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  358.                  {
  359.                      if ((mouse_col-ulc_col+1)>=3 && (mouse_col-ulc_col+1)<=6)
  360.                      Reply='N';
  361.                      if ((mouse_col-ulc_col+1)>=9 && (mouse_col-ulc_col+1)<=14)
  362.                      Reply='S';
  363.                      if ((mouse_col-ulc_col+1)>=17 && (mouse_col-ulc_col+1)<=20)
  364.                      Reply='G';
  365.                      if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66)
  366.                      Reply=0x1B;
  367.                  }
  368.                  }
  369.                  switch (Reply)
  370.                  {
  371.                  case 0x1B: _settextposition( 8, 3);
  372.                         outtextm("                    ");
  373.                         operator_intervention=U_ESC;
  374.                         break;
  375.                  case 'S':
  376.                  case 's': operator_intervention=U_SELECT;
  377.                        break;
  378.                  case 'G':
  379.                  case 'g': operator_intervention=U_GOTO;
  380.                        break;
  381.                  default: break;
  382.                  }
  383.              } while (Reply!='N' && Reply !='n' && !operator_intervention);
  384.              _settextposition( 8, 3);
  385.              outtextm("                    ");
  386.  
  387.              } /*A*/
  388.          } /*B*/
  389.          } /*C*/
  390.  
  391.  
  392.      } /*3*/
  393.      Status = FIND_NEXT(&DirBlk);
  394.     } /*1*/
  395.  
  396.  
  397.     /* Process any entries in the linked list of subdirectories */
  398.     if (TRUE)       /* was !operator_intervention */
  399.     {
  400.     p = strrchr(T_Path, '\\') + 1;  /* remove last filename */
  401.     for (t = Direc.Head; t != NULL;) /* was && !operator_intervention;) */
  402.     {
  403.         *p = '\0';
  404.         strcat(T_Path, t->Body);
  405.         strcat(T_Path, "\\");
  406.         if (!operator_intervention)   /* do not expand */
  407.              operator_intervention=WalkTree(Q,sstring,ignore_case, use_soundex);
  408.         u = t->Next;
  409.         free(t->Body);
  410.         free(t);
  411.         t = u;
  412.     }
  413.     }
  414.  
  415.     return (operator_intervention);
  416. }
  417.  
  418. /*----------------------------------------------------------------------*/
  419. /* SearchQ takes a file name as input and matches it against all of the */
  420. /* patterns in the linked list of patterns built from command line              */
  421. /* arguments.  The pattern list is an external.                                                 */
  422.  
  423. int SearchQ (char *Str)
  424. {
  425.     extern QUE_DEF  PatQue;
  426.     QUE_ENTRY      *t;
  427.     int             Result;
  428.  
  429.     for (t = PatQue.Head; t != NULL; t = t->Next) {
  430.         Result = Match(Str, t->Body);
  431.         if (Result != 0) return(Result);
  432.         }
  433.     return (0);
  434. }
  435.  
  436.  
  437.  
  438.  
  439. /****************************************************************************
  440.  *  InitQueue initializes a queue for use by the other queue functions.
  441.  ***************************************************************************/
  442.  
  443. void InitQueue (QUE_DEF *Q)
  444. {
  445.     Q->Head = Q->Current = NULL;
  446.     Q->Count = 0;
  447. }
  448.  
  449. /****************************************************************************
  450.  *  Enque  creates a queue entry linked to the other entries in FIFO order
  451.  *  and puts the string passed into the queue entry.  It returns a pointer
  452.  *  to the entry created [NULL if there is not enough memory for the entry.
  453.  ***************************************************************************/
  454.  
  455. QUE_ENTRY *Enque (QUE_DEF *Q, void *Body)
  456. {
  457.     QUE_ENTRY *p;
  458.     if ((p = malloc(sizeof(QUE_ENTRY))) == NULL ) return(NULL);
  459.     p->Next = NULL;
  460.     if ((p->Body = malloc(strlen(Body) + 1)) == NULL) return(NULL);
  461.     strcpy(p->Body, Body);
  462.     if (Q->Head == NULL) Q->Head = p;
  463.     else Q->Current->Next = p;
  464.     Q->Current = p;
  465.     ++Q->Count;
  466.     return(p);
  467. }
  468.  
  469.  
  470.  
  471. int Match (char *Str, char *Pat)
  472. {
  473.     char S_Name[_MAX_PATH], S_Ext[4];
  474.     char P_Name[_MAX_PATH], P_Ext[4];
  475.     char *p1;
  476.     strupr(Pat);
  477.     if ( (p1 = strrchr(Str, '.')) != NULL ) {
  478.         *p1 = '\0';
  479.         strcpy(S_Name, Str);
  480.         strcpy(S_Ext, p1+1);
  481.         *p1 = '.';
  482.         }
  483.     else {
  484.         strcpy(S_Name, Str);
  485.         S_Ext[0] = '\0';
  486.         }
  487.  
  488.     if ( (p1 = strchr(Pat, '.')) != NULL ) {
  489.         *p1 = '\0';
  490.         strcpy(P_Name, Pat);
  491.         strcpy(P_Ext, p1+1);
  492.         *p1 = '.';
  493.         }
  494.     else {
  495.         strcpy(P_Name, Pat);
  496.         strcpy(P_Ext, "*");
  497.         }
  498.  
  499.     if ( !I_Match(S_Name, P_Name) ) return(0);
  500.     if ( (P_Ext[0] == '\0') && (S_Ext[0] != '\0') ) return(0);
  501.     if ( !I_Match(S_Ext, P_Ext) ) return(0);
  502.     return(1);
  503. }
  504.  
  505.  
  506. static int I_Match (char *Str, char *Pat)
  507. {
  508.     char *p, *p1, *p2, Hold;
  509.     int t;
  510.     if ( (p1 = strchr(Pat, '*')) == NULL)
  511.         return( S_Match(Str, Pat, 1) );
  512.     if (Pat[0] != '*') {
  513.         *p1 = '\0';
  514.         t = S_Match(Str, Pat, 0);
  515.         *p1 = '*';
  516.         if (!t) return(0);
  517.         }
  518.     if (Pat[strlen(Pat)-1] != '*') {
  519.         p2 = strrchr(Pat, '*') + 1;
  520.         if (strlen(Str) < strlen(p2)) return(0);
  521.         if ( !S_Match(&Str[strlen(Str) - strlen(p2)], p2, 1) )
  522.             return(0);
  523.         }
  524.  
  525.     p = Str;
  526.     while ( (p2 = strchr(++p1, '*')) != NULL ) {
  527.         *p2 = '\0';
  528.         Hold = p1[0];
  529.         while ( (p = strchr(p, Hold)) != NULL ) {
  530.             if ( S_Match(p, p1, 0) ) break;
  531.             ++p;
  532.             }
  533.         if (p == NULL) return(0);
  534.         p += strlen(p1);
  535.         *p2 = '*';
  536.         p1 = p2;
  537.         }
  538.     return(1);
  539. }
  540.  
  541.  
  542. static int S_Match (char *S, char *P, int Anchor)
  543. {
  544.     while ( (*P != '\0') && (*S != '\0') ) {
  545.         if ( (*S == *P) || (*P == '?') ) {
  546.             S++;
  547.             P++;
  548.             }
  549.         else return(0);
  550.         }
  551.     if (*P != '\0') return(0);
  552.     if ( Anchor && (*S != '\0') ) return(0);
  553.     return(1);
  554. }
  555.  
  556. /***************************************************************************
  557.  Handles 'where is' screen
  558.  searchstring is the mask without device and path !
  559.  fpattern defaults to device + path + mask
  560. */
  561. int whereis(char *searchstring, int *current_page, int *filenumber)
  562. {
  563.     static char fpattern[_MAX_PATH]={'\0'};
  564.     static char org_sstring[50]={'\0'};
  565.     char sstring[50]={'\0'};
  566.  
  567.     char b[(9*69)+10]={               /* Buffer for string */
  568.         "╔══════════════════════════════════════════════════════════════════╗\n"
  569.         "║                   WHERE IS FILE CONTAINING WHAT                  ║\n"
  570.         "╠══════════════════════════════════════════════════════════════════╣\n"
  571.         "║ Filename pattern:                                                ║\n"
  572.         "║    Search string:                                                ║\n"
  573.         "║                                                                  ║\n"
  574.         "╠══════════════════════════════════════════════════════════════════╣\n"
  575.         "║                                                    ESC to cancel ║\n"
  576.         "╚══════════════════════════════════════════════════════════════════╝\n"
  577.  
  578.               };
  579.  
  580.     char __near *savedscreen;
  581.     int result,result2;
  582.     int i;
  583.     char *slash;
  584.     int ignore_case;
  585.     int use_soundex;
  586.  
  587.     construct_search_path(fpattern);
  588.  
  589.     if (!strlen(fpattern)) strcpy(fpattern,searchstring);
  590.     if (strlen(fpattern)>46) strcpy(fpattern,searchstring);
  591.     savedscreen=saveScrn();
  592.  
  593.  
  594.     _settextcolor( (short) info_text_color );
  595.     _setbkcolor( (long) info_bg_color );
  596.  
  597.     paint_box( b, 68, 9);
  598.  
  599.     _settextposition( 4, 21 );
  600.     outtextm(fpattern);
  601.     _settextposition( 5, 21 );
  602.     outtextm(org_sstring);
  603.     do
  604.     {
  605.  
  606.     _settextposition( 8, 3 );
  607.     outtextm("Enter a filename pattern, hit Return");
  608.     if (!(result=editstring(4, 21, fpattern, "+=[];|,<>/\"", ILLEGAL, 46))) break;
  609.     if (!strlen(fpattern)) strcpy(fpattern,"*.*");
  610.  
  611.     _settextposition( 6, 3 );
  612.     outtextm("Append /I to the string to ignore case, /S to use soundex");
  613.     _settextposition( 8, 3 );
  614.     outtextm("Enter string, empty to skip IN search, hit Return");
  615.     if (!(result=editstring(5, 21, org_sstring, "", ILLEGAL, 46))) break;
  616.     _settextposition( 8, 3 );
  617.         hide_mouse();
  618.     for (i=3;i<=52;i++) _outtext(" ");
  619.     _settextposition( 6, 3 );
  620.     for (i=3;i<=62;i++) _outtext(" ");
  621.         show_mouse();
  622.     strcpy(sstring,org_sstring);
  623.  
  624.     /* default ignore_case = FALSE */
  625.     ignore_case=FALSE;
  626.     if (slash=strstr(sstring,"/I"))
  627.     {
  628.         if (slash[2]=='\0')   /* sstring ENDS with /I option, otherwise part of sstring */
  629.         {
  630.            ignore_case=TRUE;
  631.            *(slash)='\0';
  632.         }
  633.     }
  634.     if (slash=strstr(sstring,"/i"))
  635.     {
  636.         if (slash[2]=='\0')   /* sstring ENDS with /I option, otherwise part of sstring */
  637.         {
  638.            ignore_case=TRUE;
  639.            *(slash)='\0';
  640.         }
  641.     }
  642.  
  643.     /* default use_soundex = FALSE */
  644.     use_soundex=FALSE;
  645.     if (slash=strstr(sstring,"/S"))
  646.     {
  647.         if (slash[2]=='\0')   /* sstring ENDS with /S option, otherwise part of sstring */
  648.         {
  649.            use_soundex=TRUE;
  650.            *(slash)='\0';
  651.         }
  652.     }
  653.     if (slash=strstr(sstring,"/s"))
  654.     {
  655.         if (slash[2]=='\0')   /* sstring ENDS with /S option, otherwise part of sstring */
  656.         {
  657.            use_soundex=TRUE;
  658.            *(slash)='\0';
  659.         }
  660.     }
  661.  
  662.     switch (result=fff(fpattern,sstring,ignore_case,use_soundex))     /* result in V_Path */
  663.     {
  664.           case U_ESC: _settextposition( 6, 3 );
  665.               outtextm("Last search canceled");
  666.               hide_mouse();
  667.               for (i=20;i<=63;i++) _outtext(" ");
  668.               show_mouse();
  669.               break;
  670.           case U_ERROR: _settextposition( 6, 3 );
  671.                 outtextm("A disk error occurred");
  672.                 hide_mouse();
  673.                 for (i=20;i<=63;i++) _outtext(" ");
  674.                 show_mouse();
  675.                 break;
  676.           case U_SELECT:
  677.           case U_GOTO: slash=set_working_drive_and_dir(V_Path); /* make drive & dir default */
  678.                                     /* and find filename */
  679.                if (!slash)
  680.                {
  681.                  result=FAILURE;
  682.                  break;
  683.                }
  684.  
  685.                /* first try original searchstring */
  686.                if (!Match(slash,searchstring))
  687.                {
  688.                  _settextposition( 8, 3 );
  689.                  outtextm( "Mask changed to *.*" );
  690.                  wait_sec(1000);
  691.                  strcpy(searchstring,"*.*");       /* this should match */
  692.                  extract_directory(searchstring);
  693.                  result2=find_name(slash, current_page, filenumber);
  694.                } else
  695.                  {
  696.                    extract_directory(searchstring);
  697.                    result2=find_name(slash, current_page, filenumber);
  698.                  }
  699.                if (result2==FAILURE)          /* find array might be full */
  700.                {
  701.                    _settextcolor( (short) info_text_color );
  702.                    _setbkcolor( (long) info_bg_color );
  703.                    _settextposition( 8, 3 );
  704.                    outtextm( "Mask changed to " );
  705.                    outtextm( slash );
  706.                    wait_sec(1000);
  707.                    strcpy(searchstring,slash);  /* this should work always */
  708.                    extract_directory(searchstring);
  709.                    result2=find_name(slash, current_page, filenumber);
  710.                }
  711.                if (result2==FAILURE) result=FAILURE;
  712.                break;
  713.           default: break;
  714.     }
  715.     } while (result!=U_SELECT && result!=U_GOTO && result!=FAILURE);
  716.  
  717.     _settextwindow( 3, 1, 23, 80 );
  718.     _setbkcolor( (long) screen_bg_color );
  719.     savedscreen=restScrn(savedscreen);
  720.     return result;
  721. }
  722.  
  723. /***************************************************************************
  724.  Find a string IN a file
  725. */
  726. int find_in_file( char *filename , char *string, int ignore_case, int use_soundex)
  727. {
  728.     char *buff;                 /* Pointer to data buffer */
  729.     int fn;                     /* file handle */
  730.     long fl;                    /* file length */
  731.     unsigned int count=0x7fff;  /* buffer size */
  732.     int  found;                 /* True if string found */
  733.     long rsize;                 /* Amount of data read into buffer */
  734.     register long offset;       /* Position where string code found */
  735.     char progress_char[]={ "/-\\|"};
  736.     static int progress_nr=0;
  737.     char progress_str[]={ "/\0" };
  738.     int Reply;
  739.     char scratch[50];
  740.     char snd1[50];
  741.     char snd2[50];
  742.  
  743.     if (ignore_case) strupr(string);
  744.  
  745.     if (use_soundex)
  746.     {
  747.      if (soundex(string,snd2)) strupr(snd2);
  748.      else
  749.      {
  750.          strcpy(snd2,"");
  751.          use_soundex=FALSE;
  752.      }
  753.     }
  754.  
  755.     if( (fn = open( filename, O_BINARY | O_RDONLY )) == - 1 )
  756.     {
  757.       show_error("Cannot open file");
  758.       return FALSE;
  759.     }
  760.     /* Get size of file */
  761.     fl = filelength(fn);
  762.     if( fl <  (long) count )
  763.     count = (unsigned int) fl;
  764.  
  765.     /* Dynamically allocate a large file buffer. If there's not enough
  766.      * memory for it, find the largest amount available
  767.      */
  768.     if( (buff = (char *)malloc( (size_t)count )) == NULL )
  769.     {
  770.     count = _memmax();
  771.     if( (buff = (char *)malloc( (size_t)count )) == NULL )
  772.     {
  773.          show_error("Cannot allocate memory for FIF");
  774.          close(fn);
  775.          return FALSE;
  776.     }
  777.     }
  778.  
  779.     found = FALSE;
  780.     while ( !eof(fn) && !found)
  781.     {
  782.       if( (rsize = (long) read( fn, buff, count )) == FAILURE )
  783.       {
  784.          show_error("Read error");
  785.          close(fn);
  786.          free(buff);
  787.          return FALSE;
  788.       }
  789.  
  790.       if (ignore_case)
  791.       {
  792.       for (offset=0L; offset < rsize; offset++)
  793.           if (isalpha((int) buff[offset]))
  794.          buff[offset]=(char) toupper((int) buff[offset]);
  795.       }
  796.  
  797.       for (offset=0L; offset <= rsize-strlen(string); offset++)
  798.       {
  799.      if (!(offset%5120L))   /* do checks after 5kb */
  800.      { /*B*/
  801.        if (fl > 5120L)      /* wheel */
  802.        {
  803.            if (progress_nr==3) progress_nr=0;
  804.            else progress_nr++;
  805.            progress_str[0]=progress_char[progress_nr];
  806.            _settextposition( 8, 3);
  807.            outtextm( progress_str );
  808.        }
  809.  
  810.        if (n_kbhit())
  811.        {  /*A*/
  812.          Reply=getkey();
  813.          if (Reply==0x1B)
  814.          {
  815.          _settextposition( 8, 3);
  816.          outtextm("Canceled, skipping this file");
  817.          wait_sec(500);
  818.          _settextposition( 8, 3);
  819.          outtextm("                            ");
  820.  
  821.          close(fn);
  822.          free(buff);
  823.          return FALSE;
  824.          }
  825.        }  /*A*/
  826.      } /*B*/
  827.  
  828.        if (use_soundex)
  829.        {
  830.       strncpy(scratch,&buff[offset],strlen(string));
  831.       scratch[strlen(string)]='\0';
  832.  
  833.       /* strings should be both alphanum ? */
  834.       if (contains_nonprintable(string) ||
  835.           (!contains_nonprintable(scratch) && !contains_nonprintable(string)))
  836.       {
  837.           if (soundex(scratch,snd1))
  838.           {
  839.         strupr(snd1);                           /* Ignore case */
  840.         if (!strcmp(snd1,snd2))                 /* here is the check */
  841.         {
  842.           found = TRUE;
  843.           if (show_context(buff,rsize,offset,strlen(string))) break;
  844.           else found = FALSE;
  845.         }
  846.           }
  847.       }
  848.        }
  849.        else
  850.        {
  851.      if (!strncmp(&buff[offset], string, strlen(string) ))   /* here is the check */
  852.      {
  853.        found = TRUE;
  854.        if (show_context(buff,rsize,offset,strlen(string))) break; /* escape from FOR loop */
  855.        else found = FALSE;
  856.      }
  857.        }
  858.       }
  859.  
  860.       if (!found && !eof(fn))    /* reposition back strlen(string)-1 to recover from split search string */
  861.       {
  862.     if (lseek (fn, 1L - ((long) (strlen(string))), SEEK_CUR)==FAILURE)
  863.     {
  864.          show_error("Seek error");
  865.          close(fn);
  866.          free(buff);
  867.          return FALSE;
  868.     }
  869.       }
  870.     }
  871.  
  872.     if (fl > 2048L) /* erase wheel */
  873.     {
  874.     _settextposition( 8, 3);
  875.     outtextm( " " );
  876.     }
  877.  
  878.     free(buff);
  879.     close(fn);
  880.  
  881.     if (!found) return FALSE;   /* String not found */
  882.     else return TRUE;     /* String found */
  883. }
  884.  
  885. /*
  886. **  Remove all files and subdirectories
  887. **  Slow but small code
  888. **  from a public domain demo by Bob Stout
  889. */
  890.  
  891. /*
  892. **  Clean all files from a directory
  893. */
  894.  
  895. void clean_dir(char *path)
  896. {
  897.       char rmpath[_MAX_PATH], *rmfile;
  898.       char scratch[_MAX_PATH];
  899.       struct find_t fbuf;
  900.       int key;
  901.       
  902.       strcpy(rmpath, path);
  903.       if ('\\' != (rmpath[strlen(rmpath) - 1]))
  904.         strcat(rmpath, "\\");
  905.       rmfile = &rmpath[strlen(rmpath)];
  906.       strcpy(rmfile, "*.*");
  907.       if (!_dos_findfirst(rmpath, _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY | _A_SYSTEM, &fbuf)) do
  908.       {
  909.             /* user aborts operation */
  910.         if (n_kbhit()) 
  911.         {        
  912.             key=getkey();
  913.                 if ((key & 0x00FF)==ESC) 
  914.                 {    
  915.                     show_message( "Aborted by user" );
  916.                     return;
  917.                 } 
  918.             }   
  919.       
  920.         strcpy(rmfile, fbuf.name);
  921.         if (remove(rmpath))
  922.         {
  923.          strcpy(scratch,"Cannot delete file");
  924.          strcat(scratch,rmpath);
  925.          show_error(scratch);
  926.         }
  927.       } while (!_dos_findnext(&fbuf));
  928. }
  929.  
  930. /*
  931. **  Process directories
  932.  * PLEASE PLEASE don't call with do_dir("..")
  933.  * it works fine (I know for sure): cleans up parent directory,
  934.  * which could be your complete harddisk
  935. */
  936.  
  937. void do_dir(char *path)
  938. {
  939.       char search[_MAX_PATH], new[_MAX_PATH];
  940.       char scratch[_MAX_PATH];
  941.       struct find_t ff;
  942.       int key;
  943.       
  944.       strcpy(search, path);
  945.       if ('\\' != (search[strlen(search) - 1]))
  946.         strcat(search, "\\");
  947.       strcat(search, "*.*");
  948.       if (!_dos_findfirst(search, 0xffff, &ff)) do
  949.       {           
  950.             /* user aborts operation */
  951.         if (n_kbhit()) 
  952.         {        
  953.             key=getkey();
  954.                 if ((key & 0x00FF)==ESC) 
  955.                 {    
  956.                     show_message( "Aborted by user" );
  957.                     return;
  958.                 } 
  959.             }   
  960.  
  961.         if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
  962.         {
  963.           strcat(strcat(strcpy(new, path), "\\"), ff.name);
  964.           do_dir(new);
  965.         }
  966.       } while (!_dos_findnext(&ff));
  967.       clean_dir(path);
  968.       if (rmdir(path))
  969.       {
  970.      strcpy(scratch,"Cannot delete directory ");
  971.      strcat(scratch,path);
  972.      show_error(scratch);
  973.       }
  974. }
  975.  
  976.  
  977. /*
  978.  * stripped version of FLOPTEST from William Zentmayer 06-JAN-92
  979.  * parameters:
  980.  * int drive = floppy drive letter to test A=0,B=1
  981.  * returns 0 if ready 
  982.  */
  983.  
  984. int floptest(int drv);
  985. void int13(union REGS *, union REGS *, struct SREGS *);
  986.  
  987. int floptest(int drv)
  988. {
  989.    union REGS InRegs, OutRegs;
  990.    struct SREGS SegRegs;
  991.    char sector_data[512];
  992.    char far *buffer=sector_data;
  993.  
  994.    InRegs.h.al=0x01;                             // number of sectors
  995.    InRegs.h.ch=0x00;                             // cylinder       
  996.    InRegs.h.cl=0x01;                             // sector              
  997.    InRegs.h.dh=0x00;                             // head                 
  998.    InRegs.h.dl=drv;                              // drive number 0=A,1=B,...
  999.    SegRegs.es =FP_SEG(buffer);                   // segment of buffer
  1000.    InRegs.x.bx=FP_OFF(buffer);                   // offset of buffer
  1001.  
  1002.    InRegs.h.ah=0x02;                             // read sector
  1003.    int13(&InRegs,&OutRegs,&SegRegs);             // int 13h func 02h
  1004.  
  1005.    return OutRegs.h.ah;
  1006. }
  1007.  
  1008. void int13(union REGS *InRegs, union REGS *OutRegs, struct SREGS *SegRegs)
  1009. {
  1010.    register int i;
  1011.    int holdreg=InRegs-> h.ah;
  1012.  
  1013.    for(i=0;i<3;i++)
  1014.        {
  1015.        InRegs-> h.ah=0x00;                       // reset controller
  1016.        int86(0x13,InRegs,OutRegs);               // int 13h func 00h
  1017.        if(OutRegs-> h.ah)                        // reset failed     
  1018.        break;                                // exit loop - error
  1019.  
  1020.        InRegs-> h.ah=holdreg;                    // called int 13h function
  1021.        int86x(0x13,InRegs,OutRegs,SegRegs);      // interrupt 13h
  1022.        if(OutRegs-> h.ah)                        // function failed
  1023.        continue;                             // retry
  1024.        }
  1025. }
  1026.  
  1027. /**********************************************************************
  1028.  * Copies one file to another (both specified by path). Dynamically
  1029.  * allocates memory for the file buffer. Prompts before overwriting
  1030.  * existing file. Returns 0 if successful, otherwise an error number.
  1031.  */
  1032. int copy( char *source, char *target )
  1033. {
  1034.     char __near *buf;
  1035.     char __huge *hbuf;
  1036.     int hsource, htarget, ch;
  1037.     long fsize;
  1038.     unsigned int count;
  1039.     unsigned int blocks;
  1040.     unsigned int last_count_size;
  1041.     unsigned int first_count_size;
  1042.     unsigned int iTel_r;
  1043.     unsigned int iTel_w;
  1044.     char full_source[_MAX_PATH];
  1045.     char full_target[_MAX_PATH];
  1046.     char __near *savedscreen;
  1047.     int sourcedrive;
  1048.     int targetdrive;
  1049.     long free_on_target;
  1050.     
  1051.     strupr(source);
  1052.     strupr(target);
  1053.     
  1054.     if (_fullpath( full_source, source, _MAX_PATH ) &&
  1055.     _fullpath( full_target, target, _MAX_PATH ))
  1056.     {
  1057.        if (!strcmp(full_source,full_target))   /* cyclic copy */
  1058.        {
  1059.       show_error("Cannot copy a file to itself");
  1060.       return (-1);
  1061.        }
  1062.     }
  1063.     
  1064.     /* determine drives to calculate free space */  
  1065.     sourcedrive=_getdrive();
  1066.     if (target[1]==':') targetdrive=(int) (target[0]-'A') + 1;
  1067.     else targetdrive=sourcedrive;
  1068.     if (getdiskfree(targetdrive,&free_on_target)==FAILURE) return (-1);
  1069.       
  1070.     /* Open source file and create target, overwriting if necessary. */
  1071.     dos_error_auto_fail=TRUE;
  1072.     if( (hsource = _open( source, O_BINARY | O_RDONLY )) == - 1 )
  1073.     return errno;
  1074.  
  1075.     htarget = _open( target, O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
  1076.                 S_IREAD | S_IWRITE );
  1077.     if( errno == EEXIST )
  1078.     {
  1079.     savedscreen=show_string( "Target exists. Overwrite ?", info_bg_color,info_text_color );
  1080.     _settextposition( 1, 1 );        /* prevent scroll-up from dos error */
  1081.     ch = getkey();
  1082.     restScrn(savedscreen);
  1083.     if (ch=='y' || ch=='Y')
  1084.         htarget = _open( target, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
  1085.                     S_IREAD | S_IWRITE );
  1086.     }
  1087.  
  1088.     if( htarget == -1 )
  1089.     {
  1090.     close( hsource );
  1091.     return errno;
  1092.     }
  1093.     dos_error_auto_fail=FALSE;
  1094.  
  1095.     fsize=filelength( hsource );
  1096.     
  1097.     /* check free diskspace */
  1098.     if (fsize > free_on_target)
  1099.     {
  1100.         show_error("Not enough disk space");
  1101.     close( hsource );
  1102.     close( htarget );
  1103.     /* cleanup empty target file header */
  1104.     unlink(target);
  1105.     return (-1);
  1106.     } 
  1107.      
  1108.     /* first try to allocate memory with _halloc */
  1109.     count=0x8000;                        /* should be power of 2 */
  1110.     blocks=(unsigned int) (fsize/((long) count));
  1111.     if (fsize%((long) count)) blocks++; /* blocks needed */
  1112.     while (blocks && !(hbuf=_halloc((long) blocks, (size_t) count))) blocks--;   /* blocks available */
  1113.     if (blocks)
  1114.     {
  1115.     /* Read-write until there's nothing left. */
  1116.     while( !eof( hsource ) )
  1117.     {
  1118.         /* Read and write input. */
  1119.         first_count_size=0x8000;    /* save normal size of read */ 
  1120.         for (iTel_r=0;iTel_r<blocks;iTel_r++)
  1121.         {
  1122.         if( (last_count_size = (unsigned int) read( hsource, ((char __huge *) hbuf+(((long)iTel_r)*((long)count))), count )) == -1 )
  1123.         {
  1124.             _hfree(hbuf);
  1125.             close( hsource );
  1126.             close( htarget );
  1127.             return errno;
  1128.         }
  1129.         if (eof(hsource))
  1130.         {
  1131.              iTel_r++;     /* this is a tricky one ! */
  1132.              break;
  1133.         }
  1134.         }
  1135.         for (iTel_w=0;iTel_w<iTel_r;iTel_w++)
  1136.         {
  1137.         if (eof(hsource) && iTel_w==(iTel_r-1)) count=last_count_size; /* use size of last read */
  1138.         if( (count = (unsigned int) write( htarget, ((char __huge *) hbuf+(((long)iTel_w)*((long)first_count_size))), count )) == - 1 )
  1139.         {
  1140.             _hfree(hbuf);
  1141.             close( hsource );
  1142.             close( htarget );
  1143.             return errno;
  1144.         }
  1145.         }
  1146.     }
  1147.     /* Close files and release memory. */
  1148.     close( hsource );
  1149.     close( htarget );
  1150.     _hfree( hbuf );
  1151.     }
  1152.     else    /* _halloc failed, try near heap copy */
  1153.     {
  1154.        /* NEAR HEAP
  1155.     * Dynamically allocate a large file buffer. If there's not enough
  1156.     * memory for it, find the largest amount available on the near heap
  1157.     * and allocate that. This can't fail, no matter what the memory model.
  1158.     */
  1159.     count=0xFF00;
  1160.     if( (unsigned int) fsize < count )
  1161.     count = (unsigned int) fsize;
  1162.  
  1163.     buf = (char __near *)_nmalloc( (size_t) count );
  1164.     if ( !buf ) /*  NULL if failed */
  1165.     {
  1166.         count = _memmax();
  1167.         buf = (char __near *)_nmalloc( (size_t) count );
  1168.         if ( !buf ) /*  NULL if failed */
  1169.         {
  1170.         show_error("Cannot allocate near heap memory for copy");
  1171.         close( hsource );
  1172.         close( htarget );
  1173.         return ENOMEM;
  1174.         }
  1175.     }
  1176.  
  1177.     /* Read-write until there's nothing left. */
  1178.     while( !eof( hsource ) )
  1179.     {
  1180.         /* Read and write input. */
  1181.         if( (count = (unsigned) read( hsource, buf, count )) == -1 )
  1182.         {
  1183.         _nfree(buf);
  1184.         close( hsource );
  1185.         close( htarget );
  1186.         return errno;
  1187.         }
  1188.         if( (count = (unsigned) write( htarget, buf, count )) == - 1 )
  1189.         {
  1190.         _nfree(buf);
  1191.         close( hsource );
  1192.         close( htarget );
  1193.         return errno;
  1194.         }
  1195.     }
  1196.     /* Close files and release memory. */
  1197.     close( hsource );
  1198.     close( htarget );
  1199.     _nfree( buf );
  1200.     } /* end near heap */
  1201.  
  1202.     /* make date, time and attributes equal */
  1203.     copy_date_time_attrib( source, target );
  1204.  
  1205.     return 0;
  1206. }
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215. /**********************************************************************
  1216.  * Copies the date ,time and attributes of one file to another
  1217.  */
  1218. void copy_date_time_attrib( char *source, char *target )
  1219. {
  1220.     unsigned fdate, ftime, fattr;
  1221.     int hsource;
  1222.     int htarget;
  1223.  
  1224.     if( _dos_open( source, _O_RDONLY, &hsource ) )
  1225.     {
  1226.     show_error( "Source open error" );
  1227.     return;
  1228.     }
  1229.  
  1230.     /* Get time, date, and attribute of file. */
  1231.     _dos_getftime( hsource, &fdate, &ftime );
  1232.     _dos_close( hsource );
  1233.     _dos_getfileattr( source, &fattr );
  1234.  
  1235.     if( _dos_open( target, _O_RDONLY, &htarget ) )
  1236.     {
  1237.     show_error( "Target open error" );
  1238.     return;
  1239.     }
  1240.  
  1241.     /* Set time, date, and attribute of file. */
  1242.     _dos_setftime( htarget, fdate, ftime );
  1243.     _dos_close( htarget );
  1244.  
  1245.     /* always set archive bit on new file */
  1246.     fattr |= _A_ARCH;
  1247.     _dos_setfileattr( target, fattr );
  1248.  
  1249. }
  1250.  
  1251.  
  1252.  
  1253.  
  1254. char *soundex(char *instr, char *outstr)
  1255. {                   /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
  1256.     char *table = "01230120022455012623010202";
  1257.     register int count = 0;
  1258.  
  1259.     while(!isalpha(instr[0]) && instr[0])
  1260.         ++instr;
  1261.  
  1262.     if(!instr[0])     /* Hey!  Where'd the string go? */
  1263.         return(NULL);
  1264.  
  1265.     if(toupper(instr[0]) == 'P' && toupper(instr[1]) == 'H')
  1266.     {
  1267.         instr[0] = 'F';
  1268.         instr[1] = 'A';
  1269.     }
  1270.  
  1271.     /* I really don't trust this line in the original soundex code
  1272.     *outstr++ = toupper(*instr++);
  1273.     */
  1274.  
  1275.     /* gebruik maximaal 5 medeklinkers */
  1276.     while(*instr && count < 5)
  1277.     {
  1278.         if(isalpha(*instr) && *instr != *(instr-1))
  1279.         {
  1280.             *outstr = table[toupper(instr[0]) - 'A'];
  1281.             if(*outstr != '0')
  1282.             {
  1283.                 ++outstr;
  1284.                 ++count;
  1285.             }
  1286.         }
  1287.         ++instr;
  1288.     }
  1289.  
  1290.     *outstr = '\0';
  1291.     return(outstr);
  1292. }
  1293.  
  1294.  
  1295.  
  1296.  
  1297. int show_context(char *buffer, long buffersize, long offset, int length)
  1298. {
  1299.     char head[35];
  1300.     char scratch[50];
  1301.     char tail[35];
  1302.     char Reply;
  1303.     register size_t i;
  1304.     int surrounding;
  1305.     int mouse_row, mouse_col;
  1306.     int ulc_row, ulc_col, dummy;        /* upper left corner row and column of window */
  1307.  
  1308.     _gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy);    /* mouse coordinates are absolute! */
  1309.  
  1310.     strncpy(scratch,buffer+offset,length);
  1311.     scratch[length]='\0';
  1312.  
  1313.     surrounding=(64-length)/2;
  1314.  
  1315.     _setbkcolor( (long) info_bg_color );
  1316.     _settextcolor( (short) hidden_directory_color );
  1317.     _settextposition( 2, 3 );
  1318.  
  1319.     /* show leading characters */
  1320.     if (offset>surrounding)
  1321.     {
  1322.     strncpy(head,buffer+offset-surrounding,surrounding);
  1323.     head[surrounding]='\0';
  1324.     }
  1325.     else
  1326.     {
  1327.     strncpy(head,buffer,(size_t) offset);
  1328.     head[offset]='\0';
  1329.     }
  1330.     for (i=0;i<(size_t) strlen(head);i++)
  1331.     if (!isprint(head[i])) head[i]='\xFA';
  1332.     outtextm(head);
  1333.  
  1334.     /* show found string */
  1335.     for (i=0;i<(size_t) length;i++)
  1336.     if (!isprint(scratch[i])) scratch[i]='\xFA';
  1337.     _settextcolor( (short) info_text_color );
  1338.     outtextm(scratch);
  1339.  
  1340.     _settextcolor( (short) hidden_directory_color );
  1341.     /* show trailing characters */
  1342.     if ((buffersize-(offset+length))>surrounding)
  1343.     {
  1344.     strncpy(tail,buffer+offset+length,surrounding);
  1345.     tail[surrounding]='\0';
  1346.     }
  1347.     else
  1348.     {
  1349.     strncpy(tail,buffer+offset+length,(size_t) (buffersize-(offset+length)));
  1350.     tail[(buffersize-(offset+length))]='\0';
  1351.     }
  1352.     for (i=0;i<(size_t) strlen(tail);i++)
  1353.     if (!isprint(tail[i])) tail[i]='\xFA';
  1354.     outtextm(tail);
  1355.  
  1356.     _settextcolor( (short) info_text_color );
  1357.     /* blank out line */
  1358.     hide_mouse();
  1359.     for (i=strlen(scratch)+strlen(head)+strlen(tail);i<=63;i++) _outtext(" ");
  1360.     show_mouse();
  1361.     _settextposition( 8, 3);
  1362.     outtextm("Any key for next occurance");
  1363.  
  1364.     do
  1365.     {
  1366.         while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
  1367.         if (n_kbhit()) Reply = (char) getkey();
  1368.         else
  1369.         {
  1370.             Reply='\0';
  1371.         if (mouse_present)
  1372.         if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
  1373.         {
  1374.             if ((mouse_col-ulc_col+1)>=3 && (mouse_col-ulc_col+1)<=28)
  1375.                Reply='A';     /* any key would do */
  1376.             if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66)
  1377.                Reply=0x1B;
  1378.         }
  1379.         }
  1380.     } while (!Reply);
  1381.  
  1382.     _settextposition( 8, 3);
  1383.     outtextm("                          ");
  1384.  
  1385.     _settextposition( 2, 3 );
  1386.     outtextm("                  WHERE IS FILE CONTAINING WHAT                 \n");
  1387.  
  1388.     if (Reply==0x1B)    return TRUE;
  1389.     else return FALSE;
  1390.  
  1391. }
  1392.  
  1393.  
  1394. int contains_nonprintable( char *string)
  1395. {
  1396.     register size_t tel;
  1397.  
  1398.     for (tel=0;tel<strlen(string);tel++)
  1399.     if (!isalnum(string[tel])) return TRUE;
  1400.     return FALSE;
  1401. }
  1402.  
  1403.  
  1404. /**************************************************************************
  1405.  old_style display file contents page by page on screen
  1406.  activated by shift-s
  1407. */
  1408. int old_show_file(char *filename)
  1409. {
  1410.     FILE *stream;
  1411.     int key;
  1412.     int line;
  1413.     char buf[82];
  1414.     int current_linewidth;
  1415.     int old_linewidth=0;
  1416.         
  1417.     dos_error_auto_fail=TRUE;
  1418.     if ((stream=fopen(filename,"rt")) == NULL )
  1419.     {
  1420.     show_error("Cannot show this file");
  1421.     return FAILURE;
  1422.     }
  1423.     dos_error_auto_fail=FALSE;
  1424.     _settextcolor( (short) file_color );
  1425.     _setbkcolor( (long) screen_bg_color );
  1426.     _clearscreen( _GWINDOW );
  1427.     _settextposition( 1, 1 );
  1428.     line=0;
  1429.     _wrapon( _GWRAPOFF );
  1430.                     
  1431.     /* read 80 chars (and add null terminator) */
  1432.     while (fgets( buf, 81, stream ))
  1433.     {
  1434.     line++; 
  1435.     
  1436.         /* a newline is not always present, so always strip newline character */        
  1437.         if (buf[strlen(buf)-1]=='\n')  buf[strlen(buf)-1]='\0';
  1438.  
  1439.     _outtext(buf);
  1440.     
  1441.       /* and add new line ourself */ 
  1442.       current_linewidth=strlen(buf);
  1443.       if (current_linewidth || (!current_linewidth && old_linewidth!=80)) _outtext("\n");
  1444.       /* save this linewidth */
  1445.       old_linewidth=current_linewidth;
  1446.       
  1447.     if (line==20)
  1448.     {
  1449.        line=0;
  1450.        _settextcolor( (short) info_text_color );
  1451.        _outtext("*** Press Esc to cancel, any other key to continue ***");
  1452.        _settextcolor( (short) file_color );
  1453.        if ((key=getkey())==ESC) break;
  1454.        _outtext("\n");
  1455.     }
  1456.     }
  1457.     if (key!=ESC)
  1458.     {
  1459.     _settextcolor( (short) info_text_color );
  1460.     _outtext("\n*** Press any key to continue ***");
  1461.     getkey();
  1462.     }
  1463.     fclose(stream);
  1464.     _settextcolor( (short) file_color );
  1465.     return SUCCESS;
  1466. }
  1467.  
  1468.  
  1469.  
  1470. /**************************************************************************
  1471.  scan the file and fill the pages array, then let show_pages() display 
  1472.  the file contents page by page on screen
  1473. */
  1474. int show_file(char *filename)
  1475. {
  1476.     FILE *stream;
  1477.     char buf[257];
  1478.     long *pages;
  1479.     unsigned int page_nr;
  1480.     long *temp_new_pages;
  1481.     unsigned int max_pages=PAGES_PER_MEMBLOCK;
  1482.     char *still_reading;
  1483.     register int line;
  1484.     int Reply;
  1485.          
  1486.     pages = (long *) malloc(sizeof(long)*max_pages*LINES_PER_PAGE);
  1487.     if (!pages) show_error("Cannot allocate memory for page buffer");
  1488.                  
  1489.     dos_error_auto_fail=TRUE;
  1490.     if ((stream=fopen(filename,"rt")) == NULL )
  1491.     {
  1492.     show_error("Cannot open this file");
  1493.     free(pages);
  1494.     return FAILURE;
  1495.     }
  1496.     
  1497.     dos_error_auto_fail=FALSE;
  1498.     
  1499.     page_nr=0;
  1500.     working(TRUE);
  1501.     do
  1502.     {
  1503.         if (n_kbhit()) Reply = (char) getkey();
  1504.         if (Reply==0X1B)
  1505.         {
  1506.             show_error("Partly read");
  1507.             break;
  1508.         }
  1509.         
  1510.         pages[page_nr++] = ftell(stream);
  1511.         
  1512.         for (line=0;line<LINES_PER_PAGE;line++) 
  1513.             /* read 255 chars (and add null terminator) */
  1514.             if (!(still_reading=fgets( buf, 256, stream ))) break;
  1515.                  
  1516.     if (page_nr==(max_pages-1)) 
  1517.     {     
  1518.         max_pages+=PAGES_PER_MEMBLOCK;
  1519.             temp_new_pages = (long *) realloc(pages,sizeof(long)*max_pages*LINES_PER_PAGE);
  1520.             if (!temp_new_pages)
  1521.             {
  1522.                 show_error("Cannot allocate enough memory for page buffer");
  1523.                 fclose(stream);
  1524.                 free(pages);
  1525.                 working(FALSE);
  1526.                 return FAILURE;
  1527.         } else pages = temp_new_pages;
  1528.     }
  1529.     } while (still_reading);
  1530.     working(FALSE); 
  1531.     
  1532.     /* start showing the pages array */ 
  1533.     show_pages(stream,pages,page_nr); 
  1534.     free(pages);
  1535.     fclose(stream);
  1536.        
  1537.     return SUCCESS;
  1538. }    
  1539.  
  1540.  
  1541. void show_pages(FILE *stream,long *pages,unsigned int last_page_nr)
  1542. {
  1543.     int key=0;
  1544.     unsigned int page_nr=1;
  1545.     register int line;
  1546.     char buf[257];
  1547.     char expanded[257];
  1548.     char *still_reading;
  1549.     int mouse_clicks;
  1550.     int linewidth;
  1551.     int page_linewidth;
  1552.     int show_from_column=0; /* start showing the left-most page */
  1553.     char window_position[3];
  1554.     int row,col;            /* dummy */
  1555.     
  1556.     int start_search=FALSE;
  1557.     char *found=(char *) NULL;
  1558.     char search_string[50]={"\0"};
  1559.     register int search_line;
  1560.     
  1561.     static int tabwidth=0;
  1562.     static int wrap=FALSE;
  1563.     
  1564.     if (wrap) _wrapon( _GWRAPON );
  1565.     else _wrapon( _GWRAPOFF );
  1566.         
  1567.     _settextcolor( (short) file_color );
  1568.     _setbkcolor( (long) screen_bg_color );
  1569.         
  1570.     
  1571.     do
  1572.     {
  1573.         if (start_search) /* scan the pages and lines for the string */
  1574.         {                 
  1575.             /* position file pointer */
  1576.             if (fseek(stream,pages[page_nr-1],SEEK_SET))
  1577.             {
  1578.                 show_error("Seek error");
  1579.                 return;
  1580.             }
  1581.             
  1582.             for ( ;page_nr<=last_page_nr;page_nr++) 
  1583.             {
  1584.                 /* check for user canceling the search */
  1585.             if (n_kbhit())
  1586.             {  
  1587.                 key=getkey();
  1588.                 if (key==0x1B) break;
  1589.                 }
  1590.             
  1591.                 /* update page number */
  1592.                 show_pages_status_line(tabwidth,wrap,page_nr,last_page_nr,"");
  1593.                                        
  1594.                 for (search_line=0;search_line<LINES_PER_PAGE;search_line++)
  1595.                 {    
  1596.                     /* read 255 chars (and add null terminator) */
  1597.                     if (!(still_reading=fgets( buf, 256, stream ))) break;
  1598.                     strlwr(buf);
  1599.                     if (found=strstr(buf,search_string)) break;
  1600.                 } 
  1601.                 if (found || !still_reading) break;
  1602.             } 
  1603.             if (!found) show_message("Not found");   
  1604.             start_search=FALSE;
  1605.             /* the page_nr is now correctly set, continue with normal mode */
  1606.         }
  1607.           
  1608.         /* show a page */                    
  1609.         /* clear window */
  1610.         _clearscreen( _GWINDOW );
  1611.         _settextposition( 1, 1 );
  1612.       
  1613.         /* position file pointer */
  1614.         if (fseek(stream,pages[page_nr-1],SEEK_SET))
  1615.         {
  1616.             show_error("Seek error");
  1617.             return;
  1618.         }
  1619.         /* show one page */ 
  1620.         page_linewidth=0;
  1621.         for (line=0;line<LINES_PER_PAGE;line++)
  1622.         {           
  1623.             /* read 255 chars (and add null terminator) */
  1624.             if (!(still_reading=fgets( buf, 256, stream ))) break;
  1625.             
  1626.             /* strip newline character */        
  1627.             if (buf[strlen(buf)-1]=='\n')  buf[strlen(buf)-1]='\0';
  1628.                     
  1629.             /* process old find action */
  1630.             /* the found pointer points to the correct string only */
  1631.             /* when tabwidth=0, but search_line is still correct */
  1632.             if (found && line==search_line)
  1633.             {
  1634.                 /* reset found */
  1635.                 found=(char *) NULL;
  1636.             _settextcolor( (short) info_text_color );
  1637.             }
  1638.             
  1639.             /* force to left-most block if in wrap mode */
  1640.             if (wrap) show_from_column=0;
  1641.             
  1642.           if (!tabwidth)
  1643.           {    
  1644.               linewidth=strlen(buf);
  1645.               if (linewidth>show_from_column) _outtext(buf+show_from_column);
  1646.           } 
  1647.           else
  1648.           {
  1649.               TabExpand (expanded, buf, tabwidth, (unsigned int) 255);
  1650.               linewidth=strlen(expanded);
  1651.               if (linewidth>show_from_column) _outtext(expanded+show_from_column);
  1652.           }
  1653.           /* skip new line if the line is spanning the screen in wrap mode */ 
  1654.           if (((linewidth+80) % 80) || !wrap || (wrap && !linewidth)) _outtext("\n");
  1655.           
  1656.           /* reset the color after flagging a found line */
  1657.           /* this is overhead on all pages but one but who cares */
  1658.             if (line==search_line) _settextcolor( (short) file_color );
  1659.             
  1660.             /* update page_linewidth */
  1661.             if (linewidth>page_linewidth) page_linewidth=linewidth;
  1662.         }
  1663.           
  1664.         /* determine starting column and set the <,<>,> symbol */
  1665.         strcpy(window_position,"");
  1666.         if (!wrap)
  1667.         {
  1668.             if (show_from_column) strcat(window_position,"<");
  1669.             if (page_linewidth>(show_from_column+80)) strcat(window_position,">");
  1670.         }
  1671.           
  1672.         /* show status line */
  1673.         show_pages_status_line(tabwidth,wrap,page_nr,last_page_nr,window_position);
  1674.                   
  1675.         /* wait for user intervention */
  1676.         while (!n_kbhit() && !mouse_button_pressed());
  1677.               
  1678.         if (mouse_present) /* act upon mouse event */
  1679.         {      
  1680.         mouse_clicks = read_left_button_queue(&row,&col);
  1681.         if (mouse_clicks) key=K_PGDN;
  1682.         mouse_clicks = read_right_button_queue(&row,&col);
  1683.         if (mouse_clicks) key=K_PGUP; 
  1684.         while (mouse_button_pressed()); /* button still down, do nothing */
  1685.     }
  1686.     
  1687.         if (n_kbhit()) /* act upon key event */          
  1688.         {
  1689.         if ((key=getkey())==ESC) break;
  1690.         if (key<256) key = tolower(key);
  1691.         if (key=='q') break;
  1692.         }
  1693.           
  1694.         /* handle both key and mouse event */  
  1695.     switch (key)
  1696.     {
  1697.         case 'f': if (edit("Find unbroken string, down, case ignored:",search_string,48,"",ILLEGAL))
  1698.                      if (strlen(search_string))
  1699.                      {
  1700.                          start_search=TRUE;
  1701.                          strlwr(search_string);
  1702.                      }
  1703.                       _settextcolor( (short) file_color );
  1704.                       break;
  1705.         case 'w': wrap ^=1;
  1706.                   if (wrap) _wrapon( _GWRAPON );
  1707.                       else _wrapon( _GWRAPOFF );
  1708.                       break;
  1709.         case '0': tabwidth=0;
  1710.                   break;
  1711.         case '1': tabwidth=1;
  1712.                   break;
  1713.         case '2': tabwidth=2;
  1714.                   break;
  1715.         case '3': tabwidth=3;
  1716.                   break;
  1717.         case '4': tabwidth=4;
  1718.                   break;
  1719.         case '5': tabwidth=5;
  1720.                   break;
  1721.         case '6': tabwidth=6;
  1722.                   break;
  1723.         case '7': tabwidth=7;
  1724.                   break;
  1725.         case '8': tabwidth=8;
  1726.                   break;
  1727.         case '9': tabwidth=9;
  1728.                   break; 
  1729.         case '<':          
  1730.             case K_CLE: if (show_from_column>=80) show_from_column -= 80;
  1731.                         break;
  1732.             case '>':            
  1733.             case K_CRI: if (page_linewidth>(show_from_column+80) && show_from_column<=160) show_from_column += 80;
  1734.                         break;                  
  1735.         case K_INS: strcpy(buf,"");
  1736.                     if (edit("Jump to page number",buf,10,"1234567890",LEGAL))
  1737.                         {
  1738.                              page_nr=atoi(buf);
  1739.                              if (page_nr<1) page_nr=1;
  1740.                              if (page_nr>last_page_nr) page_nr=last_page_nr;
  1741.                         }
  1742.                         _settextcolor( (short) file_color );
  1743.                         break;
  1744.             case 'u':            
  1745.             case K_CUP:            
  1746.         case K_PGUP: if (page_nr>1) page_nr--;
  1747.              break;
  1748.         case 't':         
  1749.         case K_HOME: page_nr=1;
  1750.              break;
  1751.         case 'b':         
  1752.         case K_END: page_nr=last_page_nr;
  1753.             break; 
  1754.             /* processed by default, but exclude them for future allocation */            
  1755.         case 'd':    
  1756.         case K_CDN:    
  1757.             case K_PGDN:        
  1758.         default: if (page_nr<last_page_nr) page_nr++;
  1759.              break;
  1760.     }
  1761.          
  1762.     } while (TRUE);
  1763. } /* end show_pages */
  1764.  
  1765.                    
  1766. void show_pages_status_line(int tabwidth, int wrap,
  1767.                             unsigned int page_nr, unsigned int last_page_nr,
  1768.                             char *horizontal_position)
  1769.     char buf[80];
  1770.     
  1771.     _settextposition( 21, 1 );
  1772.     _settextcolor( (short) info_text_color );
  1773.     sprintf(buf," ESC to cancel, Insert to jump, F to find.  Tab %d  Wrap %-3s  %-2s  Page: %u/%u",tabwidth,(wrap) ? "on" : "off",horizontal_position,page_nr,last_page_nr);
  1774.     _outtext(buf);
  1775.     _settextcolor( (short) file_color );
  1776.  
  1777.  
  1778. /* TabExpand - expand tabs to spaces
  1779.  * Original Author:     George Spofford 
  1780.  * Added overflow check
  1781.  */
  1782. int TabExpand (char *to, char *from, int ntabsp, unsigned int max_length)
  1783. {
  1784.   char *t;
  1785.   char *f;
  1786.   int   nsp; /* # of spaces to add upon '\t' */
  1787.  
  1788.   for (t = to, f = from; *f; ++f)
  1789.     if (*f == '\t') 
  1790.     {
  1791.       /* nsp = # of sp. 'til next tab-stop */
  1792.       nsp = ntabsp - (((int) (t-to)) % ntabsp);
  1793.       if ((strlen(t)+nsp) <= max_length)
  1794.       {
  1795.           memset (t, ' ', nsp);
  1796.           t += nsp;
  1797.       } else return FAILURE;   /* overflow */ 
  1798.     }
  1799.     else *t++ = *f;
  1800.     
  1801.   *t = '\0';     
  1802.   
  1803.   return SUCCESS;
  1804. }
  1805.