home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 235_01 / ovfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-18  |  24.5 KB  |  763 lines

  1. /*  061  14-Feb-87  ovfile.c
  2.  
  3.         Copyright (c) 1987 by Blue Sky Software.  All rights reserved.
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <dos.h>
  8. #include <fcntl.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include "ov.h"
  12. #include "dosfile.h"
  13.  
  14. static int stowidx;
  15. static FILE_ENT *stowfp;
  16. static DRIVE_ENT *drvlst = NULL;
  17. static char *none_tagged = "There are NO tagged files.";
  18. static char *notitself = "You can't copy a file to itself!";
  19. static char *mustbedir = "You must enter a drive and/or directory name!";
  20.  
  21. extern WINDOW cw;
  22. extern int diridx;
  23. extern char **dirlst;
  24. extern FILE_ENT files[];
  25. extern char *nullname, *cantopen;
  26.  
  27. DRIVE_ENT *findrive(int);
  28. struct search_block *nxtfile();
  29. char far *largest_f(unsigned int, unsigned int *);
  30. char *strupr(), *strchr(), *dirplus(FILE_ENT *, char *);
  31. char *parsepath(char *, char *, char *, int, char **, char **);
  32. int free_f(char far *), stowfile(struct search_block *, char *);
  33. int readbuf(int,char far *,unsigned int), writebuf(int,char far *,unsigned int);
  34. int add2windows(char *, char *, FILE_ENT *), delfromwins(char *, char *);
  35.  
  36. /******************************************************************************
  37.  **                        G E T F I L E S                                   **
  38.  *****************************************************************************/
  39.  
  40. getfiles() {           /* get data for the files in the current dir */
  41.  
  42.    int firsttime;
  43.    char pathbuf[MAX_PATHLEN+6];
  44.    register struct search_block *sbp;
  45.  
  46.    cw.files_size = 0;                  /* no files yet */
  47.    firsttime = TRUE;                   /* tell nxtfile() its the first call */
  48.  
  49.    stowidx = 0;                        /* start storing at the begining */
  50.    stowfp = files;
  51.  
  52.    /* if showall mode is active, call scantree to get all files, otherwise
  53.       scan the current dir ourselves */
  54.  
  55.    if (cw.showall) {   /* scan the current disk? */
  56.  
  57.       *pathbuf = '\0';
  58.       strncat(pathbuf,cw.dirbuf,2);
  59.       scantree("\\",pathbuf,0x16,stowfile);    /* scan entire disk */
  60.  
  61.    } else        /* scan the current directory */
  62.  
  63.       while (stowidx < MAX_FILES && (sbp = nxtfile("*.*",0x16,&firsttime)))
  64.             stowfile(sbp,NULL);
  65.  
  66.    /* sort the file names if there are any, also set nfiles */
  67.  
  68.    if (cw.nfiles = stowidx)
  69.       sort_files(NULL);
  70.  
  71.    /* set current file pointer to the first file */
  72.  
  73.    cw.curidx = 0;
  74.  
  75.    /* set file counters */
  76.  
  77.    cw.num_files = cw.nfiles;           /* files in the dir */
  78.    cw.num_tagged = 0;                  /* no files tagged yet */
  79.    cw.tag_size = 0;
  80.  
  81. }
  82.  
  83.  
  84. /*****************************************************************************
  85.                              S T O W F I L E
  86.  *****************************************************************************/
  87.  
  88. static int
  89. stowfile(sbp,dirp)     /* store a file in files[] */
  90. register struct search_block *sbp;
  91. char *dirp;
  92. {
  93.    register int len;
  94.    static char *lastdir = NULL;
  95.    register FILE_ENT *fp = stowfp;     /* fast stow pointer */
  96.  
  97.    /* if dirp is not NULL, this call is defining which dir is being scanned,
  98.       add this dir name to the showall dir list - return NZ (keep going) if
  99.       dir name added okay, 0 (stop scanning) if can't add dir name - don't
  100.       incr diridx unless everything is okay.  The dir name passed will always
  101.       have a trailing \ which we don't really want - don't keep it unless
  102.       this happens to be the root dir (len == 3) */
  103.  
  104.    if (dirp) {
  105.       if (diridx < MAX_DIR) {
  106.          len = strlen(dirp);
  107.          dirlst[diridx++] = lastdir = Strndup(dirp,len > 3 ? len-1 : len);
  108.          return(1);
  109.       }
  110.       return(0);
  111.    }
  112.  
  113.    /* ignore . and .. entries.  If the file mask is defined, make
  114.       sure the file name matches.  Make sure the file attributes
  115.       match the selection attributes */
  116.  
  117.    if (stowidx >= MAX_FILES || *sbp->fn == '.' ||
  118.        (cw.selatrs & sbp->attrib) != sbp->attrib ||
  119.        (*cw.mask && (cw.maskcmp != match_name(sbp->fn,cw.mask))))
  120.  
  121.       return(1);       /* don't want this one, but keep looking */
  122.  
  123.    /* we want the file, fill in files[] entry */
  124.  
  125.    fp->size = sbp->size;
  126.    fp->flags = sbp->attrib & 0x3f;
  127.    fp->index = stowidx++;
  128.    fp->date = sbp->date;
  129.    fp->time = sbp->time;
  130.    strcpy(fp->name,sbp->fn);
  131.    fp->dirp = cw.showall ? lastdir : cw.dirbuf;   /* point to files dir str */
  132.    cw.files_size += fp->size;                     /* accumulate total size */
  133.  
  134.    stowfp++;                             /* update for next time */
  135.    return(1);                            /* keep looking */
  136. }
  137.  
  138.  
  139. /******************************************************************************
  140.  **                             I N F O                                      **
  141.  *****************************************************************************/
  142.  
  143. info() {               /* toggle the extended info display */
  144.  
  145.    cw.info_display ^= 1;               /* toggle info on/off */
  146.  
  147.    infocnt(cw.info_display ? 1 : -1);  /* one more or less info window */
  148.  
  149.    adjust_window();                    /* resize the window data */
  150.  
  151.    update_window(1);                   /* display files in new format */
  152. }
  153.  
  154.  
  155. /******************************************************************************
  156.                               R E N _ C U R
  157.  ******************************************************************************/
  158.  
  159. ren_cur() {            /* rename (or move) the current file */
  160.  
  161.    int rc;
  162.    register FILE_ENT *fp;
  163.    char *newname, fn[MAX_NAMELEN+1];
  164.    static char ptxt[] = "Enter new file name or directory name for ";
  165.    char *fnp, *target, *todir, *tofn, *dirp, pmsg[sizeof(ptxt)+MAX_NAMELEN+1];
  166.  
  167.    fp = &files[cw.curidx];
  168.  
  169.    strcpy(pmsg,ptxt);                          /* build prompt string */
  170.    strcat(pmsg,strcpy(fn,fp->name));
  171.  
  172.    newname = strupr(prompt("Rename current file",pmsg,NULL,0,MAX_REPLY));
  173.    if (strlen(newname) == 0)
  174.       return;
  175.  
  176.    /* figure out the full target name, the dir, and the fn */
  177.  
  178.    rc = isadir(dirp=fp->dirp,newname); /* need to know if this is a dir name */
  179.  
  180.    target = parsepath(dirp,fn,newname,rc,&todir,&tofn);
  181.  
  182.    fnp = fname(fp);                    /* from name */
  183.  
  184.    rc = rename(fnp,target);            /* rename/move it */
  185.  
  186.    if (rc == 0) {                      /* rename okay? */
  187.  
  188.       /* note: fn is a local array instead of a pointer to fp->name because
  189.          add2windows() may shift the entries in files[] around thereby making
  190.          fp->name point to the wrong file - same goes for local dirp */
  191.  
  192.       add2windows(todir,tofn,fp);      /* add to new window(s) */
  193.       delfromwins(dirp,fn);            /* del from old window(s) */
  194.  
  195.    } else              /* unable to rename */
  196.  
  197.       show_error(1,0,3,"Unable to rename ",fn,": ");
  198.  
  199.    free(target);               /* release temp strings */
  200.    free(todir);
  201.    free(tofn);
  202.    free(fnp);
  203. }
  204.  
  205.  
  206. /******************************************************************************
  207.                               R E N _ T A G
  208.  ******************************************************************************/
  209.  
  210. ren_tag() {            /* rename (move) all tagged files to another dir */
  211.  
  212.    int i, rc;
  213.    register FILE_ENT *fp;
  214.    char *newdir, *fnp, *target, *todir, *dirp, fn[MAX_NAMELEN+1];
  215.  
  216.    if (cw.num_tagged == 0)             /* are there any tagged files? */
  217.       show_error(0,14,1,none_tagged);
  218.  
  219.    newdir = strupr(prompt("Move tagged files","Enter new directory name",
  220.             NULL,0,MAX_REPLY));
  221.  
  222.    if (strlen(newdir) == 0)
  223.       return;
  224.  
  225.    /* the name given must be a directory name */
  226.  
  227.    if (!isadir(cw.dirbuf,newdir))
  228.       show_error(0,12,1,mustbedir);
  229.  
  230.    /* Okay, move the tagged files */
  231.  
  232.    for (i = 0, fp = files; i < cw.nfiles && !brkout(); i++, fp++)
  233.  
  234.       if (fp->flags & TAGGED) {                /* this file tagged? */
  235.  
  236.          /* figure out the target names */
  237.  
  238.          dirp = fp->dirp;
  239.          target = parsepath(dirp,strcpy(fn,fp->name),newdir,1,&todir,NULL);
  240.  
  241.          fnp = fname(fp);              /* from name */
  242.          rc = rename(fnp,target);      /* move the file */
  243.  
  244.          if (rc == 0) {                /* move okay? */
  245.  
  246.             /* note: fn is a local array instead of a pointer to fp->name 'cause
  247.             add2windows() may shift the entries in files[] around thereby making
  248.             fp->name point to the wrong file */
  249.  
  250.             add2windows(todir,fn,fp);  /* add to new window(s) */
  251.             delfromwins(dirp,fn);      /* del from old window(s) */
  252.  
  253.          } else        /* error, unable to rename/move this file */
  254.  
  255.             show_error(1,0,3,"Unable to move ",fn,": ");
  256.  
  257.          free(target);                 /* must be tough on malloc & friends */
  258.          free(todir);
  259.          free(fnp);
  260.       }
  261. }
  262.  
  263.  
  264. /******************************************************************************
  265.  **                    E R A S E _ C U R R E N T                             **
  266.  *****************************************************************************/
  267.  
  268. erase_current() {      /* erase the current file */
  269.  
  270.    int ch;
  271.    char askmsg[30];
  272.    register FILE_ENT *fp;
  273.  
  274.    fp = &files[cw.curidx];
  275.  
  276.    strcpy(askmsg,"Erase ");
  277.    strcat(askmsg,fp->name);
  278.    strcat(askmsg," ? (y/N): ");
  279.    ch = ask(askmsg);
  280.  
  281.    if (yes(ch))
  282.       if (delfile(fp)) {                       /* delete the file */
  283.          delfromwins(fp->dirp,fp->name);       /* remove from windows */
  284.          getvolsiz(*cw.dirbuf,&cw.drivep->vol_size, /* vol stats have changed */
  285.             &cw.drivep->vol_free,&cw.drivep->clustersiz);
  286.       }
  287. }
  288.  
  289.  
  290. /*****************************************************************************
  291.                           E R A S E _ T A G G E D
  292.  *****************************************************************************/
  293.  
  294. erase_tagged() {       /* erase the tagged files */
  295.  
  296.    int ch;
  297.    register int i;
  298.    register FILE_ENT *fp;
  299.  
  300.    if (cw.num_tagged == 0)             /* are there any tagged files? */
  301.       show_error(0,14,1,none_tagged);
  302.  
  303.    ch = ask("Erase all tagged files? (y/N): ");
  304.    if (!yes(ch))
  305.       return;
  306.  
  307.    /* scan files[] looking for tagged files, when found, delete it */
  308.  
  309.    for (i = 0, fp = files; i < cw.nfiles && !brkout(); i++, fp++)
  310.       if (fp->flags & TAGGED) {
  311.          disp_msg(2,"Erasing ",fp->name);
  312.          if (delfile(fp))
  313.             delfromwins(fp->dirp,fp->name);
  314.       }
  315.  
  316.    clr_msg();                                  /* clear last erasing msg */
  317.  
  318.    getvolsiz(*cw.dirbuf,&cw.drivep->vol_size,  /* volume stats have changed */
  319.       &cw.drivep->vol_free,&cw.drivep->clustersiz);
  320. }
  321.  
  322.  
  323. /*****************************************************************************
  324.                                D E L F I L E
  325.  *****************************************************************************/
  326.  
  327. static int
  328. delfile(fp)            /* delete a file */
  329. register FILE_ENT *fp;
  330. {
  331.    int rc;
  332.    char *fn;
  333.  
  334.    rc = unlink(fn = fname(fp));        /* actually delete the file */
  335.    free(fn);
  336.  
  337.    if (rc)                             /* delete okay? */
  338.       show_error(1,0,3,"Unable to erase ",fp->name,": ");
  339.  
  340.    return(rc == 0);
  341. }
  342.  
  343.  
  344. /******************************************************************************
  345.  **                      C O P Y _ C U R R E N T                             **
  346.  *****************************************************************************/
  347.  
  348. copy_current() {       /* copy the current file */
  349.  
  350.    FILE_ENT tmpfent;
  351.    register FILE_ENT *fp;
  352.    register DRIVE_ENT *dp;
  353.    char *dest, *target, *todir, *tofn;
  354.  
  355.    dest = prompt("Copy current file","Copy to where? ",NULL,0,MAX_REPLY);
  356.  
  357.    if (strlen(dest)) {
  358.       fp = &files[cw.curidx];
  359.       target = parsepath(fp->dirp,fp->name,dest,isadir(fp->dirp,dest),&todir,&tofn);
  360.  
  361.       if (strcmp(fp->dirp,todir) != 0 || strcmp(fp->name,tofn) != 0) {
  362.          if (copyfile(fp,target)) {
  363.             tmpfent = *fp;                     /* new file will have */
  364.             tmpfent.flags |= ARCHIVE;          /* ARCHIVE attrib on  */
  365.             add2windows(todir,tofn,&tmpfent);
  366.             dp = findrive(*todir);
  367.             getvolsiz(dp->drive,&dp->vol_size,&dp->vol_free,&dp->clustersiz);
  368.          }
  369.       } else           /* attempt to copy file to itself! */
  370.  
  371.          show_error(0,0,1,notitself);
  372.  
  373.       free(target);
  374.       free(todir);
  375.       free(tofn);
  376.    }
  377. }
  378.  
  379.  
  380. /******************************************************************************
  381.  **                        C O P Y _ T A G G E D                             **
  382.  *****************************************************************************/
  383.  
  384. copy_tagged() {        /* mass copy of tagged files to somewhere */
  385.  
  386.    int i, ch;
  387.    FILE_ENT tmpfent;
  388.    register FILE_ENT *fp;
  389.    register DRIVE_ENT *dp;
  390.    char *dir, *target, *todir, *tofn;
  391.  
  392.    if (cw.num_tagged == 0)             /* are there any tagged files? */
  393.       show_error(0,14,1,none_tagged);
  394.  
  395.    dir = prompt("Copy tagged files","Copy to which dir? ",NULL,0,MAX_REPLY);
  396.    if (strlen(dir) == 0)
  397.       return;
  398.  
  399.    if (!isadir(cw.dirbuf,dir))         /* user must give a directory name */
  400.       show_error(0,12,1,mustbedir);
  401.  
  402.    /* Okay, copy the tagged files */
  403.  
  404.    for (fp = files, i = 0; i < cw.nfiles && !brkout(); i++, fp++)
  405.  
  406.       if (fp->flags & TAGGED) {
  407.          disp_msg(2,"Copying ",fp->name);
  408.  
  409.          target = parsepath(fp->dirp,fp->name,dir,1,&todir,&tofn);
  410.  
  411.          if (strcmp(fp->dirp,todir) != 0 || strcmp(fp->name,tofn) != 0) {
  412.  
  413.             if (copyfile(fp,target)) {
  414.                tmpfent = *fp;                     /* new file will have */
  415.                tmpfent.flags |= ARCHIVE;          /* ARCHIVE attrib on  */
  416.                add2windows(todir,tofn,&tmpfent);
  417.             }
  418.  
  419.          } else        /* trying to copy a file to itself */
  420.  
  421.             show_error(0,0,1,notitself);
  422.  
  423.          free(target);                 /* release temp strings */
  424.          free(todir);
  425.          free(tofn);
  426.       }
  427.  
  428.    clr_msg();                          /* clear last copying msg */
  429.  
  430.    /* update volume stats after copy */
  431.  
  432.    dp = strlen(dir) > 1 && dir[1] == ':' ? findrive(*dir) : cw.drivep;
  433.    getvolsiz(dp->drive,&dp->vol_size,&dp->vol_free,&dp->clustersiz);
  434.  
  435. }
  436.  
  437.  
  438. /******************************************************************************
  439.  **                         C O P Y F I L E                                  **
  440.  *****************************************************************************/
  441.  
  442. static int
  443. copyfile(fp,to)        /* copy from to */
  444. register FILE_ENT *fp;
  445. char *to;
  446. {
  447.    char *fn;
  448.    int fd, td, len;
  449.    char far *buffer;
  450.    unsigned int bufsiz;
  451.    static char *copyabort = " -- copy aborted";
  452.  
  453.    /* open the from file */
  454.  
  455.    fd = open(fn = fname(fp),O_RDONLY|O_BINARY);
  456.    free(fn);
  457.  
  458.    if (fd == -1) {
  459.       show_error(1,0,3,cantopen,fp->name,": ");
  460.       return(0);
  461.    }
  462.  
  463.    /* allocate space for the in memory copy buffer */
  464.  
  465.    buffer = largest_f(63*1024,&bufsiz);  /* get largest possible blk up 2 63k */
  466.    if (bufsiz < 1024) {                  /* give it up if < 1k available */
  467.       if (bufsiz)                        /* release the tiny buffer */
  468.          free_f(buffer);
  469.       show_error(0,0,2,"No free memory to allocate copy buffer",copyabort);
  470.       return(0);
  471.    }
  472.  
  473.    /* open the output file */
  474.  
  475.    if ((td = open(to,O_CREAT|O_BINARY|O_TRUNC|O_RDWR,S_IWRITE)) == -1) {
  476.       free_f(buffer);
  477.       show_error(1,0,3,cantopen,to,": ");
  478.       return(0);
  479.    }
  480.  
  481.    /* copy the file, a buffer at a time */
  482.  
  483.    while (len = readbuf(fd,buffer,bufsiz))
  484.       if (writebuf(td,buffer,len) == -1) {
  485.          free_f(buffer);
  486.          show_error(1,0,3,"Error writting to ",to,": ");
  487.          return(0);
  488.       }
  489.  
  490.    setftime(td,fp->date,fp->time);     /* set the to file time = from file */
  491.  
  492.    close(fd);                          /* files copied, close files */
  493.    close(td);
  494.    free_f(buffer);                     /*   and release copy buffer */
  495.  
  496.    /* give the new file the same attributes as the old, but add ARCHIVE */
  497.  
  498.    setattrib(to,(fp->flags & (ARCHIVE | SYSTEM | HIDDEN | RDONLY)) | ARCHIVE);
  499.  
  500.    return(1);          /* tell caller we think we worked */
  501. }
  502.  
  503.  
  504. /******************************************************************************
  505.                                 L O G I N
  506.  *****************************************************************************/
  507.  
  508.  
  509. login() {              /* login to another directory */
  510.  
  511.    char *new_dir, *todir;
  512.  
  513.    new_dir = prompt("","Login to which drive/directory? ",NULL,0,MAX_REPLY);
  514.  
  515.    /* if they give a relative dir spec and showall is in effect, we want
  516.       the relative dir spec to be relative to the current file's dir, not
  517.       the current dir */
  518.  
  519.    if (strlen(todir = new_dir)) {
  520.       if (cw.showall && cw.curidx < cw.nfiles)
  521.          parsepath(files[cw.curidx].dirp,"",new_dir,1,&todir,NULL);
  522.  
  523.       switch_dir(todir);
  524.  
  525.       if (todir != new_dir)            /* free mem if parsepath called */
  526.          free(todir);
  527.    }
  528. }
  529.  
  530.  
  531. /******************************************************************************
  532.  **                       S W I T C H _ D I R                                **
  533.  *****************************************************************************/
  534.  
  535. switch_dir(dir)        /* change the current directory */
  536. char *dir;
  537. {
  538.    int rc;
  539.    register DRIVE_ENT *dp;
  540.  
  541.    if ((rc = change_dir(dir)) == 0) {  /* dir switched okay? */
  542.  
  543.       if (cw.showall)                  /* turn off showall mode if it was */
  544.          showoff();                    /*   in effect in this window */
  545.  
  546.       getcwd(cw.dirbuf,MAX_PATHLEN);   /* get the current dir name */
  547.       initdrive(*cw.dirbuf);           /* (re)init DRIVE_ENT for this drive */
  548.       getfiles();                      /* load the files[] structure */
  549.       adjust_window();                 /* resize window data */
  550.       update_header();                 /* update the header  */
  551.       update_window(1);                /* and the window data */
  552.  
  553.    } else {                            /* can't switch, tell user */
  554.  
  555.       show_error(1,0,3,"Can't change to ",dir,": ");
  556.    }
  557.    return(rc);
  558. }
  559.  
  560.  
  561. /*****************************************************************************
  562.                             I N I T D R I V E
  563.  *****************************************************************************/
  564.  
  565. initdrive(drive)       /* initialize DRIVE_ENT for 'drive' */
  566. int drive;
  567. {
  568.    register DRIVE_ENT *dp;
  569.  
  570.    dp = findrive(*cw.dirbuf);       /* get DRIVE_ENT address 4 drive */
  571.    cw.drivep = dp;                  /* keep address in window block */
  572.  
  573.    get_set_vol(dp->volbuf,NULL);            /* get the new volume name */
  574.    getvolsiz(*cw.dirbuf,&dp->vol_size,      /*  and the volume size stats */
  575.              &dp->vol_free,&dp->clustersiz);/*  incase they are different */
  576.  
  577. }
  578.  
  579.  
  580. /******************************************************************************
  581.                             F I N D R I V E
  582.  *****************************************************************************/
  583.  
  584. DRIVE_ENT *
  585. findrive(drive)        /* find or allocate a DRIVE_ENT for drive */
  586. int drive;
  587. {
  588.    register DRIVE_ENT *dp, *ldp = NULL;
  589.  
  590.    dp = drvlst;                        /* try to find the DRIVE_ENT in the */
  591.    while (dp != NULL) {                /*   linked list of DRIVE_ENTs */
  592.       if (dp->drive == drive)
  593.          break;
  594.       ldp = dp;
  595.       dp = dp->next;
  596.    }
  597.  
  598.    if (dp == NULL) {                   /* allocate a new DRIVE_ENT */
  599.       dp = (DRIVE_ENT *) Malloc(sizeof(DRIVE_ENT));
  600.       dp->next = NULL;
  601.       dp->drive = drive;
  602.       if (ldp)
  603.          ldp->next = dp;
  604.       else
  605.          drvlst = dp;
  606.    }
  607.  
  608.    return(dp);
  609. }
  610.  
  611.  
  612. /*****************************************************************************
  613.                                F I N D I R
  614.  *****************************************************************************/
  615.  
  616. char *
  617. findir(dir)    /* find a dirlst entry that matches dir */
  618. char *dir;
  619. {
  620.    register int i;
  621.    register char **dp;
  622.  
  623.    for (dp = dirlst, i = diridx; i; i--, dp++)
  624.       if (strcmp(dir,*dp) == 0)
  625.          return(*dp);
  626.  
  627.    return("");                 /* better never happen! */
  628. }
  629.  
  630.  
  631. /******************************************************************************
  632.  **                         S E T _ V O L                                    **
  633.  *****************************************************************************/
  634.  
  635. set_vol() {            /* set the volume label */
  636.  
  637.    char *label;
  638.  
  639.    label = prompt("Set volume label","Enter new volume label: ",NULL,0,11);
  640.    if (strlen(label) == 0)
  641.       return;
  642.  
  643.    get_set_vol(cw.drivep->volbuf,label);    /* one call to set it */
  644.    get_set_vol(cw.drivep->volbuf,NULL);     /* another to see what comes back */
  645.  
  646.    gotorc(VOL_ROW,1);                  /* display volume label */
  647.    out_str(cw.drivep->volbuf,11,' ');
  648. }
  649.  
  650.  
  651. /*****************************************************************************
  652.                           M A T C H _ N A M E
  653.  *****************************************************************************/
  654.  
  655. match_name(np,pp)      /* determine if file name matched pattern */
  656. register char *np, *pp;
  657. {
  658.    /* Why you might ask is this code like this, well..., I have plans to port
  659.       this code to a system that has file names up to 79 characters long, and
  660.       I thought this type of code would be easier to port than something that
  661.       knew MS-DOS names are 8+3 */
  662.  
  663.    while (*np) {
  664.       if (*np == *pp)                          /* name char match pattern? */
  665.          goto match;
  666.       else
  667.          if (*np == '.') {                     /* watch to switches to the */
  668.             while (*pp == '*' || *pp == '?')   /* extension, the pattern   */
  669.                pp++;                           /* must have one also */
  670.             if (*pp != '.')
  671.                return(0);                      /* no pattern ext, no match */
  672.             goto match;
  673.          } else
  674.             if (*pp == '*') {                  /* allow wildcards */
  675.                np++;                           /* NOTE: doesn't advance the */
  676.                continue;                       /*       pattern pointer */
  677.             } else
  678.                if (*pp == '?')
  679.                   goto match;
  680.                else
  681.                   return(0);                   /* don't match, not wild */
  682.    match:
  683.       np++;                                    /* chars match, advance */
  684.       pp++;
  685.    }
  686.  
  687.    /* the name string matched so far, make sure the pattern only has
  688.       wildcards left (if anything) */
  689.  
  690.    while (*pp)
  691.       if (*pp != '*' && *pp != '?' && *pp != '.')
  692.          return(0);
  693.       else
  694.         pp++;
  695.  
  696.    return(1);                          /* A MATCH! */
  697. }
  698.  
  699.  
  700. /*****************************************************************************
  701.                            P A C K F I L E S
  702.  *****************************************************************************/
  703.  
  704. packfiles() {          /* pack the files structure */
  705.  
  706.    FILE_ENT *endp;
  707.    register FILE_ENT *p, *q;
  708.  
  709.    p = q = files;
  710.    endp = &files[cw.nfiles];
  711.  
  712.    while (q < endp)
  713.       if (*p->name) {
  714.          if (p == q)
  715.             p = ++q;
  716.          else
  717.             p++;
  718.       } else
  719.          if (*q->name == '\0')
  720.             q++;
  721.          else {
  722.             *p++ = *q;
  723.             *q->name = '\0';
  724.             q++;
  725.          }
  726.  
  727.    cw.nfiles = p - files;              /* new # of files in files[] */
  728. }
  729.  
  730.  
  731. /*****************************************************************************
  732.                                 F N A M E
  733.  *****************************************************************************/
  734.  
  735. char * ALTCALL
  736. fname(fp)              /* return the address of a file name */
  737. register FILE_ENT *fp;
  738. {
  739.    return(dirplus(fp,fp->name));       /* maybe this routine is too simple */
  740. }
  741.  
  742. /*****************************************************************************
  743.                              D I R P L U S
  744.  *****************************************************************************/
  745.  
  746. char *
  747. dirplus(fp,pp)         /* return a string which is the files dir + whatever */
  748. register FILE_ENT *fp;
  749. char *pp;
  750. {
  751.    register char *dp;
  752.  
  753.    if (cw.showall) {
  754.       dp = (char *) Malloc(strlen(fp->dirp)+strlen(pp)+2);
  755.       strcpy(dp,fp->dirp);
  756.       if (dp[strlen(dp)-1] != '\\')
  757.          strcat(dp,"\\");
  758.       strcat(dp,pp);
  759.       return(dp);
  760.    } else
  761.       return(Strdup(pp));
  762. }
  763.