home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 235_02 / ovwin.c < prev    next >
Text File  |  1987-06-17  |  34KB  |  952 lines

  1. /*  034  14-Feb-87  ovwin.c
  2.  
  3.         Copyright (c) 1987 by Blue Sky Software.  All rights reserved.
  4. */
  5.  
  6. #include <setjmp.h>
  7. #include <dos.h>
  8. #include "ov.h"
  9.  
  10. #ifndef NULL
  11. #define NULL (0)
  12. #endif
  13.  
  14. #define V_bar (0xba)
  15. #define H_bar (0xcd)
  16.  
  17. int diridx = 0;                        /* # dir names when showall */
  18. char **dirlst = NULL;                  /* ptr to dir name ptrs when showall */
  19.  
  20. static int win_update;                         /* NZ if refresh_screen update */
  21. static unsigned char inwin = 0;                /* # active info windows */
  22. static unsigned char numwin = 1;               /* # active windows */
  23. static WINDOW *curwin = NULL, *winlis = NULL, *winp;
  24.  
  25. static char *tdir;                             /* target dir */
  26. static char *tname;                            /* target name */
  27. static FILE_ENT holdf;                         /* save file_ent */
  28.  
  29. static char *nomem = "Insufficient memory for another window, no window created!";
  30. static char *noaccess = "Unable to access specified directory: ";
  31.  
  32. extern WINDOW cw;
  33. extern int winupdate;
  34. extern FILE_ENT files[];
  35. extern unsigned dataseg;
  36. extern jmp_buf back_to_main;
  37. extern unsigned char anyshowall;
  38.  
  39. char far *malloc_f();
  40. int ALTCALL scanwindows(), ALTCALL win_switch();
  41. int addfile_ent(), delfile_ent(), refresh_window();
  42. char *strrchr(), *strchr(), *parsepath(), *findir();
  43. int ALTCALL wincpy(WINDOW *, WINDOW *), ALTCALL disp_empty_msg(int);
  44. int ALTCALL savefiles(char far *, int), ALTCALL restorefiles(char far *, int);
  45.  
  46. /******************************************************************************
  47.  **                         W I N _ O P E N                                  **
  48.  *****************************************************************************/
  49.  
  50. win_open() {           /* open another file name display window */
  51.  
  52.    register WINDOW *wp;
  53.  
  54.    /* make sure the current window is large enough to split */
  55.  
  56.    if (cw.wrows < 6)
  57.       show_error(0,10,1,"Current window is too small to open another");
  58.  
  59.    /* allocate memory for the new window structure */
  60.  
  61.    if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL)
  62.       show_error(0,11,1,nomem);
  63.  
  64.    wincpy(wp,&cw);             /* initialize new window via current window */
  65.  
  66.    /* allocate memory to store files[] data */
  67.  
  68.    if ((wp->save_files = malloc_f(MAX_FILES * sizeof(FILE_ENT))) == NULL) {
  69.       free((char *)wp);
  70.       show_error(0,12,1,nomem);
  71.    }
  72.  
  73.    /*  if there is only one window open so far, create the window structure
  74.        and files[] save area to store the current window stuff */
  75.  
  76.    if (numwin == 1) {
  77.       curwin = (WINDOW *) malloc(sizeof(WINDOW));
  78.       cw.save_files = malloc_f(MAX_FILES * sizeof(FILE_ENT));
  79.       if (curwin == NULL || cw.save_files == NULL) {
  80.          free((char *)wp);
  81.          if (curwin) {
  82.             free((char *)curwin);
  83.             curwin = NULL;
  84.          }
  85.          show_error(0,13,1,nomem);
  86.       }
  87.       cw.prev = cw.next = winlis = curwin;
  88.    }
  89.  
  90.    savefiles(cw.save_files,cw.nfiles); /* save current window's files[] data */
  91.  
  92.    /* link the new window just after the current window */
  93.  
  94.    wincpy(curwin,&cw);
  95.    wp->next = curwin->next;
  96.    wp->prev = curwin;
  97.    wp->prev->next = wp;
  98.    wp->next->prev = wp;
  99.    wincpy(&cw,curwin);
  100.  
  101.    /* adjust the current window and new window display sizes */
  102.  
  103.    wp->wrows = cw.wrows / 2;           /* new is at most 1/2 of current */
  104.    cw.wrows = cw.wrows - wp->wrows;    /* current keeps whats left */
  105.    wp->fwrow = cw.fwrow + cw.wrows;    /* new start at end of current */
  106.    cw.ndrows -= wp->wrows;             /* all new rows came from name disp */
  107.    wp->fnrow = wp->fwrow + 1;          /* one overhead row for dir name */
  108.    wp->ndrows = wp->wrows - 1;
  109.  
  110.    /* adjust the top window if it was the only one and it didn't already
  111.       have a header line */
  112.  
  113.    if (numwin == 1 && !cw.showall) {
  114.       cw.fnrow++;                         /* need a line to display window */
  115.       cw.ndrows--;                        /*   directory line */
  116.       insert_line(cw.fwrow+1,cw.wrows-1); /* scroll file info down a line */
  117.       disp_dirname();                     /* disp the dir name */
  118.    }
  119.  
  120.    /* adjust old window if current item is no longer visible and turn off
  121.       the file pointer in the old window */
  122.  
  123.    if (!on_screen(cw.curidx)) {        /* adjust/redisplay window */
  124.  
  125.       adjust_window();                 /*   if current item no longer */
  126.       update_window(0);                /*   displayed */
  127.  
  128.    } else              /* not redisplaying window, turn off highlighted ptr */
  129.  
  130.       if (cw.nfiles)                      /* turn off file ptr in old window */
  131.          fp_off(cw.curidx);
  132.       else                                /* or de-highlight empty dir msg */
  133.          disp_empty_msg(0);
  134.  
  135.    /* make the new window the current one */
  136.  
  137.    wincpy(curwin,&cw);                 /* save the old current one */
  138.    wincpy(&cw,wp);                     /* new one becomes current */
  139.    curwin = wp;                        /* remember who it is */
  140.  
  141.    numwin++;                           /* one more window than there was */
  142.  
  143.    if (cw.info_display)                /* if info display is active, there */
  144.       infocnt(1);                      /*   is now 1 more info window active */
  145.  
  146.    /* only one window can be in showall mode */
  147.  
  148.    if (cw.showall) {                   /* did the old window have showall? */
  149.       cw.showall = 0;                  /* yes, turn off on this one */
  150.       getfiles();                      /* reread current dir only */
  151.       update_header();                 /* display current dir header info */
  152.    }
  153.  
  154.    /* display the file data in the new window */
  155.  
  156.    adjust_window();
  157.    update_window(1);
  158.  
  159. }
  160.  
  161.  
  162. /******************************************************************************
  163.                             W I N _ C L O S E
  164.  *****************************************************************************/
  165.  
  166. win_close() {          /* close the current window */
  167.  
  168.    int fwrowadj;
  169.    register WINDOW *wp;
  170.  
  171.    if (numwin == 1)            /* nothing to do if only one window */
  172.       return;
  173.  
  174.    /* determine the window adjustment fudge factor, 1 extra line is available
  175.       if only one window will remain and that window is not showall */
  176.  
  177.    fwrowadj = (numwin == 2 && (!anyshowall || cw.showall)) ? 0 : 1;
  178.  
  179.    /* adjust the next or prior window to take up the closing windows space
  180.       on the screen.  Always pick the next window unless current is the
  181.       last one displyed */
  182.  
  183.    if ((wp = cw.next) != winlis) {             /* next = winlis if last */
  184.  
  185.       wp->fwrow = cw.fwrow;                    /* adj nxt to take over */
  186.  
  187.    } else              /* closing last window on screen */
  188.  
  189.       wp = cw.prev;                            /* prev is current to be */
  190.  
  191.    wp->wrows += cw.wrows;              /* it has this many more rows */
  192.    wp->fnrow = wp->fwrow + fwrowadj;   /*   name display rows */
  193.    wp->ndrows = wp->wrows - fwrowadj;
  194.  
  195.    cw.next->prev = cw.prev;            /* delink the current (closing) */
  196.    cw.prev->next = cw.next;            /* windows block from window list */
  197.  
  198.    if (curwin == winlis)               /* keep track of new top window if */
  199.       winlis = wp;                     /* old top is being closed */
  200.  
  201.    if (cw.showall)                     /* turn off showall mode if this */
  202.       showoff();                       /*   window had it on */
  203.  
  204.    if (cw.info_display)                /* one less info window if this wind */
  205.       infocnt(-1);                     /*   had info display active */
  206.  
  207.    free_f(cw.save_files);              /* free the cur win's  files[] area */
  208.    free((char *)curwin);               /* free the cur/old win's block */
  209.  
  210.    /* make the next (or prior) window current, restore its files */
  211.  
  212.    wincpy(&cw,curwin = wp);
  213.    restorefiles(cw.save_files,cw.nfiles);
  214.  
  215.    numwin--;                           /* one less window now */
  216.  
  217.    /* when there is only one window, don't keep the block and files[]
  218.       save area overhead */
  219.  
  220.    if (numwin == 1) {
  221.       free((char *)curwin);
  222.       free_f(cw.save_files);
  223.       curwin = winlis = NULL;
  224.       cw.save_files = (char far *) NULL;
  225.    }
  226.  
  227.    update_header();            /* make volume, dir, file, tag info correct */
  228.  
  229.    adjust_window();            /* adjust the display */
  230.    update_window(1);
  231.  
  232.    /* switch to the window's directory */
  233.  
  234.    if (change_dir(cw.dirbuf) != 0)
  235.       show_error(1,0,1,noaccess);
  236. }
  237.  
  238.  
  239. /******************************************************************************
  240.                             W I N _ E X P A N D
  241.  *****************************************************************************/
  242.  
  243. win_expand() {         /* expand current window to full screen */
  244.  
  245.    int i;
  246.    register WINDOW *wp, *np;
  247.  
  248.    if (numwin == 1)            /* nothing to do if only one window */
  249.       return;
  250.  
  251.    /* there will only be one window left, free up all memory blocks */
  252.  
  253.    for (i == numwin, wp = winlis; i; i--) {
  254.       np = wp->next;
  255.       free_f(wp->save_files);
  256.       free((char *)wp);
  257.       wp = np;
  258.    }
  259.  
  260.    numwin = 1;                 /* set counters/pointer to 1 window status */
  261.    curwin = winlis = NULL;
  262.  
  263.    if (anyshowall && !cw.showall)      /* turn off showall mode if it was */
  264.       showoff();                       /*   active in another window */
  265.  
  266.    infocnt(cw.info_display ? -(inwin-1) : -inwin); /* at most 1 info win left */
  267.  
  268.    /* adjust to full screen */
  269.  
  270.    cw.fwrow = cw.fnrow = FIRST_NROW + cw.info_display;
  271.    cw.wrows = cw.ndrows = NAME_ROWS - cw.info_display;
  272.  
  273.    if (cw.showall) {           /* showall always has a header */
  274.       cw.fnrow++;
  275.       cw.ndrows--;
  276.    }
  277.  
  278.    adjust_window();            /* redisplay the window with new size */
  279.    update_window(1);
  280.  
  281. }
  282.  
  283.  
  284. /******************************************************************************
  285.  **                         W I N _ N E X T                                  **
  286.  *****************************************************************************/
  287.  
  288. win_next() {           /* switch to the next window */
  289.  
  290.    if (numwin == 1)            /* nothing to do if only one window */
  291.       return;
  292.  
  293.    win_switch(curwin->next);   /* switch to next window */
  294. }
  295.  
  296.  
  297. /******************************************************************************
  298.                             W I N _ P R E V
  299.  *****************************************************************************/
  300.  
  301. win_prev() {           /* switch to the previous window */
  302.  
  303.    if (numwin == 1)            /* nothing to do if only one window */
  304.       return;
  305.  
  306.    win_switch(curwin->prev);   /* switch to previous window */
  307. }
  308.  
  309.  
  310. /******************************************************************************
  311.                             W I N _ S W I T C H
  312.  *****************************************************************************/
  313.  
  314. static int ALTCALL
  315. win_switch(newp)       /* switch to a new window */
  316. register WINDOW *newp;
  317. {
  318.    savefiles(cw.save_files,cw.nfiles); /* save current window's files[] data */
  319.  
  320.    if (cw.nfiles)                      /* deselect current item in widow */
  321.       fp_off(cw.curidx);
  322.    else                                /* or de-highlight empty dir msg */
  323.       disp_empty_msg(0);
  324.  
  325.    wincpy(curwin,&cw);                 /* switch to new window */
  326.    wincpy(&cw,curwin = newp);
  327.  
  328.    restorefiles(cw.save_files,cw.nfiles); /* get new windows files[] entries */
  329.  
  330.    if (cw.nfiles)                      /* select current item in new window */
  331.       fp_on(cw.curidx);
  332.    else                                /* or highlight empty dir msg */
  333.       disp_empty_msg(1);
  334.  
  335.    if (change_dir(cw.dirbuf) != 0)     /* switch to the window's directory */
  336.       show_error(1,0,1,noaccess);
  337.  
  338.    update_header();               /* make volume, dir, file, tag info correct */
  339. }
  340.  
  341.  
  342. /*****************************************************************************
  343.                           A D D 2 W I N D O W S
  344.  *****************************************************************************/
  345.  
  346. add2windows(todir,tofn,fp)     /* add file to any windows showing dest dir */
  347. FILE_ENT *fp;
  348. char *todir, *tofn;
  349. {
  350.    tdir = Strdup(todir);       /* save dir and fn in var's for addfile_ent */
  351.    tname = Strdup(tofn);
  352.  
  353.    holdf = *fp;                /* save file_ent 'cause files[] is changed */
  354.    holdf.flags &= ~TAGGED;     /* we don't want the tagged flag */
  355.  
  356.    scanwindows(addfile_ent);   /* add the file_ent to all matching windows */
  357.  
  358.    free(tdir);                 /* local strings alloc'd because callers tend */
  359.    free(tname);                /* to use strings in files[] which is swapped */
  360. }
  361.  
  362.  
  363. /*****************************************************************************
  364.                           D E L F R O M W I N S
  365.  *****************************************************************************/
  366.  
  367. delfromwins(fromdir,fromfn)  /* delete file from all windows showing dest dir */
  368. char *fromdir, *fromfn;
  369. {
  370.  
  371.    tdir = Strdup(fromdir);     /* save target dir and name in var's */
  372.    tname = Strdup(fromfn);     /*   for delfile_ent */
  373.  
  374.    scanwindows(delfile_ent);   /* delete the file_ent from all windows */
  375.  
  376.    free(tdir);                 /* local strings alloc'd because callers tend */
  377.    free(tname);                /* to use strings in files[] which is swapped */
  378. }
  379.  
  380.  
  381. /****************************************************************************
  382.                           A D D F I L E _ E N T
  383.  ****************************************************************************/
  384.  
  385. static int
  386. addfile_ent() {        /* add a FILE_ENT to target windows */
  387.  
  388.    register int i;
  389.    register FILE_ENT *tfp;
  390.  
  391.    /* if the current window displays the target dir or the target drive
  392.       in showall mode, add the file ent to it */
  393.  
  394.    if (stricmp(cw.dirbuf,tdir) == 0 || (cw.showall && *cw.dirbuf == *tdir)) {
  395.  
  396.       /* don't add the file if it doesn't match the selection criteria */
  397.  
  398.       if ((cw.selatrs & holdf.flags) != holdf.flags ||
  399.           (*cw.mask && (cw.maskcmp != match_name(holdf.name,cw.mask))))
  400.          return;
  401.  
  402.       if (numwin > 1)                       /* make sure files[] is ok */
  403.          restorefiles(cw.save_files,cw.nfiles);
  404.  
  405.       /* see if there is an existing file by that name in the target dir */
  406.  
  407.       for (i = cw.nfiles, tfp = files; i; i--, tfp++)
  408.           if (stricmp(tname,tfp->name) == 0 && stricmp(tdir,tfp->dirp) == 0)
  409.              break;
  410.  
  411.       if (i) {                      /* back out info for an existing */
  412.          delent(tfp);               /* file by the same name */
  413.          packfiles();               /* pack files[] now, not later */
  414.       }
  415.  
  416.       /* modify holding file entry to its final form */
  417.  
  418.       strncpy(holdf.name,tname,sizeof(holdf.name));        /* file name */
  419.       holdf.dirp = cw.showall ? findir(tdir) : cw.dirbuf;  /* file's dir */
  420.       holdf.index = cw.nfiles+1;                           /* a guess */
  421.  
  422.       /* add file to files[] if there is room */
  423.  
  424.       if (cw.nfiles < MAX_FILES) {
  425.  
  426.          /* since the files may be sorted by something other than name (say
  427.             date for example) we need to scan files[] again to find where to
  428.             insert the new entry - I used to just sort files[] again but qsort
  429.             is way to slow when files[] is already almost sorted */
  430.  
  431.          for (i = cw.nfiles, tfp = files; i; i--, tfp++)
  432.              if ((*cw.sortfunc)(&holdf,tfp) < 0)
  433.                 break;
  434.  
  435.          /* i > 0 if entry needs to be inserted, i = 0 if at end */
  436.  
  437.          if (i)
  438.             memcpy((char *)(tfp+1),(char *)tfp,i*sizeof(FILE_ENT));
  439.  
  440.          *tfp = holdf;                 /* finally, add entry */
  441.          cw.nfiles++;                  /* there is one more file now */
  442.          cw.num_files++;
  443.          cw.files_size += tfp->size;   /* taking this much more space */
  444.          cw.updated = W_DISP;          /* win needs redisplay (not packing) */
  445.          winupdate++;                  /* some window needs redisplay */
  446.  
  447.          if (numwin > 1)
  448.             savefiles(cw.save_files,cw.nfiles);
  449.       }
  450.    }
  451. }
  452.  
  453.  
  454. /****************************************************************************
  455.                           D E L F I L E _ E N T
  456.  ****************************************************************************/
  457.  
  458. static int
  459. delfile_ent() {        /* delete a FILE_ENT from target windows */
  460.  
  461.    register int i;
  462.    register FILE_ENT *tfp;
  463.  
  464.    /* if the current window displays the target dir or the target drive
  465.       in showall mode, delete the file ent */
  466.  
  467.    if (stricmp(cw.dirbuf,tdir) == 0 || (cw.showall && *cw.dirbuf == *tdir)) {
  468.  
  469.       if (numwin > 1)                       /* make sure files[] is ok */
  470.          restorefiles(cw.save_files,cw.nfiles);
  471.  
  472.       /* see if there is an existing file by that name in the target dir */
  473.  
  474.       for (i = cw.nfiles, tfp = files; i; i--, tfp++)
  475.           if (stricmp(tname,tfp->name) == 0 && stricmp(tdir,tfp->dirp) == 0)
  476.              break;
  477.  
  478.       if (i) {                      /* back out info for an existing */
  479.          delent(tfp);               /* file by the same name */
  480.          winupdate++;               /* window needs redisplay */
  481.          cw.updated |= W_PACK;      /* files[] needs to be packed */
  482.          if (numwin > 1)
  483.             savefiles(cw.save_files,cw.nfiles);
  484.       }
  485.    }
  486. }
  487.  
  488.  
  489. /*****************************************************************************
  490.                                 D E L E N T
  491.  *****************************************************************************/
  492.  
  493. delent(fp)             /* remove an entry from files[] */
  494. register FILE_ENT *fp;
  495. {
  496.    /* Note: this routine changes cw.num_files, but it doesn't change
  497.       cw.nfiles - this is because the routine packfiles which should
  498.       be called shortly needs the old value of cw.nfiles */
  499.  
  500.    cw.num_files--;                     /* one fewer file */
  501.    cw.files_size -= fp->size;          /* that much space not used */
  502.    if (fp->flags & TAGGED) {           /* was file tagged? */
  503.       cw.num_tagged--;                 /* one less tagged file */
  504.       cw.tag_size -= fp->size;         /* this space not tagged now */
  505.    }
  506.    *fp->name = '\0';                   /* mark this entry as deleted */
  507. }
  508.  
  509.  
  510. /****************************************************************************
  511.                           S C A N W I N D O W S
  512.  ****************************************************************************/
  513.  
  514. static int ALTCALL
  515. scanwindows(func)      /* scan windows, call func for each one */
  516. int (*func)();
  517. {
  518.    int i;
  519.    register WINDOW *wp;
  520.  
  521.    /* if there is a list of windows, start with the 1st; switch if not there */
  522.  
  523.    if (numwin > 1) {
  524.       wincpy(curwin,&cw);                      /* save current window if > 1 */
  525.       savefiles(cw.save_files,cw.nfiles);
  526.       if (curwin != winlis) {                  /* temp switch to top window */
  527.          wincpy(&cw,winlis);
  528.       }
  529.    }
  530.  
  531.    /* Note: only the files for the original window are saved and restored,
  532.       callers func should restore/savefiles if it needs to */
  533.  
  534.    for (i = numwin, wp = winlis; i; i--) {     /* check each file window */
  535.  
  536.       winp = wp;               /* let func know which window it is */
  537.  
  538.       (*func)();               /* invoke callers func with this window */
  539.  
  540.       if (numwin > 1) {        /* advance to next window if there is one */
  541.          wincpy(wp,&cw);
  542.          wincpy(&cw,wp = cw.next);
  543.       }
  544.    }
  545.  
  546.    if (numwin > 1) {           /* restore the current window if > 1 */
  547.       wincpy(&cw,curwin);
  548.       restorefiles(cw.save_files,cw.nfiles);
  549.    }
  550. }
  551.  
  552.  
  553. /******************************************************************************
  554.  **                             R E N E W                                    **
  555.  *****************************************************************************/
  556.  
  557. renew() {              /* renew the file display */
  558.  
  559.    getcwd(cw.dirbuf,MAX_PATHLEN);        /* reinit drive/dir info incase */
  560.    initdrive(*cw.dirbuf);                /*   it changed somehow */
  561.  
  562.    getfiles();                         /* reread the directory */
  563.    setup_file_scr();                   /* display the static screen image */
  564.    update_header();                    /* update header info */
  565.    refresh_screen(0);                  /* redisplay all file data */
  566. }
  567.  
  568.  
  569. /******************************************************************************
  570.                         R E N E W _ W I N D O W
  571.  *****************************************************************************/
  572.  
  573. renew_window() {       /* renew the current window display */
  574.  
  575.    getfiles();                         /* reload the files[] structure */
  576.    adjust_window();                    /* resize window data */
  577.    update_header();                    /* update the header  */
  578.    update_window(1);                   /* and the window data */
  579. }
  580.  
  581.  
  582. /******************************************************************************
  583.                           R E F R E S H _ S C R E E N
  584.  *****************************************************************************/
  585.  
  586. refresh_screen(wup)    /* (re)initialize the total file data display */
  587. int wup;
  588. {
  589.    win_update = wup;          /* save wup in static for refresh_window */
  590.  
  591.    if (inwin && wup == 0)     /* display the info header if needed */
  592.       infohead();
  593.  
  594.    scanwindows(refresh_window);        /* redisplay each window */
  595. }
  596.  
  597. /*****************************************************************************
  598.                         R E F R E S H _ W I N D O W
  599.  *****************************************************************************/
  600.  
  601. static int
  602. refresh_window() {     /* refresh one window - called by scanwindows */
  603.  
  604.    if (numwin > 1)
  605.       restorefiles(cw.save_files,cw.nfiles);
  606.  
  607.    if (win_update && cw.updated) {     /* is this a window update call? */
  608.       if (cw.updated & W_PACK)
  609.          packfiles();
  610.       if (numwin > 1)
  611.          savefiles(cw.save_files,cw.nfiles);
  612.    }
  613.  
  614.    /* redisplay this window if not a win_update call or win_update call and
  615.       this window has been modified */
  616.  
  617.    if (!win_update || cw.updated) {
  618.       adjust_window();                 /* calculate display parameters */
  619.       update_window(winp == curwin);   /* update display window */
  620.       cw.updated = 0;                  /* doesn't need to be updated again */
  621.    }
  622. }
  623.  
  624.  
  625. /******************************************************************************
  626.                     U P D A T E _ V O L _ S T A T S
  627.  ******************************************************************************/
  628.  
  629. update_vol_stats() {   /* get and display volume statistics */
  630.  
  631.    getvolsiz(*cw.dirbuf,&cw.drivep->vol_size,&cw.drivep->vol_free,
  632.              &cw.drivep->clustersiz);
  633.    disp_vol_stats();
  634. }
  635.  
  636.  
  637. /******************************************************************************
  638.                         U P D A T E _ H E A D E R
  639.  ******************************************************************************/
  640.  
  641. update_header() {      /* update display header */
  642.  
  643.    gotorc(VOL_ROW,1);                  /* make sure volume, directory, */
  644.    out_str(cw.drivep->volbuf,11,' ');  /* file, tagged info is correct */
  645.  
  646.    if (!cw.showall) {                  /* display the current dir name */
  647.       gotorc(VOL_ROW,PATH_COL+1);      /*   but if showall is in effect */
  648.       out_str(cw.dirbuf,65,' ');       /*   its done somewhere else */
  649.    }
  650.  
  651.    disp_vol_stats();
  652.    disp_file_stats();
  653.  
  654.    gotorc(MASK_ROW,MASK_COL-1);        /* display the selection mask */
  655.    disp_char(cw.maskcmp ? ' ' : '~');
  656.    out_str(cw.mask,MASK_LEN,' ');
  657.  
  658.    gotorc(MASK_ROW+1,MASK_COL-1);      /* display the selection attributes */
  659.    disp_attrib(cw.selatrs);
  660.    disp_str(cw.selatrs & DIR ? " D" : " .");
  661. }
  662.  
  663.  
  664. /******************************************************************************
  665.                         U P D A T E _ W I N D O W
  666.  *****************************************************************************/
  667.  
  668. int ALTCALL
  669. update_window(fptr)    /* display a window full of file info */
  670. int fptr;
  671. {
  672.    int col;
  673.    register int i, m;
  674.  
  675.    if (numwin > 1 || cw.showall)       /* display window header if > 1 */
  676.       disp_dirname();                  /*   window or showall mode */
  677.  
  678.    /* display a window of file names */
  679.  
  680.    for (i = 0; i + cw.fnrow < cw.fnrow + cw.ndrows; i++) {
  681.  
  682.       gotorc(i+cw.fnrow,0);
  683.  
  684.       if (i < cw.nrows) {
  685.          for (col = 0, m = cw.nbase + i; m < cw.nfiles; col++, m += cw.nrows)
  686.             disp_file(&files[m],(m == cw.curidx && fptr));
  687.  
  688.          if (col < cw.ncols)   /* try to only clear on rows where less */
  689.             clr_eol();         /* than ncols are displayed */
  690.       } else
  691.          clr_eol();
  692.    }
  693.  
  694.    /* display files dir path if showall mode */
  695.  
  696.    if (fptr && cw.showall && cw.curidx < cw.nfiles)
  697.       disp_path(cw.curidx);
  698.  
  699.    if (cw.nfiles == 0)         /* display a msg if no files in dir */
  700.       disp_empty_msg(fptr);
  701. }
  702.  
  703.  
  704. /******************************************************************************
  705.                         A D J U S T _ W I N D O W
  706.  *****************************************************************************/
  707.  
  708. int ALTCALL
  709. adjust_window() {
  710.  
  711.    /* for MS DOS, assume the max length file name is 13.  8 for the primary
  712.       name, 1 for '.', 3 for the extension, and 1 for '\' if its a directory */
  713.  
  714.    cw.maxlen = MAX_NAMELEN + 1;
  715.  
  716.    /* everything depends on # files in directory */
  717.  
  718.    if (cw.nfiles == 0)                 /* unusual, but dir may be empty */
  719.       cw.nrows = cw.ncols = 1;
  720.    else {                              /* are files, calc logical rows, cols */
  721.       cw.ncols = (cw.info_display) ? 1 : 5;
  722.       cw.nrows = (cw.nfiles+(cw.ncols-1)) / cw.ncols;
  723.    }
  724.  
  725.    cw.colsiz = SCREEN_COLS / cw.ncols;         /* width of each column */
  726.  
  727.    /* update current logical idx */
  728.  
  729.    if (cw.curidx >= cw.nfiles)
  730.       cw.curidx = cw.nfiles ? cw.nfiles - 1 : 0;
  731.  
  732.    /* make sure nbase is setup such that the current file is displayed */
  733.  
  734.    if (cw.nfiles <= cw.ndrows * cw.ncols) /* if file entries will fit on */
  735.       cw.nbase = 0;                       /*   1 screen, start at 1st */
  736.    else {
  737.       cw.nbase = idx2lr(cw.curidx) - cw.ndrows / 2;  /* try to center curidx */
  738.       if (cw.nbase > 0 && cw.nbase + cw.ndrows > cw.nrows) /* no blank rows  */
  739.          cw.nbase = cw.nrows - cw.ndrows;                  /* if possible    */
  740.       if (cw.nbase < 0)                              /* might overshoot */
  741.          cw.nbase = 0;
  742.    }
  743.  
  744. }
  745.  
  746.  
  747. /******************************************************************************
  748.                              I N F O C N T
  749.  *****************************************************************************/
  750.  
  751. infocnt(chg)           /* display/remove info header when required */
  752. int chg;
  753. {
  754.    int cur_isnt_top;
  755.  
  756.    inwin += chg;                       /* more or less info windows */
  757.  
  758.    cur_isnt_top = (numwin > 1 && curwin != winlis);
  759.  
  760.    /* if the count of info windows just went to 0, or it just went from 0 to 1,
  761.       we need to add or remove the info display header.  The top display
  762.       window losses or gains a row when this happens */
  763.  
  764.    if ((inwin == 0 && chg) || (inwin == 1 && chg > 0)) {
  765.  
  766.       /* do a temp switch to the top window if not already there */
  767.  
  768.       if (cur_isnt_top) {
  769.          wincpy(curwin,&cw);
  770.          savefiles(cw.save_files,cw.nfiles);
  771.          wincpy(&cw,winlis);
  772.          restorefiles(cw.save_files,cw.nfiles);
  773.       }
  774.  
  775.       /* now add or remove a row from the window */
  776.  
  777.       if (inwin) {                     /* remove a line, display header */
  778.          cw.fwrow++;  cw.fnrow++;
  779.          cw.wrows--;  cw.ndrows--;
  780.          infohead();
  781.       } else {                         /* add a line, remove header */
  782.          cw.fwrow--;  cw.fnrow--;
  783.          cw.wrows++;  cw.ndrows++;
  784.       }
  785.  
  786.       /* now update the top window display, but don't bother if the current
  787.          window is the top window - it will be updated by caller */
  788.  
  789.       if (cur_isnt_top) {
  790.          adjust_window();      /* calculate #rows, columns, etc to display */
  791.          update_window(0);
  792.       }
  793.  
  794.       /* restore windows if we did a temp switch above */
  795.  
  796.       if (cur_isnt_top) {
  797.          wincpy(winlis,&cw);
  798.          savefiles(cw.save_files,cw.nfiles);
  799.          wincpy(&cw,curwin);
  800.          restorefiles(cw.save_files,cw.nfiles);
  801.       }
  802.    }
  803. }
  804.  
  805.  
  806. /*****************************************************************************
  807.                       D I S P _ E M P T Y _ M S G
  808.  *****************************************************************************/
  809.  
  810. static int ALTCALL
  811. disp_empty_msg(on)     /* display empty dir msg w/wo highlighting */
  812. int on;
  813. {
  814.    if (on)
  815.       setvattrib(DIS_HIGH);
  816.  
  817.    disp_str_at("No files!",cw.fnrow+1,SCREEN_COLS/2-5);
  818.  
  819.    if (on)
  820.       setvattrib(DIS_NORM);
  821. }
  822.  
  823.  
  824. /*****************************************************************************
  825.                         D I S P _ D I R N A M E
  826.  *****************************************************************************/
  827.  
  828. disp_dirname() {       /* display the dir name header */
  829.  
  830.    char allmsg[20];
  831.  
  832.    if (cw.showall) {                   /* special header if showall mode */
  833.  
  834.       strcpy(allmsg,"FILES ON DRIVE ");
  835.       strncat(allmsg,cw.dirbuf,2);
  836.       center_text(cw.fwrow,allmsg);
  837.  
  838.    } else
  839.  
  840.       center_text(cw.fwrow,cw.dirbuf);    /* disp the dir name */
  841. }
  842.  
  843.  
  844. /*****************************************************************************
  845.                           I N F O H E A D
  846.  *****************************************************************************/
  847.  
  848. infohead() {           /* display the info header */
  849.  
  850.    setvattrib(DIS_HEAD);
  851.    disp_str_at("      NAME           USED  ALLOCATED     DATE         TIME      R H S A DIR",
  852.       FIRST_NROW,0);
  853.    clr_eol();
  854.    setvattrib(DIS_NORM);
  855. }
  856.  
  857.  
  858. /*****************************************************************************
  859.                             S H O W _ A L L
  860.  *****************************************************************************/
  861.  
  862. show_all() {
  863.  
  864.    if (anyshowall && !cw.showall)      /* only one window can do showall */
  865.       show_error(0,17,1,"Only one window can show all files!");
  866.  
  867.    if (cw.showall ^= 1) {      /* toggle showall mode */
  868.  
  869.       /* showall mode is being turned on, allocate space for dir name ptrs */
  870.  
  871.       if ((dirlst = (char **) calloc(MAX_DIR,sizeof(char *))) == NULL) {
  872.          cw.showall = 0;
  873.          show_error(0,16,1,"Out of memory!  Show All is not active!");
  874.       }
  875.  
  876.       if (numwin == 1) {       /* make row for showall header if not already */
  877.          cw.fnrow++;
  878.          cw.ndrows--;
  879.       }
  880.  
  881.       anyshowall = TRUE;       /* yes, a window has showall turned on */
  882.  
  883.    } else              /* showall is being turned off */
  884.  
  885.       showoff();
  886.  
  887.    renew_window();     /* redo window with/without showall mode */
  888. }
  889.  
  890. /*****************************************************************************
  891.                               S H O W O F F
  892.  *****************************************************************************/
  893.  
  894. showoff() {            /* turn off show all mode */
  895.  
  896.    register int i;
  897.    register char **cp;
  898.  
  899.    for (i = 0, cp = dirlst; i < diridx; i++, cp++)     /* release dir name */
  900.        free(*cp);                                      /*   memory */
  901.  
  902.    free((char *)dirlst);       /* now release pointer memory */
  903.  
  904.    diridx = 0;                 /* reset for next time */
  905.    dirlst = NULL;
  906.  
  907.    cw.showall = anyshowall = FALSE;    /* no window has showall now */
  908.  
  909.    if (numwin == 1) {          /* release showall header line if not needed */
  910.       cw.fnrow--;
  911.       cw.ndrows++;
  912.    }
  913. }
  914.  
  915.  
  916. /******************************************************************************
  917.                               W I N C P Y
  918.  ******************************************************************************/
  919.  
  920. static int ALTCALL
  921. wincpy(to,from)        /* copy window structures - I made this a separate */
  922. WINDOW *to, *from;     /* routine cause MSC generates a bunch of code for */
  923. {                      /* each structure asignment - in reality, it just a */
  924.                        /* little more than the code required to call this */
  925.                        /* function, but... */
  926.  
  927.    *to = *from;        /* not much to look at */
  928. }
  929.  
  930.  
  931. /******************************************************************************
  932.  **                  S A V E / R E S T O R E  F I L E S                      **
  933.  ******************************************************************************/
  934.  
  935. static int ALTCALL
  936. savefiles(fp,nf)       /* copy files[] to save area */
  937. char far *fp;
  938. int nf;
  939. {
  940.    movedata(dataseg,(unsigned int) files,FP_SEG(fp),FP_OFF(fp),
  941.              nf * sizeof(FILE_ENT));
  942. }
  943.  
  944. static int ALTCALL
  945. restorefiles(fp,nf)    /* copy files[] from save area */
  946. char far *fp;
  947. int nf;
  948. {
  949.    movedata(FP_SEG(fp),FP_OFF(fp),dataseg,(unsigned int) files,
  950.             nf * sizeof(FILE_ENT));
  951. }
  952.