home *** CD-ROM | disk | FTP | other *** search
/ RBBS in a Box Volume 1 #2 / RBBS_vol1_no2.iso / add2 / fc_v003.exe / FC.C < prev    next >
Text File  |  1989-04-24  |  17KB  |  601 lines

  1. /***************************************************************************
  2.  *
  3.  *          Name:   FC-File Commentor
  4.  *      Synopsis:   FC filespec [switches]
  5.  *
  6.  *   Description:   Allows File Comments to be appended to standard 
  7.  *                  looking directory listings.  Meant to be a substitute
  8.  *                  for the DIR command.  Uses a linked list to store
  9.  *                  data for more efficient memory usage.
  10.  *
  11.  *      Revision:   0.003
  12.  *
  13.  *        Author:   Ronald C. Bieber
  14.  *
  15.  *      Compiler:   Turbo C Version 2.00
  16.  *
  17.  **************************************************************************/
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <dos.h>
  21. #include <dir.h>
  22. #include <io.h>
  23. #include <fcntl.h>
  24. #include <string.h>
  25. #include <alloc.h>
  26. #include <conio.h>
  27. #include "fc.h"
  28.  
  29. unsigned long sig = 0x6d5945b1;
  30.  
  31. int         olddrive,
  32.             drive,
  33.             fh,
  34.             no_found = 0,
  35.             flags = 0;          /* integer variable to hold command line
  36.                                    options.  Initialize to zero (no options
  37.                                    selected).       */ 
  38.  
  39. char        filespec[MAXPATH],
  40.             oldpath[MAXPATH],
  41.             comment_file[MAXPATH],
  42.             newpath[MAXPATH];
  43.  
  44. char        *months[12] = {                 /* 3 digit month names */
  45.                             "Jan",          /* per Jeff Darling 4-23 */
  46.                             "Feb",
  47.                             "Mar",
  48.                             "Apr",
  49.                             "May",
  50.                             "Jun",
  51.                             "Jul",
  52.                             "Aug",
  53.                             "Sep",
  54.                             "Oct",
  55.                             "Nov",
  56.                             "Dec"
  57.                         };
  58.  
  59. /************************ Function Declarations ***************************/
  60.  
  61. void        Usage();
  62. void        prtlong(long);
  63. void        format_time(unsigned short);
  64. void        splitfilespec(char *, char *, char *, int *);
  65. void        quit(int);
  66. char        *editline(char *, int);
  67. int         c_brk();
  68. void        pause();                            /* for pause mode */
  69.  
  70. FILELIST    *head;
  71.  
  72. main(argc, argv)
  73. int     argc;
  74. char    **argv;
  75. {
  76.     FILELIST    *next,
  77.                 *found;
  78.     char        *ptr,
  79.                 node[9],
  80.                 ext[4];
  81.     struct      ffblk   files;
  82.     int         done,
  83.                 linecount = 2,
  84.                 pos = 0,
  85.                 attr = FA_ARCH + FA_HIDDEN + FA_RDONLY + FA_SYSTEM + FA_DIREC;
  86.  
  87.     olddrive = drive = getdisk();           /* set default drive */
  88.     getcwd(oldpath, MAXPATH);
  89.  
  90.     printf("FC-File Commentor, Version %s, (C) Copr 1989, Ronald C. Bieber\n\n", VERSION);
  91.  
  92.     ctrlbrk(c_brk);
  93.  
  94.     argc = parms(argc, argv);
  95.  
  96.     if (argc < 1)
  97.         strcpy(filespec, "*.*");
  98.     else {
  99.         if (strcmp(*(++argv), "?") == 0)
  100.             Usage();
  101.         else
  102.             splitfilespec(*argv, newpath, filespec, &drive);
  103.     }
  104.  
  105.     sprintf(comment_file, "%scomments.fc", newpath);
  106.  
  107.     head = (FILELIST *) calloc(1, sizeof(FILELIST));
  108.  
  109.     setdisk(drive);
  110.  
  111.     if ((fh = open(comment_file, O_RDWR)) < 0)
  112.         fh = mk_info();
  113.     else
  114.         read_info(head, fh);
  115.  
  116.     if (flags & COMPRESS) {
  117.         close(fh);
  118.         fh = mk_info();
  119.         compress(head);
  120.         write_info(head, fh);
  121.         printf("COMMENTS.FC had been compressed.\n");
  122.         quit(FAILURE);
  123.     }
  124.  
  125.     done = findfirst(filespec, &files, attr);
  126.  
  127.     while(!done) {
  128.  
  129.         ptr = files.ff_name;
  130.         ext[0] = 0;
  131.         pos = 0;
  132.  
  133.         if (strchr(files.ff_name, '.') != NULL && strncmp(files.ff_name, ".", 1) != 0) {
  134.             while (*ptr != '.')
  135.                 node[pos++] = *(ptr++);
  136.             node[pos] = 0;
  137.             ptr++;
  138.             strcpy(ext, ptr);
  139.         } else
  140.             strcpy(node, files.ff_name);
  141.  
  142.         printf("%-8.8s %-3.3s ", strlwr(node), strlwr(ext));
  143.         if (!(files.ff_attrib & FA_DIREC))
  144.             prtlong(files.ff_fsize);
  145.         else
  146.             printf("     <DIR>");
  147.  
  148.         printf(" %2.2d-%3.3s-%d ",  files.ff_fdate &0x1f,
  149.                                     months[((files.ff_fdate>>5) &0x0f) - 1],
  150.                                     (files.ff_fdate>>9) + 80);
  151.         format_time(files.ff_ftime);
  152.  
  153.         if ((found = search(head, files.ff_name)) != NULL && !(flags & ADD))
  154.             if (flags & DELETE)
  155.                 node_delete(head, files.ff_name);
  156.             else
  157.                 printf("%s", found->fileinfo.comment);
  158.         
  159.         no_found++;
  160.  
  161.         if (flags & ADD) {
  162.             if ((next = search(head, files.ff_name)) == NULL)
  163.                 if ((next = mk_node(head)) == NULL) {
  164.                     printf("Internal Stack Error:  Not enough Memory\n");
  165.                     exit(1);
  166.                 }
  167.  
  168.             strcpy(next->fileinfo.filename, files.ff_name);
  169.             editline(next->fileinfo.comment, 38);
  170.  
  171.             if (strlen(next->fileinfo.comment) < 1) {
  172.                 flags |= DELETE;
  173.                 node_delete(head, next->fileinfo.filename);
  174.             }
  175.         }
  176.  
  177.         putchar('\n');
  178.  
  179.         if (!(flags & ADD) && (flags & PAUSE)) {  /* for /P - pause option */
  180.             linecount++;
  181.             if (linecount >= 24) {
  182.                 pause();
  183.                 linecount = 0;
  184.             }
  185.         }
  186.  
  187.         done = findnext(&files);
  188.     }
  189.  
  190.     if (flags & DELETE) {
  191.         close(fh);
  192.         fh = mk_info();
  193.     }
  194.  
  195.     quit(SUCCESS);
  196.  
  197. }
  198. /****************************************************************************
  199.  *
  200.  *          Name:   Usage
  201.  *      Synopsis:   void    Usage();
  202.  *
  203.  *   Description:   Prints usage format and command line options to
  204.  *                  standard output.
  205.  *
  206.  *       Returns:   Nothing.
  207.  *
  208.  ***************************************************************************/
  209. void Usage()
  210. {
  211.     printf("Usage:  FC [filespec] [switches] >outfile\n\n");
  212.     printf("Switches:\n");
  213.     printf("    /A          Add or edit existing file comments.\n");
  214.     printf("    /COMPRESS   Compress COMMENTS.FC file.\n");
  215.     printf("    /D          Delete file comments.\n");
  216.     printf("    /P          Pause Mode; press a key to continue.\n");
  217.     printf("\nFC was written by Ron Bieber.\n");
  218.     printf("Program design by Ron Bieber and Jeff Darling.\n\n");
  219.     printf("Courtesy of Polysyncronism BBS - (312) 358-5104\n");
  220.     exit(1);
  221. }
  222. /******************************************************************************
  223.  *
  224.  *          Name:   prtlong()
  225.  *      Synopsis:   void prtlong(number);
  226.  *                  long    number;
  227.  *
  228.  *   Description:   Prints out a long number in formatted form (X,XXX,XXX)
  229.  *
  230.  *****************************************************************************/
  231. void prtlong(number)
  232. long    number;
  233. {
  234.     char    newnum[17],
  235.             *ptr,
  236.             Number[17];
  237.  
  238.     int     count = 0,
  239.             loop,
  240.             length,
  241.             slength;
  242.  
  243.     if (number <= 999) {
  244.         printf("       %3lu",number);
  245.         return;
  246.     }
  247.  
  248.     ptr = newnum;
  249.     ptr = ltoa(number, ptr, 10);
  250.  
  251.     length = strlen(newnum);
  252.     slength = length;
  253.     *newnum = *strrev(newnum);
  254.     for (loop = 0;loop<length;loop++) {
  255.         if ( (loop == 3 && slength > 3) || (loop == 6 && slength > 6)) {
  256.             Number[count++] = 0x2C;
  257.             length++;
  258.         }
  259.         Number[count++] = newnum[loop];
  260.     }
  261.     strncpy(newnum,Number,length);
  262.     ptr = strrev(Number);
  263.     printf("%10s", ptr);
  264. }
  265.  
  266. /****************************************************************************
  267.  *
  268.  *          Name:   format_time
  269.  *      Synopsis:   void    format_time(ttime);
  270.  *                  unsigned short  ttime;      time stored in DOS format
  271.  *                  
  272.  *
  273.  *   Description:   Prints the time in HH:MM[ap] format.
  274.  *
  275.  *       Returns:   Nothing.
  276.  *
  277.  ***************************************************************************/
  278. void    format_time(ttime)
  279. unsigned short  ttime;
  280. {
  281.     int     hours,
  282.             minutes;
  283.             
  284.     char    *temp,
  285.             a_p = 'a';
  286.             
  287.  
  288.     hours = ((ttime & 0xF800) >> 11);
  289.     minutes = ((ttime & 0x07E0) >> 5);
  290.  
  291.     if (hours >= 12)
  292.         a_p = 'p';
  293.  
  294.     if (hours > 12)
  295.         hours -= 12;
  296.     else
  297.         if (hours == 0)
  298.             hours = 12;
  299.  
  300.     printf("%2d:%2.2d%c ", hours, minutes, a_p);
  301.  
  302. }
  303. /******************************************************************************
  304.  *
  305.  *          Name:   parms
  306.  *      Synopsis:   void parms(indx, ptr);
  307.  *                  int     indx;
  308.  *                  char    **ptr;
  309.  *
  310.  *   Description:   Retrieves program switches "Norton Style".
  311.  *                  (e.g.  Progname parm1 /switch1 /switch2 /switch3)
  312.  *
  313.  *       Returns:   Number of regular arguments (excluding switches)
  314.  *
  315.  *****************************************************************************/
  316. int parms(indx, ptr)
  317. int     indx;
  318. char    **ptr;
  319. {
  320.     char    c,
  321.             temp[3],
  322.             *tempptr;
  323.     int     count;
  324.  
  325.     count = indx - 1;
  326.     ptr += count;
  327.  
  328.     while (*(ptr[0]) == '/') {
  329.         c = *(++ptr[0]);
  330.         switch(toupper(c)) {
  331.             case 'A':   flags |= ADD;
  332.                         break;
  333.             case 'C':   if (stricmp(*ptr, "COMPRESS") == 0)
  334.                             flags |= COMPRESS;
  335.                         break;
  336.             case 'D':   flags |= DELETE;
  337.                         break;
  338.             case 'P':   flags |= PAUSE;
  339.                         break;
  340.         }
  341.         count--;
  342.         ptr--;
  343.     }
  344.     return(count);
  345.  
  346. }
  347. /****************************************************************************
  348.  *
  349.  *          Name:   editline
  350.  *      Synopsis:   char    *editline(line, l);
  351.  *                  char    *line;          line of text to edit
  352.  *                  int     l;              length of line
  353.  *
  354.  *   Description:   Allows user to edit line of text (entry description)
  355.  *
  356.  ***************************************************************************/
  357. char    *editline(line, l)
  358. char    *line;
  359. int     l;
  360. {
  361.  
  362.     char    c;
  363.     int     count = 0,
  364.             row,
  365.             col,
  366.             ocol,
  367.             orow;
  368.  
  369.     ocol = col = wherex();
  370.     orow = row = wherey();
  371.  
  372.     textcolor(BLACK);
  373.     textbackground(WHITE);
  374.  
  375.     for (c = 0; c < l; c++)
  376.         putch(' ');
  377.     
  378.     gotoxy(col, row);
  379.  
  380.     cprintf("%s", line);
  381.  
  382.     gotoxy(col, row);
  383.  
  384.     while ((c = getch()) != '\r')
  385.         switch(c) {
  386.  
  387.             case 0: if (kbhit()) {      /* extended key was pressed */
  388.                         c = getch();
  389.                         switch(c) {
  390.                             case 77:    if (count < l - 1) {
  391.                                             c = line[count++];  /* right arrow */
  392.                                             putch(c);
  393.                                             gotoxy(wherex(), row);
  394.                                         } else
  395.                                             BEEP();
  396.                                         continue;        
  397.  
  398.                             case 75:    if (count > 0) {
  399.                                             c = line[count--];  /* left arrow */
  400.                                             putch(c);
  401.                                             gotoxy(wherex() - 2, row);
  402.                                         } else
  403.                                             BEEP();
  404.                             default:    continue;
  405.                         }
  406.                     }
  407.  
  408.             case  8:                        /* backspace was pressed */
  409.                     if (count > 0) {
  410.                         col = wherex();
  411.                         row = wherey();
  412.                         gotoxy(col - 1, row);
  413.                         putch(' ');
  414.                         gotoxy(col - 1, row);
  415.                         line[--count] = 0;
  416.                     } else
  417.                         BEEP();
  418.                     break;
  419.  
  420.             case 27:                    /* ESCAPE key was pressed */ 
  421.                     normvideo();
  422.                     gotoxy(ocol, orow);
  423.                     clreol();
  424.                     printf("%s", line);
  425.                     putc('\n', stdout);
  426.                     quit(SUCCESS);
  427.                     break;
  428.  
  429.            default: if (count < l) {
  430.                         line[count] = c;
  431.                         count++;
  432.                     } else {
  433.                         col = wherex() - 1;
  434.                         row = wherey();
  435.                         if (count < l) 
  436.                             line[count] = c;
  437.                         gotoxy(col, row);
  438.                     }
  439.                     putch(c);
  440.  
  441.                     if (count > l - 1)        /* sound bell if at end of field */
  442.                         BEEP();
  443.  
  444.                     break;
  445.         }
  446.         
  447.     line[strlen(line)] = 0;
  448.  
  449.     normvideo();
  450.     gotoxy(ocol, orow);
  451.     clreol();
  452.     
  453.     printf("%s", line);
  454.  
  455.     return(line);
  456.  
  457. }
  458. /******************************************************************************
  459.  *
  460.  *          Name:   splitfilespec
  461.  *      Synopsis:   void splitfilespec(filespec, file, drive);
  462.  *                  char    *filespec,          filespec to split
  463.  *                          *file;              variable to hold filename.ext
  464.  *                  int     drive;              variable to store new drive #
  465.  *
  466.  *   Description:   parses filespec and returns the drive number and filename
  467.  *
  468.  *****************************************************************************/
  469. void splitfilespec(filespec, path, file, driveno)
  470. char    *filespec,
  471.         *path,
  472.         *file;
  473. int     *driveno;
  474. {
  475.     char    drive[MAXDRIVE],
  476.             dir[MAXDIR],
  477.             name[MAXFILE],
  478.             ext[MAXEXT],
  479.             temp[MAXPATH],
  480.             newspec[MAXPATH];
  481.  
  482.     struct  ffblk files;
  483.     int     status,
  484.             result;
  485.  
  486.     strupr(filespec);
  487.     status = fnsplit(filespec, drive, dir, name, ext);
  488.  
  489.     if (status & DRIVE)
  490.         *driveno = drive[0] - 65;
  491.     else
  492.         *driveno = getdisk();
  493.  
  494.     if (status & DIRECTORY) {
  495.         sprintf(path, "%s%s", drive, dir);
  496.     } else
  497.         path[0] = 0;
  498.  
  499.     if (status & FILENAME) {
  500.         if (strchr(name, '*') == NULL && strchr(name, '?') == NULL) {
  501.             sprintf(temp, "%s%s%s%s", drive, dir, name, ext);
  502.             result = findfirst(temp, &files, FA_ARCH + FA_HIDDEN + FA_RDONLY + FA_SYSTEM + FA_DIREC);
  503.             if (result == 0) {
  504.                 if (files.ff_attrib & FA_DIREC) {
  505.                     sprintf(temp, "%s%s%s\\", drive, dir, name);
  506.                     strcpy(path, temp);
  507.                     status ^= FILENAME;
  508.                     name[0] = 0;
  509.                     ext[0] = 0;
  510.                 }
  511.             }
  512.         }
  513.     }
  514.  
  515.     if (!(status & FILENAME))
  516.         strcpy(name, "*");
  517.  
  518.     if (!(status & EXTENSION) || strlen(ext) < 1)
  519.         strcpy(ext, ".*");
  520.  
  521.     sprintf(file, "%s%s%s", path, name, ext);
  522.     
  523. }
  524. /******************************************************************************
  525.  *
  526.  *          Name:   c_brk
  527.  *      Synopsis:   int cbrk(void);
  528.  *
  529.  *   Description:   Control Break interrupt handler
  530.  *
  531.  *****************************************************************************/
  532. int c_brk()
  533. {
  534.     setdisk(olddrive);
  535.     exit(3);
  536. }
  537. /****************************************************************************
  538.  *
  539.  *          Name:   quit
  540.  *      Synopsis:   void quit(status);
  541.  *                  int     status;         status of quit
  542.  *
  543.  *   Description:   Stops program.   If status is SUCCESS, print number
  544.  *                  found and disk free space. If status is FAILURE, just
  545.  *                  quit.
  546.  *
  547.  ***************************************************************************/
  548. void quit(status)
  549. int     status;
  550. {
  551.     long        size_of_comment_file = 0;
  552.     struct      dfree   dfree;
  553.  
  554.     write_info(head, fh);
  555.  
  556.     size_of_comment_file = filelength(fh);
  557.     close(fh);
  558.  
  559.     if (size_of_comment_file <= 8)
  560.         unlink(comment_file);
  561.  
  562.     setdisk(olddrive);
  563.     chdir(oldpath);
  564.  
  565.     if (status == SUCCESS) {
  566.         if (no_found) {
  567.             getdfree(drive + 1, &dfree);
  568.             printf("\n%d file(s)  ", no_found);
  569.             prtlong((long) (dfree.df_bsec * dfree.df_sclus) * dfree.df_avail);
  570.             printf(" bytes free\n");
  571.         } else
  572.             printf("No files found.\n");
  573.     }
  574.     exit(0);
  575. }
  576. /***************************************************************************
  577.  *
  578.  *          Name:   pause
  579.  *      Synopsis:   void    pause(void);
  580.  *
  581.  *   Description:   Displays 'Press a key to continue ...' message and
  582.  *                  waits for keypress.  Then clears the line and starts
  583.  *                  display where it left off.
  584.  *
  585.  ***************************************************************************/
  586. void pause()
  587. {
  588.     int     row = wherey(),
  589.             col = wherex();
  590.  
  591.     gotoxy(1, row);
  592.     clreol();
  593.     printf("Press a key to continue ... ");
  594.     getch();
  595.  
  596.     gotoxy(1, row);
  597.     clreol();
  598.     gotoxy(col, row);
  599.  
  600. }
  601.