home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 180.lha / Files_v1.2 / src / files.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  14KB  |  670 lines

  1.  
  2. /*
  3.  *  FILES.C
  4.  *
  5.  *  File Manager!
  6.  *
  7.  *  (c)Copyright 1987 Matthew Dillon, All Rights Reserved.
  8.  */
  9.  
  10. #include "files.h"
  11.  
  12. extern LOCK *Lock();
  13. extern LOCK *ParentDir(), *CurrentDir();
  14. extern void *malloc();
  15. extern void addentry();
  16.  
  17. RECORD *Rbase;        /*  All entries          */
  18. RECORD *DisplayTop;    /*  Entry at the display top */
  19. RECORD *Highlighted;    /*  Highlighted entry         */
  20. short  MaxNameLen;
  21. long   NumEntries;
  22. long   NumSelected;
  23. long   NumTop;
  24. long   NewNumTop;
  25. FIB    *Fib;
  26. short  Modified;
  27.  
  28. short  Xs, Xe, Ys, Ye, Rows, Cols;
  29.  
  30. char Title[80];
  31.  
  32. redisplay(newtop)
  33. {
  34.     short i;
  35.     short noscroll = 0;
  36.     uword percent, fill;
  37.     RECORD *rec;
  38.  
  39.     bigboxbounds(&Xs,&Xe,&Ys,&Ye);
  40.     Rows = (Ye-Ys)/Rp->TxHeight;
  41.     Cols = (Xe-Xs)/Rp->TxWidth;
  42.  
  43.     if (newtop) {
  44.     long delta = NumTop - NewNumTop;
  45.     if (delta < 0)
  46.         delta = -delta;
  47.     if (delta >= Rows)
  48.         noscroll = 1;
  49.     }
  50.     while (DisplayTop && !(DisplayTop->flags & R_SELECTED))
  51.     DisplayTop = DisplayTop->next;
  52.     if (newtop) {
  53.     while (NewNumTop != NumTop && DisplayTop) {
  54.         if (NewNumTop < NumTop) {
  55.         do {
  56.             DisplayTop = DisplayTop->prev;
  57.         } while (DisplayTop && !(DisplayTop->flags & R_SELECTED));
  58.         --NumTop;
  59.         if (DisplayTop && !noscroll) {
  60.             ScrollRaster(Rp, 0, -Rp->TxHeight, Xs, Ys, Xe-1, Ye-1);
  61.             displayat(DisplayTop, 0);
  62.         }
  63.         } else {
  64.         do {
  65.             DisplayTop = DisplayTop->next;
  66.         } while (DisplayTop && !(DisplayTop->flags & R_SELECTED));
  67.         ++NumTop;
  68.         if (DisplayTop && !noscroll) {
  69.             ScrollRaster(Rp, 0, Rp->TxHeight, Xs, Ys, Xe-1, Ye-1);
  70.             displayrow(Rows-1);
  71.         }
  72.         }
  73.     }
  74.     if (DisplayTop && !noscroll)
  75.         return(0);
  76.     }
  77.     sprintf(Title, "%ld/%ld", NumSelected, NumEntries);
  78.     title(Title);
  79.     if (DisplayTop == NULL) {
  80.     DisplayTop = Rbase;
  81.     NumTop = 0;
  82.     }
  83.     if (!newtop) {
  84.     percent = fill = 0xFFFF;
  85.     if (NumSelected) {
  86.         if (NumTop+(Rows>>1) > NumSelected)
  87.         percent = 0xFFFF;
  88.         else
  89.         percent = (NumTop + (Rows>>1)) * 0xFFFF / NumSelected;
  90.         fill = Rows * 0xFFFF / NumSelected;
  91.         if (Rows > NumSelected)
  92.         fill = 0xFFFF;
  93.     }
  94.     setslider(percent, fill);
  95.     }
  96.     SetAPen(Rp, 0);
  97.     RectFill(Rp, Xs, Ys, Xe-1, Ye-1);
  98.     SetAPen(Rp, 1);
  99.     for (rec = DisplayTop, i = 0; rec && i < Rows; rec = rec->next) {
  100.     if (!(rec->flags & R_SELECTED))
  101.         continue;
  102.     displayat(rec, i);
  103.     ++i;
  104.     }
  105. }
  106.  
  107. redisplayone(rec)
  108. RECORD *rec;
  109. {
  110.     RECORD *nrec;
  111.     short i;
  112.  
  113.     for (i = 0, nrec = DisplayTop; nrec && i < Rows; nrec = nrec->next) {
  114.     if (!(nrec->flags & R_SELECTED))
  115.         continue;
  116.     if (nrec == rec)
  117.         break;
  118.     ++i;
  119.     }
  120.     if (i < Rows && nrec == rec) {
  121.     SetAPen(Rp, 0);
  122.     RectFill(Rp, Xs, Ys + (Rp->TxHeight*i), Xe-1, Ys + (Rp->TxHeight*i) + Rp->TxHeight - 1);
  123.     SetAPen(Rp, 1);
  124.     displayat(rec, i);
  125.     }
  126. }
  127.  
  128. displayrow(row)
  129. {
  130.     register RECORD *rec = DisplayTop;
  131.     register short i = row;
  132.  
  133.     while (i && rec) {
  134.     rec = rec->next;
  135.     while (rec && !(rec->flags & R_SELECTED))
  136.         rec = rec->next;
  137.     --i;
  138.     }
  139.     if (rec && row < Rows)
  140.     displayat(rec, row);
  141. }
  142.  
  143. displayat(rec, i)
  144. RECORD *rec;
  145. {
  146.     short len;
  147.  
  148.     len = strlen(rec->name);
  149.     if (len > Cols)
  150.     len = Cols;
  151.     if (rec == Highlighted) {
  152.     SetAPen(Rp, 0);
  153.     SetBPen(Rp, 1);
  154.     }
  155.     Move(Rp, Xs, Ys + (Rp->TxHeight*i) + Rp->TxBaseline);
  156.     Text(Rp, rec->name, len);
  157.     if (Cols > MaxNameLen && rec->comment) {
  158.     len = strlen(rec->comment);
  159.     if (len > Cols - MaxNameLen)
  160.         len = Cols - MaxNameLen;
  161.     Move(Rp, Xs + MaxNameLen * Rp->TxWidth, Ys + (Rp->TxHeight * i) + Rp->TxBaseline);
  162.     Text(Rp, rec->comment, len);
  163.     }
  164.     if (rec == Highlighted) {
  165.     SetAPen(Rp, 1);
  166.     SetBPen(Rp, 0);
  167.     }
  168. }
  169.  
  170. bigboxhit(y, up)
  171. {
  172.     RECORD *hl = Highlighted;
  173.     short row;
  174.  
  175.     Highlighted = NULL;
  176.     if (hl)
  177.     redisplayone(hl);
  178.     row = (y - Ys) / Rp->TxHeight;
  179.     if (row >= Rows || Rows < 0)
  180.     return(0);
  181.     for (hl = DisplayTop; hl && !(hl->flags & R_SELECTED); hl = hl->next);
  182.     while (hl && row) {
  183.     if (hl->flags & R_SELECTED)
  184.         --row;
  185.     hl = hl->next;
  186.     }
  187.     for (; hl && !(hl->flags & R_SELECTED); hl = hl->next);
  188.     if (Highlighted = hl) {
  189.     redisplayone(hl);
  190.     setcomment((hl->comment) ? hl->comment : "");
  191.     if (up)
  192.         activate_com();
  193.     }
  194. }
  195.  
  196. sliderhit()
  197. {
  198.     uword pos, fill;
  199.  
  200.     getsliderpos(&pos, &fill);
  201.     NewNumTop = pos * (NumSelected - Rows + 1) / 0xFFFF;
  202.     redisplay(1);
  203. }
  204.  
  205. /*
  206.  *  Add a disk volume to the list.  Determine
  207.  *  the root and add entries beginning at the
  208.  *  specification.
  209.  */
  210.  
  211. void
  212. add_volume(str)
  213. char *str;
  214. {
  215.     LOCK *lock;
  216.     char path[128];
  217.     int len;
  218.  
  219.     Highlighted = NULL;
  220.     Fib = malloc(sizeof(FIB));
  221.     if (Fib == NULL)
  222.     return;
  223.     resetsort();                /* also cleans up the database  */
  224.     path[0] = 0;
  225.     if (lock = Lock(str, ACCESS_READ)) {
  226.     if (Examine(lock, Fib)) {
  227.         buildpath(lock, path);
  228.         len = strlen(path);
  229.         if (path[len-1] == ':' || path[len-1] == '/') {
  230.         path[len] = '*';
  231.         path[len+1] = 0;
  232.         select_pattern(path, 1);
  233.         path[len] = 0;
  234.         }
  235.         Examine(lock, Fib);
  236.         if (Fib->fib_DirEntryType < 0) {
  237.         addentry(path, Fib->fib_Comment, Fib->fib_Size);
  238.         } else {
  239.         RECORD *base;
  240.  
  241.         /*  find start of killpatterns, if any    */
  242.         for (base = Rbase; base; base = base->next) {
  243.             if (strcmp(base->name, KILLNAME) < 0)
  244.             continue;
  245.             break;
  246.         }
  247.         title("Wait.. Scanning");
  248.         scandir(lock, path, base);
  249.         }
  250.         title("Wait.. Update");
  251.         rem_selected(NULL,   1);
  252.     }
  253.     UnLock(lock);
  254.     }
  255.     free(Fib);
  256.     strcat(path, "*");
  257.     title("Select path");
  258.     select_pattern(path, 0);
  259. }
  260.  
  261. buildpath(lock, path)
  262. LOCK *lock;
  263. char *path;
  264. {
  265.     LOCK *parent;
  266.     short plen, nlen;
  267.  
  268.     plen = strlen(path);
  269.     nlen = strlen(Fib->fib_FileName) + 1;
  270.     if (nlen == 1) {    /*  RAM: */
  271.     strcpy(Fib->fib_FileName, "ram");
  272.     nlen = 4;
  273.     }
  274.     bmov(path, path + nlen, plen + 1);
  275.     strcpy(path, Fib->fib_FileName);
  276.     if (Fib->fib_DirEntryType >= 0)
  277.     path[nlen-1] = '/';
  278.     if (parent = ParentDir(lock)) {
  279.     if (Examine(parent, Fib)) {
  280.         buildpath(parent, path);
  281.     }
  282.     UnLock(parent);
  283.     } else {
  284.     path[nlen-1] = ':';
  285.     }
  286. }
  287.  
  288. scandir(lock, path, base)
  289. LOCK *lock;
  290. char *path;
  291. RECORD *base;
  292. {
  293.     short restorelen = strlen(path);
  294.     short len = restorelen;
  295.     LOCK *olddirlock;
  296.  
  297.     if (path[restorelen-1] != ':' && path[restorelen-1] != '/') {
  298.     strcpy(path + restorelen, "/");
  299.     ++len;
  300.     }
  301.     olddirlock = CurrentDir(lock);
  302.     if (notkilled(path, base))
  303.     addentry(path, Fib->fib_Comment, Fib->fib_Size);
  304.     while (ExNext(lock, Fib)) {
  305.     strcpy(path+len, Fib->fib_FileName);
  306.     if (Fib->fib_DirEntryType < 0) {
  307.         if (notkilled(path, base))
  308.         addentry(path, Fib->fib_Comment, Fib->fib_Size);
  309.     } else {
  310.         LOCK *lock = Lock(Fib->fib_FileName, ACCESS_READ);
  311.         if (lock) {
  312.         FIB *oldfib = Fib;
  313.         if (Fib = malloc(sizeof(FIB))) {
  314.             Examine(lock, Fib);
  315.             scandir(lock, path, base);
  316.             UnLock(lock);
  317.             free(Fib);
  318.         }
  319.         Fib = oldfib;
  320.         }
  321.     }
  322.     }
  323.     CurrentDir(olddirlock);
  324.     path[restorelen] = 0;
  325. }
  326.  
  327. notkilled(path,base)
  328. char *path;
  329. RECORD *base;
  330. {
  331.     while (base && strcmp(base->name, KILLNAME) == 0) {
  332.     if (base->comment && newwildcmp(base->comment, path))
  333.         return(0);
  334.     base = base->next;
  335.     }
  336.     return(1);
  337. }
  338.  
  339. load_database(fi)
  340. FILE *fi;
  341. {
  342.     char name[132];
  343.     char comm[132];
  344.     char size[32];
  345.  
  346.     fgets(name, 128, fi);   /*  # entries per item  */
  347.     Highlighted = NULL;
  348.     resetsort();
  349.     title("Wait... Loading");
  350.     while (fgets(name, 128, fi) && fgets(comm, 128, fi) && fgets(size, 32, fi)) {
  351.     name[strlen(name)-1] = 0;   /*  remove newlines */
  352.     comm[strlen(comm)-1] = 0;
  353.     addentry(name, comm, atoi(size));
  354.     }
  355.     rem_selected(NULL, 1);
  356.     selectall();
  357.     redisplay(0);
  358. }
  359.  
  360. save_database(fi)
  361. FILE *fi;
  362. {
  363.     RECORD *rec;
  364.     char buf[32];
  365.  
  366.     cleanup();
  367.     title("Saving...");
  368.     fputs("3\n", fi);
  369.     for (rec = Rbase; rec; rec = rec->next) {
  370.     fwrite(rec->name, strlen(rec->name), 1, fi);
  371.     putc('\n', fi);
  372.     if (rec->comment)
  373.         fwrite(rec->comment, strlen(rec->comment), 1, fi);
  374.     putc('\n', fi);
  375.     sprintf(buf, "%ld\n", rec->bytes);
  376.     fputs(buf, fi);
  377.     if (ferror(fi))
  378.         break;
  379.     }
  380. }
  381.  
  382. selectall()
  383. {
  384.     RECORD *rec;
  385.     short len;
  386.  
  387.     Highlighted = NULL;
  388.     DisplayTop = NULL;
  389.     MaxNameLen = 0;
  390.     for (rec = Rbase; rec; rec = rec->next) {
  391.     if (rec->flags & R_KILLPAT)
  392.         continue;
  393.     len = strlen(rec->name);
  394.     if (MaxNameLen <= len)
  395.         MaxNameLen = len + 1;
  396.     rec->flags |= R_SELECTED;
  397.     }
  398.     NumSelected = NumEntries;
  399. }
  400.  
  401. select_pattern(str, noref)
  402. char *str;
  403. {
  404.     register RECORD *rec;
  405.     register short len;
  406.     short which = 0;
  407.  
  408.     if (*str == '+')    /*  ADD selected patterns   */
  409.     ++str, which = 1;
  410.     if (*str == '-')    /*  REMOVE selected patterns*/
  411.     ++str, which = 2;
  412.     DisplayTop = NULL;
  413.     Highlighted= NULL;
  414.  
  415.     switch(which) {
  416.     case 0:
  417.     NumSelected = 0;
  418.     MaxNameLen = 0;
  419.     for (rec = Rbase; rec; rec = rec->next) {
  420.         rec->flags &= ~R_SELECTED;
  421.         if (rec->flags & R_KILLPAT)
  422.         continue;
  423.         if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
  424.         if (noref) {
  425.             rec->flags |= R_UPDATE;
  426.         } else {
  427.             rec->flags |= R_SELECTED;
  428.             ++NumSelected;
  429.             if ((len = strlen(rec->name)) >= MaxNameLen)
  430.             MaxNameLen = len + 1;
  431.         }
  432.         }
  433.     }
  434.     break;
  435.     case 1:
  436.     for (rec = Rbase; rec; rec = rec->next) {
  437.         if ((rec->flags & R_KILLPAT) || (rec->flags & R_SELECTED))
  438.         continue;
  439.         if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
  440.         rec->flags |= R_SELECTED;
  441.         ++NumSelected;
  442.         if ((len = strlen(rec->name)) >= MaxNameLen)
  443.             MaxNameLen = len + 1;
  444.         }
  445.     }
  446.     break;
  447.     case 2:
  448.     for (rec = Rbase; rec; rec = rec->next) {
  449.         if (!(rec->flags & R_SELECTED))
  450.         continue;
  451.         if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
  452.         rec->flags &= ~R_SELECTED;
  453.         --NumSelected;
  454.         }
  455.     }
  456.     break;
  457.     }
  458.     if (!noref)
  459.     redisplay(0);
  460. }
  461.  
  462. /*
  463.  *  If onerec != NULL, remove the one record,
  464.  *  else remove all SELECTED records.
  465.  */
  466.  
  467. rem_selected(onerec, noref)
  468. RECORD *onerec;
  469. {
  470.     register RECORD *rec;
  471.     register long len, maxlen;
  472.  
  473.     Highlighted = NULL;
  474.     cleanup();
  475.     if (onerec) {
  476.     if (onerec->flags & R_SELECTED) {
  477.         onerec->flags &= ~R_SELECTED;
  478.         --NumSelected;
  479.     }
  480.     onerec->flags |= R_KILLPAT;
  481.     --NumEntries;
  482.     } else {
  483.     maxlen = 0;
  484.     for (rec = Rbase; rec; rec = rec->next) {
  485.         if (noref) {
  486.         if (rec->flags & R_UPDATE) {
  487.             rec->flags &= ~R_UPDATE;
  488.             rec->flags |= R_KILLPAT;
  489.             --NumEntries;
  490.         }
  491.         } else {
  492.         if (rec->flags & R_SELECTED) {
  493.             rec->flags &= ~R_SELECTED;
  494.             rec->flags |= R_KILLPAT;
  495.            --NumEntries;
  496.         }
  497.         }
  498.         if (!(rec->flags & R_KILLPAT) && (len=strlen(rec->name)) > maxlen)
  499.         maxlen = len;
  500.     }
  501.     if (!noref)
  502.         NumSelected = 0;
  503.     MaxNameLen = maxlen+1;
  504.     }
  505.     if (noref)
  506.     cleanup();
  507.     else
  508.     redisplay(0);
  509. }
  510.  
  511. undo()
  512. {
  513.     RECORD *rec;
  514.  
  515.     Highlighted = NULL;
  516.     for (rec = Rbase; rec; rec = rec->next) {
  517.     if (rec->flags & R_KILLPAT) {
  518.         rec->flags &= ~R_KILLPAT;
  519.         rec->flags |= R_SELECTED;
  520.         ++NumSelected;
  521.         ++NumEntries;
  522.         if (strlen(rec->name) >= MaxNameLen)
  523.         MaxNameLen = strlen(rec->name)+1;
  524.     }
  525.     }
  526.     redisplay(0);
  527. }
  528.  
  529. cleanup()
  530. {
  531.     RECORD *rec, *nrec;
  532.     for (rec = Rbase; rec; rec = nrec) {
  533.     nrec = rec->next;
  534.     if (rec->flags & R_KILLPAT) {
  535.         if (rec == DisplayTop)
  536.         DisplayTop = nrec;
  537.         rmrecord(rec);
  538.     }
  539.     }
  540. }
  541.  
  542. rmrecord(rec)
  543. RECORD *rec;
  544. {
  545.     if (rec->flags & R_SOFTERR) {
  546.     puts("panic: soft error");
  547.     exit(1);
  548.     }
  549.     if (rec->prev)
  550.     rec->prev->next = rec->next;
  551.     else
  552.     Rbase = rec->next;
  553.     if (rec->next)
  554.     rec->next->prev = rec->prev;
  555.     rec->flags |= R_SOFTERR;
  556.     freestr(rec->name);
  557.     freestr(rec->comment);
  558.     freerecord(rec);
  559. }
  560.  
  561. /*
  562.  *  modify the comment field for the highlighted
  563.  *  item.
  564.  */
  565.  
  566. mod_comment(str)
  567. char *str;
  568. {
  569.     if (Highlighted) {
  570.     Modified = 1;
  571.     freestr(Highlighted->comment);
  572.     if (str[0]) {
  573.         Highlighted->comment = allocstr(str);
  574.         if (Highlighted->comment == NULL)
  575.         title("OUT OF MEMORY!");
  576.     } else {
  577.         Highlighted->comment = NULL;
  578.     }
  579.     redisplayone(Highlighted);
  580.     }
  581. }
  582.  
  583.  
  584. static RECORD *Cache;
  585.  
  586. resetsort()
  587. {
  588.     cleanup();
  589.     Cache = Rbase;
  590. }
  591.  
  592. void
  593. addentry(name, comm, size)
  594. char *name;
  595. char *comm;
  596. long size;
  597. {
  598.     RECORD *rec;
  599.     short n;
  600.  
  601.     Modified = 1;
  602.     rec = allocrecord();
  603.     if (rec == NULL) {
  604.     title("OUT OF MEMORY!");
  605.     return;
  606.     }
  607.     rec->name = allocstr(name);
  608.     if (rec->name == NULL) {
  609.     rmrecord(rec);
  610.     title("OUT OF MEMORY!");
  611.     return;
  612.     }
  613.     rec->comment = NULL;
  614.     if (strlen(comm)) {
  615.     rec->comment = allocstr(comm);
  616.     if (rec->comment == NULL) {
  617.         freestr(rec->name);
  618.         rmrecord(rec);
  619.         title("OUT OF MEMORY!");
  620.         return;
  621.     }
  622.     }
  623.     rec->bytes = size;
  624.  
  625.     if (Rbase == NULL) {
  626.     Rbase = rec;
  627.     rec->prev = NULL;
  628.     rec->next = NULL;
  629.     } else {
  630.     short n = strcmp(name, Cache->name);
  631.     if (n == 0 && strcmp(name, KILLNAME) == 0)
  632.         n = 1;
  633.     if (n < 0) {                    /*  name < Cache, move backwards */
  634.         while ((Cache = Cache->prev) && (n=strcmp(name, Cache->name)) < 0);
  635.     } else
  636.     if (n > 0) {                    /*  name > Cache, move forwards  */
  637.         while (Cache->next && (n=strcmp(name, Cache->next->name)) > 0)
  638.         Cache = Cache->next;
  639.         if (Cache->next && n == 0)
  640.         Cache = Cache->next;
  641.     }
  642.     if (Cache) {
  643.         rec->next = Cache->next;    /*  insert after cache */
  644.         rec->prev = Cache;
  645.         Cache->next = rec;
  646.     } else {            /*  or at beginning    */
  647.         rec->next = Rbase;
  648.         rec->prev = NULL;
  649.         Rbase = rec;
  650.     }
  651.     if (rec->next)
  652.         rec->next->prev = rec;
  653.     if (n == 0) {                   /*  replace if exact   */
  654.         if (Cache->comment) {
  655.         char *swap = Cache->comment;
  656.         Cache->comment = rec->comment;
  657.         rec->comment = swap;
  658.         Cache->flags |= R_UPDATE;
  659.         }
  660.     }
  661.     }
  662.     rec->flags = R_SELECTED;
  663.     ++NumSelected;
  664.     ++NumEntries;
  665.     if (MaxNameLen <= strlen(rec->name))
  666.     MaxNameLen = strlen(rec->name) + 1;
  667.     Cache = rec;
  668. }
  669.  
  670.