home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 522.lha / ccd_v2.0 / ccd.c < prev    next >
C/C++ Source or Header  |  1991-06-09  |  22KB  |  857 lines

  1. #include <stdio.h>
  2. #include <assert.h>
  3. #include <proto/dos.h>
  4. #include <proto/intuition.h>
  5. #include <libraries/dos.h>
  6. #include <libraries/dosextens.h>
  7. #include <exec/memory.h>
  8. #include <exec/types.h>
  9. #include <intuition/intuition.h>
  10.  
  11. #include "ccd.h"
  12. #include "win.h"
  13.  
  14. #define GRAPHICS
  15. #define VERSION "2"
  16. #define WINDOWTITLE "ccd v2.0, beta version         by Cédric BEUST"
  17.  
  18. #define CCDCONFIGFILE "ccd:.ccdconfig"
  19. #define WIDTH 640             /* width of the display */
  20. #define HEIGHT 200           /* its height */
  21. #define DELTAX 80           /* # of pixels between two entries */
  22. #define DELTAY 10          /* vertical step */
  23. #define UPPERX 25         /* upper corner where we start to write */
  24. #define UPPERY 7         /* ditto */
  25.  
  26. #define LINESPERWINDOW 18          /* # of lines displayed */
  27. #define BETWEEN_GADGETS 10        /* # of vert pixels between gadgets */
  28.  
  29. #define min(a,b) (a < b ? a : b)
  30.  
  31. #define NEW(v, t) v = (t *) malloc(sizeof(*v))
  32.  
  33. static char actualdir[128];
  34. struct Window *mainwindow;
  35. struct Screen *mainscreen;
  36. long IntuitionBase;
  37. long GfxBase;
  38. int configlines = 0;    /* # of lines in ccdconfig */
  39. int actualline = 1;
  40. int nbvolumes = 0;    /* # of volumes found */
  41. int volumesid = 0;   /* id of the first Volume gadgets */
  42.  
  43. USHORT *chippointer = NULL, *chippointer2 = NULL;
  44.  
  45. struct Tree_t {
  46.   struct Tree_t *brother;
  47.   struct Tree_t *son;      /* could be sister and daughter... */
  48.   char name[128];
  49.   char fullname[128];
  50.   int x;
  51.   int line;
  52. } *the_tree = NULL;
  53.  
  54. int show_ambiguities = 0;
  55. int update_list = 0;
  56. int no_expand = 0;
  57.  
  58. BPTR locklist[128];
  59. int lockpt = 0;
  60.  
  61. BPTR
  62. get_a_lock(char *name, long code)
  63. {
  64.   locklist[lockpt] = Lock(name, code);
  65.   if (locklist[lockpt])
  66.     return locklist[lockpt++];
  67.   else
  68.     return 0;
  69. }
  70.  
  71. void
  72. unlock(BPTR lock)
  73. {
  74. /*
  75.   UnLock(lock);
  76. */
  77. }
  78.  
  79. void
  80. free_all_locks()
  81. {
  82.   int i;
  83.   for (i = 0; i < lockpt; i++)
  84.     UnLock(locklist[i]);
  85. }
  86.  
  87. void
  88. myputs(char *s)
  89. {
  90.   Write(Output(), s, strlen(s));
  91. }
  92.  
  93. void
  94. Read_Dirs(char *dir, FILE *f)
  95. {
  96.   BPTR lock;
  97.   struct FileInfoBlock info, *fib;
  98.  
  99.   lock = Lock(dir, ACCESS_READ);
  100.   if (lock == 0) {
  101.     fprintf(stderr,"*** Yup! Couldn't lock %s\n", dir);
  102.     return;
  103.   }
  104.   
  105.   fib = (struct FileInfoBlock *) Examine(lock, &info);
  106.   fib = &info;
  107.   while (1) {
  108.     if (ExNext(lock, fib) == 0) break;
  109.     if (fib -> fib_DirEntryType > 0) {
  110.       char t[50],c;
  111.       strcpy(t, dir);
  112.       if ((c = t[strlen(t) - 1]) != ':' && c != '/')
  113.         strcat(t,"/");
  114.       strcat(t, fib -> fib_FileName);
  115.       fprintf(f, "%s\n", t);
  116.       Read_Dirs(t,f);
  117.     }
  118.   }
  119.   unlock(lock);
  120. }
  121.  
  122. void
  123. Update(char **dirname, int ndirs)
  124. /* Update the config file with the list of dirs (dirname) of length ndirs */
  125. {
  126.   FILE *f = fopen(CCDCONFIGFILE,"w");
  127.   int i;
  128.  
  129.   if (f == NULL) {
  130.     fprintf(stderr, "*** Couldn't open '%s', maybe an assign is missing?\n", CCDCONFIGFILE);
  131.     return(0);
  132.   } 
  133.  
  134.   Put_Version(f);
  135.   printf("Updating %s with", CCDCONFIGFILE);
  136.   for (i = 0; i < ndirs; i++) {
  137.     printf(" %s", *dirname);
  138.     fflush(stdout);
  139.     fprintf(f, "%s\n", *dirname);
  140.     Read_Dirs(*dirname++, f);
  141.   }
  142.   printf(" -- done!\n");
  143.   fclose(f);
  144. }
  145.  
  146. int
  147. mystricmp(char *bigdir, char *shortdir)
  148. /* Check if shortdir is part of the path bigdir, return 0 if it is */
  149. {
  150.   char t[50], *pt = t, *ps;
  151.   int end = 0;
  152.   int i = 0;
  153.  
  154.   while (*bigdir) {
  155.     while (*bigdir && *bigdir != ':' && *bigdir != '/' && *bigdir != '\n')
  156.       *pt++ = *bigdir++;
  157.     if (*bigdir) bigdir++;
  158.     *pt++ = '\0';
  159.     pt = t;
  160.   }
  161.  
  162. /* Now, we must see if shortdir is included in t */
  163.  
  164.   for (i = 0; i <= strlen(t) - strlen(shortdir); i++) {
  165.     pt = &t[i]; ps = shortdir;
  166.     while (*pt && *ps && (*pt | 0x20) == (*ps | 0x20)) {
  167.       ps++; pt++;
  168.     };
  169.     if (*pt == 0 || *ps == 0) return(0);   /* match! */
  170.   }
  171.   return(1);
  172. }
  173.  
  174. void
  175. Update_Prompt(char *currentdir)
  176. /* Update the concerned field with the new current dir                 */
  177. /* This routine is for users of wshell or such, thar display this name */
  178. /* as the shell prompt.                                                */
  179. /* This trick was previously pointed to me by Henry J. Cobb on Usenet  */
  180. /* for my 'find' program (another great utility of mine :-)).          */
  181. /* Let him be thanked again!                                           */
  182. {
  183.   struct Process *pr = (struct Process *) FindTask(0L);
  184.   struct CommandLineInterface *cli =
  185.     (struct CommandLineInterface *) (pr -> pr_CLI) << 2;
  186.   char *p = (char *) (cli -> cli_SetName) << 2;
  187.  
  188.   *p++ = strlen(currentdir);          /* it is a BSTR, so length first */
  189.   while (*currentdir) *p++ = *currentdir++;  /* don't add '\0' */
  190. }
  191.  
  192. int
  193. Check_Version(FILE *f)
  194. {
  195.    char v[100];
  196.  
  197.    fscanf(f, "%s\n", v);
  198.    if (! isdigit(v[0]) || atoi(v) < atoi(VERSION)) {
  199.       printf("*** config file is obsolete for this version, run ccd -u\n");
  200.       fclose(f);
  201.       exit(0);
  202.    }
  203. }
  204.  
  205. int
  206. Put_Version(FILE *f)
  207. {
  208.    fprintf(f, "%s\n", VERSION);
  209. }
  210.  
  211. char *
  212. locate_dir(char *dir, FILE *f)
  213. /* Return the complete path for the fragment given, if any, in file *f */
  214. {
  215.   int match = 0;
  216.   static char onedir[100];
  217.  
  218.   while (! feof(f) && ! match) {
  219.     int i;
  220.     fgets(onedir, 100, f);
  221.     i = strlen(onedir) - 1;
  222.     if (onedir[i] == '\n')
  223.       onedir[i] = '\0';     /* strip trailing \n */
  224.     if (mystricmp(onedir, dir) == 0) {
  225.       match = 1;
  226.       break;
  227.     }
  228.   }
  229.   if (match) return(onedir);
  230.   else return(NULL);
  231. }
  232.  
  233. char *
  234. reverse(char *s)
  235. /* Return the string s backwards (modify s)*/
  236. {
  237.   register char c;
  238.   char *result = s + strlen(s) - 1, *r2 = s;
  239.  
  240.   while (result > s) {
  241.     c = *result;
  242.     *result = *s;
  243.     *s = c;
  244.     s++; result--;
  245.   }
  246.   return(r2);
  247. }
  248.  
  249. void
  250. Get_Real_Name(BPTR lock, char *result)
  251. /* This is a very useful function! Put in result path of lock */
  252. /* Assume lock is not null */
  253. /* Result always device:dir/dir/...   */
  254. {
  255.   char *p = result;
  256.   struct FileInfoBlock ib;  
  257.  
  258.   assert(lock);
  259.  
  260.   if (no_expand) return;
  261.   Examine(lock, &ib);
  262.   strcpy(result, reverse(ib.fib_FileName));
  263.   strcat(result, "/");
  264.   while (lock) {
  265.     lock = ParentDir(lock);
  266.     if (lock) {
  267.       Examine(lock, &ib);
  268.       strcat(result, reverse(ib.fib_FileName));
  269.       strcat(result,"/");
  270.       unlock(lock);
  271.     }
  272.   }
  273.   p = &p[strlen(p) - 1];
  274.   *p-- = '\0';
  275.   while (*p != '/') p--;
  276.   *p = ':';
  277.   reverse(result);
  278. }
  279.  
  280. void
  281. Call_CurrentDir(char *actualdir)
  282. {
  283.    BPTR lock;
  284.  
  285.    if (actualdir[0]) {
  286.       lock = Lock(actualdir, ACCESS_READ);
  287.       if (lock == 0) {
  288.          fprintf(stderr,
  289.       "*** Couldn't cd to %s, '%s' probably outdated (re-run ccd -u)\n",
  290.             actualdir, CCDCONFIGFILE);
  291.          exit(0);
  292.       }
  293.       CurrentDir(lock);
  294.       Get_Real_Name(lock, actualdir);
  295.       printf("Current directory is now %s\n", actualdir);
  296.       Update_Prompt(actualdir);
  297.       unlock(lock);
  298.   }
  299.   else
  300.     printf("%s: no such dir\n", actualdir);
  301. }
  302.  
  303. void
  304. Change_Dir(char *dir, int occ)
  305. /* The main function to change to the fragment of dir given,  */
  306. /* to the occ'th occurence found in the config file */
  307. /* New 1.3: first, try to cd right into 'dir' */
  308. {
  309.   char cmd[50];
  310.   FILE *f = fopen(CCDCONFIGFILE,"r");
  311.   int match = 0;
  312.   BPTR lock;
  313.  
  314.   Check_Version(f);
  315.   strcpy(actualdir, dir);
  316.   if ((lock = Lock(actualdir, ACCESS_READ))) {   /* can we cd directly? */
  317.     BPTR old;
  318.     Get_Real_Name(lock, actualdir);
  319.     lock = get_a_lock(actualdir, ACCESS_READ);
  320.     printf("Current directory is now %s\n", actualdir);
  321.     Update_Prompt(actualdir);
  322.     old = CurrentDir(lock);                     /* yes! Do it and end */
  323. /*
  324.     UnLock(lock);
  325.     UnLock(old);
  326. */
  327.     return;
  328.   }
  329.  
  330.                            /* no, dir is a path fragment */
  331.    if (f == NULL) {
  332.      fprintf(stderr,
  333.         "*** Couldn't open '%s'; run ccd -u first, will you?\n", CCDCONFIGFILE);
  334.      exit(0);
  335.    };
  336.  
  337.    while (occ--) {
  338.      strcpy(actualdir, locate_dir(dir, f));
  339.    }
  340.  
  341.    Call_CurrentDir(actualdir);
  342.  
  343.   fclose(f);
  344. }
  345.  
  346. void
  347. Show_Ambiguities(char *dir)
  348. {
  349.   char *onedir = NULL;
  350.   char cmd[50];
  351.   FILE *f = fopen(CCDCONFIGFILE,"r");
  352.   int match = 0;
  353.  
  354.   if (f == NULL) {
  355.     fprintf(stderr,
  356.        "*** Couldn't open '%s'; run ccd -u first, will you?\n", CCDCONFIGFILE);
  357.     exit(0);
  358.   };
  359.  
  360.   Check_Version(f);
  361.   while ((onedir = locate_dir(dir, f))) {
  362.      myputs(onedir);
  363.      myputs("\n");
  364.   }
  365.  
  366.   fclose(f);  
  367. }
  368.  
  369. void
  370. Usage()
  371. {
  372.   myputs("\nccd v2.0,  by Cedric Beust    (C) 1991\n\n");
  373.   myputs("    Usage:\n");
  374.   myputs("           ccd                           Brings up the graphics display\n");
  375.   myputs("     or    ccd -u <dir> <dir> ...        Rebuild dir list with dirs\n");
  376.   myputs("     or    ccd -a <partial dir>          Show ambiguities\n");
  377.   myputs("     or    ccd [opt] <partial dir> [n]   Change to this dir, nth occurence\n");
  378.   myputs("             where opt is one of\n");
  379.   myputs("                 -n    No path expansion\n\n");
  380.   exit(0);
  381. }
  382.  
  383. void
  384. get_vol(char *path, char *vol)
  385. /* String is a line of the .ccdconfig (volume:a/b/c) */
  386. /* Return volume in the variable vol */
  387. {
  388.    char *p = path;
  389.    while (*p && *p != ':') *vol++ = *p++;
  390.    *vol++ = '\0';  
  391. }
  392.  
  393. int
  394. numberofdirs(char *path)
  395. /* path is 'vol:a/b/c' */
  396. /* Return number of dirs in it (3 here), actually = number of '/' + 1 */
  397. {
  398.    int result = 0;
  399.  
  400.    while (*path) {
  401.       while (*path && *path != '/') path++;
  402.       if (*path == '/') {
  403.          result++;
  404.          path++;
  405.       }
  406.    }
  407.    return(++result);
  408. }
  409.  
  410. void
  411. nthdir(char *dir, char *path, int n)
  412. /* Path is 'volume:a/b/c' */
  413. /* Return in dir the nth dir in it (e.g. with n=2, it's b) */
  414. {
  415.    char *dirhead = dir;
  416.    while (*path && *path != ':') path++;
  417.    if (*path == ':') {
  418.      path++;
  419.      while (*path) {
  420.          while (*path && *path != '/') {
  421.             *dir++ = *path++;
  422.          }
  423.          if (*(dir - 1) == '\n') dir--;
  424.          *dir++ = '\0';
  425.          if (*path == '/') path++;
  426.          if (n == 1) return;
  427.          else {
  428.             n--; dir = dirhead;
  429.          }
  430.       }
  431.    }
  432.    else {
  433.       printf("nthdir: problem\n");
  434.       exit(0);
  435.    }
  436. }
  437.  
  438. struct Tree_t *
  439. new_node(char *s, int line, int x, char *fullname)
  440. {
  441.    struct Tree_t *newnode;
  442.  
  443.    NEW(newnode, struct Tree_t);
  444.    if (s[strlen(s) - 1] == '\n')
  445.       s[strlen(s) - 1] = '\0';
  446.    strcpy(newnode -> name, s);
  447.    strcpy(newnode -> fullname, fullname);
  448.    newnode -> brother = NULL;
  449.    newnode -> son = NULL;
  450.    newnode -> line = line;
  451.    newnode -> x = x;
  452.    return(newnode);
  453. }
  454.  
  455. struct Tree_t *
  456. get_line(struct Tree_t *root, int line)
  457. /* Return the struct for line line, searching from root */
  458. {
  459. /*
  460.    printf("get_line with %s, %d\n", root->name, line);
  461. */
  462.    if (root) {
  463.       if (root -> line == line) return root;
  464.       else if (root -> brother) {
  465.          if (root -> brother -> line <= line)
  466.             return get_line(root -> brother, line);
  467.          else
  468.             return get_line(root -> son, line);
  469.       }
  470.       else
  471.          return get_line(root -> son, line);
  472.    }
  473.    return NULL;
  474. }
  475.  
  476. void
  477. add_node(char *s, struct Tree_t *root, int line)
  478. /* Add the appropriate node to the tree */
  479. /* Assert root != NULL */
  480. /*
  481.       dh0:   ->    dh1:    ->   dh2:
  482.                     | 
  483.                   Anews
  484.                     |
  485.                    New
  486. */
  487. {
  488.    char vol[30];
  489.    char dir[30];
  490.    struct Tree_t *newnode;
  491.    int i;
  492.    int x = UPPERX - DELTAX;
  493.  
  494.    get_vol(s, vol);
  495.    assert(root);
  496.    while (root -> brother && stricmp(root -> name, vol))
  497.       root = root -> brother;
  498.  
  499.    if (strcmp(root -> name, vol)) {   /* new vol, must create a new node */
  500.       root -> brother = new_node(vol, line, x + DELTAX, s);
  501.       newnode = root -> brother;
  502.    }
  503.    else {
  504.       struct Tree_t *t = root;
  505.       newnode = root;
  506.    }
  507.    assert(newnode);
  508.    assert(stricmp(newnode -> name, vol) == 0);
  509.  
  510. /* Now, newnode is a node that contains the volume. Create the path */
  511.  
  512.    for (i = 1; i <= numberofdirs(s); i++) {             
  513.       x = newnode -> x;
  514.       nthdir(dir, s, i);
  515.       if (newnode -> son) {
  516.          root = newnode -> son;     /* get down one level */
  517.  
  518. /* Search amid the brothers if we have a matching name */
  519.          while (root -> brother && stricmp(dir, root -> name)) {
  520.             root = root -> brother;
  521.          }
  522.          if (stricmp(root -> name, dir)) {    /* new dir, create new node */
  523.             newnode = root -> brother = new_node(dir, line, x + DELTAX, s);
  524.          }
  525.          else {
  526.             newnode = root;
  527.          }
  528.       }
  529.       else {    /* no son yet, have to create one */
  530.          newnode -> son = new_node(dir, line, x + DELTAX, s);
  531.          newnode = newnode -> son;
  532.       }
  533.  
  534. /* Now, newnode is a node that contains how far we've got in the path */
  535. /* Let's go on */
  536.       root = newnode;
  537.    }
  538. }
  539.  
  540. struct Tree_t *
  541. Build_Tree()
  542. {
  543.    FILE *f;
  544.    char string[128];
  545.    char currentvol[30];
  546.    struct Tree_t *result;
  547.  
  548.    f = fopen(CCDCONFIGFILE, "r");
  549.    if (f == NULL) {
  550.      fprintf(stderr,
  551.         "*** Couldn't open '%s'; run ccd -u first, will you?\n", CCDCONFIGFILE);
  552.      exit(0);
  553.    };
  554.  
  555.    Check_Version(f);
  556.    NEW(result, struct Tree_t);
  557.    strcpy(result -> name, "Root");
  558.    result -> brother = NULL;
  559.    result -> son = NULL;
  560.    result -> line = -1;
  561.  
  562.    while (! feof(f)) {
  563.       configlines++;
  564.       fgets(string, 128, f);
  565.       if (string[strlen(string) - 1] == '\n')
  566.          string[strlen(string) - 1] = '\0';
  567.       add_node(string, result, configlines);
  568.    }
  569.    return result;
  570. }
  571.  
  572. void
  573. Find_Dir_Coo(int x, int y, int line)
  574. {
  575.    struct Tree_t *root;
  576.  
  577.    root = get_line(the_tree, line + (y / DELTAY) - 1);
  578.    Call_CurrentDir(root -> fullname);
  579. }
  580.  
  581. int
  582. Display_Tree(struct Tree_t *root, int line, int x, int y)
  583. /* Graphically display the tree for the volume 'vol', from the line */
  584. /* line in the ccdconfig file, at coordinates x and y */
  585. /* Return the y coordinate at the end */
  586. {
  587.    int len, i;
  588.    struct RastPort *rp = mainwindow -> RPort;
  589.    int xinit = x;
  590.  
  591.    root = get_line(the_tree, line);
  592. /*
  593.    printf("For line %d, found %s\n", line, root -> name);
  594. */
  595.    while (root && y < 200) {
  596.       y += 10;
  597. #ifdef GRAPHICS
  598.       assert(rp);
  599.       Move(rp, root -> x, y);
  600.       Text(rp, root -> name, strlen(root -> name));
  601. #endif
  602.       y = Display_Tree(root -> son, line + 1, x, y);
  603.       root = root -> brother;
  604.    }
  605.    return y;
  606. }
  607.  
  608. int
  609. Create_Gadgets()
  610. /* Create the Volumes gadgets. Return the id of the first one */
  611. {
  612.    struct Tree_t *t;
  613.    struct Gadget *gad = mainwindow -> FirstGadget, *lastgadget = NULL;
  614.    struct IntuiText *tex;
  615.    int id = 1, result;
  616.    int gady = w1Gadget2.TopEdge;
  617.  
  618. /* First, transfer the gadget imageries into chip ram */
  619.    chippointer = (USHORT *)
  620.        AllocMem(sizeof(w1ImageData1), MEMF_PUBLIC | MEMF_CHIP);
  621.    if (chippointer == 0) {
  622.       printf("*** Couldn't allocate in chip mem...\n");
  623.       exit(0);
  624.    }
  625.    memcpy(chippointer, w1ImageData1, sizeof(w1ImageData1));
  626.    w1Image1.ImageData = chippointer;
  627.  
  628.    chippointer2 = (USHORT *)
  629.        AllocMem(sizeof(w1ImageData2), MEMF_PUBLIC | MEMF_CHIP);
  630.    if (chippointer2 == 0) {
  631.       printf("*** Couldn't allocate in chip mem...\n");
  632.       exit(0);
  633.    }
  634.    memcpy(chippointer2, w1ImageData2, sizeof(w1ImageData2));
  635.    w1Image2.ImageData = chippointer2;
  636.  
  637.    while (gad -> NextGadget) {
  638.       gad = gad -> NextGadget;
  639.    }
  640.    lastgadget = gad;
  641.    result = lastgadget -> GadgetID + 1;
  642.    id = result;
  643.    t = the_tree -> brother;
  644.    while (t) {
  645.  
  646. /* Dynamically create the gadget, using w1Gadget2 as template */
  647.       gad = (struct Gadget *) malloc(sizeof(*gad));
  648.       memcpy(gad, & w1Gadget2, sizeof(*gad));
  649.       gad -> TopEdge = gady;
  650.       gady += BETWEEN_GADGETS + w1Gadget2.Height;
  651.       gad -> GadgetID = id++;
  652.  
  653. /* Link the previous gadget to the one we're building up */
  654.       if (lastgadget) lastgadget -> NextGadget = gad;
  655.       lastgadget = gad;
  656.       gad -> NextGadget = NULL;
  657.  
  658. /* And now create its IntuiText structure, using w1IText1 */
  659.       tex = (struct IntuiText *) malloc(sizeof(*tex));
  660.       memcpy(tex, & w1IText1, sizeof(*tex));
  661.       tex -> IText = (char *) malloc(sizeof(t -> name) + 1);
  662.       strcpy(tex -> IText, t -> name);
  663.  
  664. /* Link the text to the gadget */
  665.       gad -> GadgetText = tex;
  666.  
  667.       nbvolumes++;
  668.       t = t -> brother;
  669.    }
  670.    return result;
  671. }
  672.  
  673. void
  674. Display_Dir(int line)
  675. /* Display the directory of the volume in the window, starting at the */
  676. /* line in the config file */
  677. {
  678.    struct Tree_t *t;
  679.    char dir[128];
  680.    struct Window *w = mainwindow;
  681.    struct Gadget *gad = NULL, *lastgadget;
  682.    struct IntuiText *tex = NULL;
  683.    int gady = w1Gadget2.TopEdge;
  684.    int id = 2;
  685.  
  686.    assert(mainwindow);
  687.  
  688. /* Warning!!! Here, I assume the 1st gadget is the scrollbar, so I */
  689. /* start from the second... */
  690.    lastgadget = w -> FirstGadget;
  691.    if (! the_tree) the_tree = Build_Tree();
  692.    dir[0] = '\0';
  693.  
  694.    actualline = 1;
  695.    SetAPen(w -> RPort, 0);
  696.    RectFill(w -> RPort, UPPERX, UPPERY + 4, WIDTH - 4, HEIGHT - 2);
  697.    SetAPen(w -> RPort, 2);
  698.    (void) Display_Tree(the_tree -> brother, line, UPPERX + DELTAX, UPPERY);
  699. }
  700.  
  701. int
  702. Locate_Vol(char *vol)
  703. /* Return first line where vol (dh0:, dh1:, ...) appears */
  704. {
  705.    struct Tree_t *t = the_tree -> brother;
  706.  
  707.    while (t && stricmp(vol, t -> name)) {
  708.       t = t -> brother;
  709.    }
  710.    if (t) return t -> line;
  711.    else assert(0);
  712. }
  713.  
  714. void
  715. Display_Window()
  716. /* Main routine for the graphic display */
  717. {
  718.    struct IntuiMessage *message;
  719.    long class, code;
  720.    int i, fin = 0;
  721.    int firstline = 1, previousline = 1;
  722.    struct Gadget *g;
  723.    struct PropInfo *info;
  724.    struct Tree_t *highlight;
  725.  
  726.    IntuitionBase = OpenLibrary("intuition.library", 0);
  727.    GfxBase = OpenLibrary("graphics.library", 0);
  728.  
  729. #ifdef GRAPHICS
  730.    mainscreen = OpenScreen(& NewScreenStructure);
  731.    LoadRGB4(&mainscreen -> ViewPort, Palette, PaletteColorCount);
  732.    w1NewWindowStructure1.Screen = mainscreen;
  733.    w1NewWindowStructure1.Title = (char *) malloc(sizeof(WINDOWTITLE));
  734.    strcpy(w1NewWindowStructure1.Title, WINDOWTITLE);
  735.    w1Gadget1.NextGadget = NULL;
  736.    mainwindow = OpenWindow(& w1NewWindowStructure1);
  737. #endif
  738.    Display_Dir(1);
  739. #ifdef GRAPHICS
  740.    volumesid = Create_Gadgets();
  741.    info = (struct PropInfo *) w1Gadget1.SpecialInfo;
  742.    info -> VertBody = (0xffff * LINESPERWINDOW) / configlines;
  743.    RefreshGadgets(mainwindow -> FirstGadget, mainwindow, NULL);
  744.  
  745.    while (! fin) {
  746.       while ((message = (struct IntuiMessage *)
  747.                            GetMsg(mainwindow -> UserPort))) {
  748.          class = message -> Class;
  749.          code = message -> Code;
  750.          ReplyMsg(message);
  751.  
  752.          switch(class) {
  753.             case CLOSEWINDOW:
  754.                fin = 1;
  755.                break;
  756.             case GADGETUP:
  757.                g = (struct Gadget *) message -> IAddress;
  758.                if (g -> GadgetID >= volumesid) {
  759.                   firstline = Locate_Vol(g -> GadgetText -> IText);
  760.                   w1w1Gadget1SInfo.VertPot = (firstline * 0xffff) / configlines;
  761.                }
  762.                else
  763.                   firstline = (configlines * w1w1Gadget1SInfo.VertPot) / 0xffff;
  764.  
  765. /* Take care of trunc problems */
  766.                if (firstline == previousline + LINESPERWINDOW + 1 ||
  767.                    firstline == previousline + LINESPERWINDOW - 1)
  768.                       firstline = previousline + LINESPERWINDOW;
  769.                else
  770.                if (firstline == previousline - LINESPERWINDOW + 1 ||
  771.                    firstline == previousline - LINESPERWINDOW - 1)
  772.                        firstline = previousline - LINESPERWINDOW;
  773.  
  774.                if (firstline == 0) firstline = 1;
  775.                if (firstline > configlines - LINESPERWINDOW - 1)
  776.                   firstline = configlines - LINESPERWINDOW - 1;
  777.                Display_Dir(firstline);
  778.                RefreshGadgets(mainwindow -> FirstGadget, mainwindow, NULL);
  779.                break;
  780.  
  781.             case GADGETDOWN:
  782.                printf("Gadgetdown, class=%d, code=%d\n", class, code);
  783.                g = (struct Gadget *) message -> IAddress;
  784.                printf("Gadgetdown, gadget id: %d\n", g -> GadgetID);
  785.                break;
  786.             case MOUSEBUTTONS:
  787.                if (message -> MouseX >= UPPERX && message -> MouseY>=UPPERY
  788.                    && code == SELECTDOWN) {
  789.                   Find_Dir_Coo(message -> MouseX, message -> MouseY, firstline);
  790.                   fin = 1;
  791.                }
  792.                break;
  793.             case MOUSEMOVE:
  794.                printf("Mousemove\n");
  795.                highlight = get_line(the_tree, firstline + (message -> MouseY / DELTAY) - 1);
  796.                SetAPen(mainwindow -> RPort, 1);
  797.                Move(mainwindow -> RPort, highlight -> x, message -> MouseY);
  798.                Text(mainwindow -> RPort, highlight -> name, strlen(highlight -> name));
  799.                break;
  800.             default:
  801.                printf("Class=%d, Code = %d\n", class, code);
  802.                break;
  803.          } /* switch class */
  804.       } /* while message */
  805.    }
  806.    if (mainwindow) CloseWindow(mainwindow);
  807.    if (mainscreen) CloseScreen(mainscreen);
  808. #endif
  809. }
  810.  
  811. int
  812. main(int argc, char **argv)
  813. {
  814.   int i = 1;
  815.  
  816.   if (argc == 1) {
  817.       Display_Window();
  818.       exit(0);
  819.   }
  820.   while (argv[i][0] == '-') {
  821.     switch(argv[i][1]) {
  822.       case 'u' :         /* update config file */
  823.         if (argc == i + 1) Usage();
  824.         update_list = 1;
  825.         break;
  826.       case 'a' :         /* show ambiguities */
  827.         if (argc == i) Usage();
  828.         show_ambiguities = 1;
  829.         break;
  830.       case 'n' :
  831.          if (argc == i) Usage();
  832.          no_expand = 1;
  833.          break;
  834.       default :
  835.          Usage();
  836.     } /* switch */
  837.     i++;
  838.   } /* while */
  839.  
  840.   if (update_list)
  841.      Update(&argv[i], argc - 2);
  842.   else if (show_ambiguities) {
  843.      printf("Ambiguities for %s\n", argv[i]);
  844.      Show_Ambiguities(argv[i]);
  845.   }
  846.   else
  847.      Change_Dir(argv[i], (argc == i + 2 ? atoi(argv[i+1]) : 1));
  848.  
  849. /*
  850.   free_all_locks();
  851. */
  852.   if (chippointer) FreeMem(chippointer, sizeof(w1ImageData1));
  853.   if (chippointer2) FreeMem(chippointer2, sizeof(w1ImageData2));
  854.   exit(0);
  855. }
  856.  
  857.