home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / UNIX / ARCHIE / CLIENTS / XARCHIE3.TAR / xarchie-2.0.1 / browser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-22  |  12.6 KB  |  519 lines

  1. /*
  2.  * browser.c : Device-independent browser routines
  3.  *
  4.  * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "stringdefs.h"
  9. #include "pfs.h"
  10. #include "db.h"
  11. #include "xtypes.h"
  12. #include "appres.h"
  13. #include "query.h"
  14. #include "actions.h"
  15. #include "browser.h"
  16. #include "selection.h"
  17. #include "display.h"
  18. #include "ftp-actions.h"
  19. #include "alert.h"
  20. #include "status.h"
  21. #include "debug.h"
  22. extern DbEntry *db;
  23.  
  24. /*
  25.  * Functions defined here:
  26.  */
  27. void resetBrowser();
  28. int paneDepth();
  29. void selectBrowserItem(),unselectBrowserItem();
  30. void displayEntries();
  31. void resortBrowser();
  32. int openBrowserAll(),openBrowserDirectories(),openBrowserFiles();
  33. void shiftBrowserDown(), shiftBrowserUp(), shiftBrowserTop();
  34. void setBrowserState();
  35. int getBrowserState();
  36.  
  37. static void clearInfoForDepth(),displayInfoForDepth();
  38. static void updateButtons(),resetParentEntries();
  39. static void openBrowserDirectory();
  40.  
  41. /*
  42.  * Data defined here:
  43.  */
  44. /*
  45.  * These are the parents of the heads of the lists being displayed in
  46.  * the browser panes.
  47.  */
  48. static DbEntry *parentEntries[MAX_DEPTH];
  49.  
  50. /*
  51.  * This is the index of the leftmost pane's contents in the previous arrays.
  52.  */
  53. static int currentRootDepth;
  54.  
  55. static int browserState;
  56.  
  57. /*    -    -    -    -    -    -    -    -    */
  58.  
  59. void
  60. resetBrowser()
  61. {
  62.     clearBrowser();
  63.     currentRootDepth = 0;
  64.     resetSelections(0);
  65.     resetParentEntries(0);
  66.     setUpSensitive(0);
  67.     setDownSensitive(0);
  68. }
  69.  
  70. int
  71. paneDepth(pane)
  72. int pane;
  73. {
  74.     return(currentRootDepth+pane);
  75. }
  76.  
  77. #ifdef DEBUG
  78. /*ARGSUSED*/
  79. static void
  80. doPrint(dbp,list_index)
  81. DbEntry dbp;
  82. int list_index;
  83. {
  84.     printf("%d ",list_index);
  85. }
  86. #endif
  87.  
  88. void
  89. selectBrowserItem(pane,item)
  90. int pane,item;
  91. {
  92.     DbEntry *dbp;
  93.     int depth;
  94.     
  95.     /* Adjust for shifted browser */
  96.     depth = paneDepth(pane);
  97. #ifdef DEBUG
  98.     fprintf(stderr,"selecting item %d, pane=%d, depth=%d\n",item,pane,depth);
  99.     fprintf(stderr,"  before: selections[] = ");
  100.     if (hasSelection(depth))
  101.     forEachSelectedItemAtDepth(depth,doPrint);
  102.     else
  103.     fprintf(stderr,"None");
  104.     fprintf(stderr,"\n");
  105. #endif
  106.     if (isSelected(depth,item)) {
  107.     DEBUG1("item %d already selected\n",item);
  108.     return;
  109.     }
  110.     dbp = findEntryFromIndex(parentEntries[depth],item);
  111.     DEBUG2("selected item is \"%s\"(%lx)\n",dbp->name,dbp);
  112.     DEBUG1("clearing parents depth >= %d\n",depth+1);
  113.     resetParentEntries(depth+1);
  114.     DEBUG1("resetting selections for depth >= %d\n",depth+1);
  115.     resetSelections(depth+1);
  116.     DEBUG3("adding selection at depth %d = \"%s\"(%lx)\n",depth,dbp->name,dbp);
  117.     addSelection(depth,dbp,item);
  118.     DEBUG3("setting parentEntries[%d] = \"%s\"(%lx)\n",depth+1,dbp->name,dbp);
  119.     parentEntries[depth+1] = dbp;
  120.     DEBUG3("displaying entry \"%s\"(%lx) in pane %d\n",dbp->name,dbp,pane);
  121.     /* Highlight the selected item */
  122.     redrawSelectionsForPane(pane);
  123.     /* Show selected info */
  124.     displayInfoForDepth(depth);
  125.     /* If we're not at the rightmost pane, then show the choices. */
  126.     if (pane < NUM_BROWSER_PANES-1) {
  127.     displayEntries(dbp,pane+1);
  128.     }
  129. #ifdef DEBUG
  130.     fprintf(stderr,"  after: selections[] = ");
  131.     if (hasSelection(depth))
  132.     forEachSelectedItemAtDepth(depth,doPrint);
  133.     else
  134.     fprintf(stderr,"None");
  135.     fprintf(stderr,"\n");
  136.     fprintf(stderr,"done selecting item\n");
  137. #endif
  138. }
  139.  
  140. void
  141. unselectBrowserItem(pane,item)
  142. int pane,item;
  143. {
  144.      int depth,i;
  145.     
  146.     /* Adjust for shifted browser */
  147.     depth = paneDepth(pane);
  148. #ifdef DEBUG
  149.     fprintf(stderr,"unselecting item %d, pane=%d, depth=%d\n",item,pane,depth);
  150.     fprintf(stderr,"  before: selections[] = ");
  151.     if (hasSelection(depth))
  152.     forEachSelectedItemAtDepth(depth,doPrint);
  153.     else
  154.     fprintf(stderr,"None");
  155.     fprintf(stderr,"\n");
  156. #endif
  157.     unhighlightBrowserItem(pane,item);
  158.     /* Clear all panes below this one */
  159.     for (i=NUM_BROWSER_PANES-1; i > pane; i--)
  160.     clearBrowserPane(i);
  161.     /* Clear all info including this one since de-selected */
  162.     clearInfoForDepth(depth);
  163.     DEBUG2("removing selection at depth %d = item %d\n",depth,item);
  164.     removeSelection(depth,NULL,item);
  165.     DEBUG1("clearing parents depth >= %d\n",depth+1);
  166.     resetParentEntries(depth+1);
  167. #ifdef DEBUG
  168.     printf("  after: selections[] = ");
  169.     if (hasSelection(depth))
  170.     forEachSelectedItemAtDepth(depth,doPrint);
  171.     else
  172.     printf("None");
  173.     printf("\n");
  174.     fprintf(stderr,"done deselecting item\n");
  175. #endif
  176. }
  177.  
  178. static void
  179. clearInfoForDepth(depth)
  180. int depth;
  181. {
  182.     switch (depth) {
  183.     case 0:    setHostText("");
  184.         /* fall through */
  185.     case 1:    setLocationText("");
  186.         /* fall through */
  187.     case 2:    setFileText("");
  188.         setSizeText("");
  189.         setModesText("");
  190.         setDateText("");
  191.         break;
  192.     }
  193.     DEBUG1("cleared info for depth %d\n",depth);
  194. }
  195.  
  196. static void
  197. displayInfoForDepth(depth)
  198. int depth;
  199. {
  200.     SelectedItem *item;
  201.     char buf[MAX_VPATH];
  202.     int i;
  203.  
  204.     DEBUG1("  display info for depth %d:\n",depth);
  205.     if ((item=getSelection(0)) != NULL) {
  206.     setHostText(item->entry->name);
  207.     DEBUG1("    host: \"%s\"\n",item->entry->name);
  208.     }
  209.     /* Special case if location was selected */
  210.     if (depth == 1) {
  211.     if ((item=getSelection(1)) != NULL) {
  212.         setLocationText(item->entry->name);
  213.         DEBUG1("    loc: \"%s\"\n",item->entry->name);
  214.     }
  215.     } else {    /* Otherwise normal case, get location and file */
  216.     strcpy(buf,"");
  217.     for (i=1; i < depth; i++)
  218.         if ((item=getSelection(i)) != NULL) {
  219.         (void)strcat(buf,item->entry->name);
  220.         if (i < depth-1 &&
  221.             buf[strlen(buf)-1] != '/')
  222.             strcat(buf,"/");
  223.         }
  224.     setLocationText(buf);
  225.     DEBUG1("    loc: \"%s\"\n",buf);
  226.     if ((item=getSelection(depth)) != NULL) {
  227.         setFileText(item->entry->name);
  228. #ifdef MSDOS
  229.         sprintf(buf,"%lu",item->entry->size);
  230. #else
  231.         sprintf(buf,"%d",item->entry->size);
  232. #endif
  233.         setSizeText(buf);
  234.         setModesText(item->entry->modes);
  235.         setDateText(item->entry->date);
  236.         DEBUG1("    file: \"%s\"\n",item->entry->name);
  237.     }
  238.     }
  239. }
  240.  
  241. void
  242. displayEntries(parent,pane)
  243. DbEntry *parent;
  244. int pane;
  245. {
  246.     DbEntry *dbp;
  247.     SelectedItem *sel;
  248.     int i,depth;
  249.  
  250.     depth = paneDepth(pane);
  251.     if (parent == NULL) {
  252.     fprintf(stderr,"DB error: attempt to display entries from NULL list");
  253.     return;
  254.     }
  255.     DEBUG3("displaying parent \"%s\" in pane %d (depth %d)\n",
  256.        (parent?parent->name:"<NIL>"),pane,depth);
  257.     /* Clear this and all subordinate panes */
  258.     for (i=pane; i < NUM_BROWSER_PANES; i++) {
  259.     DEBUG1("  clearing pane %d\n",i);
  260.     clearBrowserPane(i);
  261.     }
  262.     /* Set the strings to be displayed in this pane */
  263.     for (i=0, dbp=parent->entries; dbp != NULL; dbp=dbp->next) {
  264.     DEBUG2("  item %d: \"%s\"\n",i,dbp->name);
  265.     setBrowserItem(pane,i++,dbp->name);
  266.     }
  267.     /* If there's anything to display, display it */
  268.     if (i > 0)
  269.     redrawBrowserPane(pane);
  270.     /* If there's only one thing then select it */
  271.     if (i == 1) {
  272.     DEBUG0("  solo -> select\n");
  273.     addSelection(depth,parent->entries,0);
  274.     }
  275.     /* If there's something selected (either because we just selected the
  276.        only thing or because we're scrolling left), then redo the
  277.        highlighting and display the correct info. If we're not at the
  278.        rightmost pane, then recusively draw the next pane. */
  279.     if ((sel=getSelection(depth)) != NULL) {
  280.     redrawSelectionsForPane(pane);
  281.     displayInfoForDepth(depth);
  282.     if (pane < NUM_BROWSER_PANES - 1)
  283.         displayEntries(sel->entry,pane+1);
  284.     } else {
  285.     /* Otherwise there's nothing selected here */
  286.     clearInfoForDepth(depth);
  287.     }
  288.     /* Save which list is being displayed in the pane */
  289.     parentEntries[paneDepth(pane)] = parent;
  290.     /* Get the shift buttons right */
  291.     updateButtons();
  292. }
  293.  
  294. static void
  295. updateButtons()
  296. {
  297.     SelectedItem *sel;
  298.  
  299.     setUpSensitive(currentRootDepth > 0);
  300.     if ((sel=getSelection(currentRootDepth+NUM_BROWSER_PANES-1)) != NULL &&
  301.     sel->entry->entries != NULL)
  302.     setDownSensitive(1);
  303.     else
  304.     setDownSensitive(0);
  305. }
  306.  
  307. static void
  308. resetParentEntries(first)
  309. int first;
  310. {
  311.     int i;
  312.  
  313.     for (i=first; i < MAX_DEPTH; i++)
  314.     parentEntries[i] = NULL;
  315. }
  316.  
  317. /*    -    -    -    -    -    -    -    -    */
  318. /* Resort the browser based on the appResources */
  319.  
  320. void
  321. resortBrowser()
  322. {
  323.     /* Reset browser to leftmost position */
  324.     DEBUG0("resortBrowser: resetting browser\n");
  325.     resetBrowser();
  326.     DEBUG0("resortBrowser: sorting entries\n");
  327.     switch(appResources.sortType) {
  328.     case GfName:
  329.         sortEntriesRecursively(db,cmpEntryNames);
  330.         break;
  331.     case GfDate:
  332.         sortEntriesRecursively(db,cmpEntryDates);
  333.         break;
  334.     case GfWeight:
  335.         sortEntriesRecursively(db,cmpEntryWeights);
  336.         break;
  337.     }
  338.     /* Display results in browser */
  339.     DEBUG0("resortBrowser: displaying entries\n");
  340.     displayEntries(db,0);
  341.     DEBUG0("resortBrowser: done\n");
  342. }
  343.  
  344. /*    -    -    -    -    -    -    -    -    */
  345. /* Routines to open (ie. expand) the browser */
  346.  
  347. static int numOpened;
  348.  
  349. /*
  350.  * Open any selected items in the browser. Return the number of items
  351.  * that were successfully opened.
  352.  */
  353. int
  354. openBrowserAll()
  355. {
  356.     DEBUG1("openBrowserAll: depth = %d\n",currentRootDepth);
  357.     if (!hasSelection(NUM_BROWSER_PANES-1)) {
  358.     alert0("You must select something to open.");
  359.     return(0);
  360.     }
  361.     numOpened = 0;
  362.     /* Do the directories */
  363.     forEachSelectedItem(openBrowserDirectory);
  364.     /* Do the files */
  365.     ftpOpenSelectedItems();
  366.     status0("Ready");
  367.     DEBUG1("done openBrowserAll, returning %d\n",numOpened);
  368.     return(numOpened);
  369. }
  370.  
  371. int
  372. openBrowserDirectories()
  373. {
  374.     DEBUG1("openBrowserDirectories: depth = %d\n",currentRootDepth);
  375.     if (!hasSelection(2)) {
  376.     alert0("You must select a directory to open.");
  377.     return(0);
  378.     }
  379.     numOpened = 0;
  380.     forEachSelectedItem(openBrowserDirectory);
  381.     status0("Ready");
  382.     DEBUG1("done openBrowserDirectories, returning %d\n",numOpened);
  383.     return(numOpened);
  384. }
  385.  
  386. int
  387. openBrowserFiles()
  388. {
  389.     DEBUG1("openBrowserFiles: depth = %d\n",currentRootDepth);
  390.     if (!hasSelection(2)) {
  391.     alert0("You must select a file to open.");
  392.     return(0);
  393.     }
  394.     numOpened = 0;
  395.     ftpOpenSelectedItems();
  396.     status0("Ready");
  397.     DEBUG1("done openBrowserFiles, returning %d\n",numOpened);
  398.     return(numOpened);
  399. }
  400.  
  401. /*
  402.  * Open a selected item. Ignore any selections that aren't directories.
  403.  */
  404. /*ARGSUSED*/
  405. static void
  406. openBrowserDirectory(dbp,list_index)
  407. DbEntry *dbp;
  408. int list_index;
  409. {
  410.     VLINK vl,links;
  411.  
  412.     DEBUG1("openBrowserDirectory: \"%s\"\n",dbp->name);
  413.     if (dbp->type != DB_DIRECTORY)
  414.     return;
  415.     if (dbp->entries == NULL) {
  416.     /* It's not been expanded already... */
  417.     if ((vl=dbp->vlink) == NULL) {
  418.         alert0("ERROR: NULL vlink to openBrowserDirectory!");
  419.         return;
  420.     }
  421.     /* Disable querying */
  422.     setBrowserState(BROWSER_DIRSEND);
  423.     DEBUG1("getting entries for \"%s\"\n",dbp->name);
  424.     links = stringQuery(vl->host,vl->filename);
  425.     DEBUG0("calling handleProsperoErrors\n");
  426.     (void)handleProsperoErrors();
  427.     if (links != NULL)
  428.         numOpened += 1;
  429. #ifdef DEBUG
  430.     fprintf(stderr,"unprocessed results of stringQuery:\n");
  431.     for (vl=links; vl != NULL; vl=vl->next)
  432.         fprintf(stderr,"  \"%s\"\n",vl->filename);
  433.     fprintf(stderr,"calling parseStringQueryResults\n");
  434. #endif
  435.     /* Process the results into the database */
  436.     switch(appResources.sortType) {
  437.         case GfName:
  438.         (void)parseStringQueryResults(dbp,links,cmpEntryNames);
  439.         break;
  440.         case GfDate:
  441.         (void)parseStringQueryResults(dbp,links,cmpEntryDates);
  442.         break;
  443.         case GfWeight:
  444.         (void)parseStringQueryResults(dbp,links,cmpEntryWeights);
  445.         break;
  446.     }
  447.     /* Re-enable querying */
  448.     setBrowserState(BROWSER_READY);
  449.     }
  450.     DEBUG0("done openBrowserDirectory\n");
  451. }
  452.  
  453. /*    -    -    -    -    -    -    -    -    */
  454. /* Routines for shifting the browser up, down, top. */
  455.  
  456. void
  457. shiftBrowserDown()
  458. {
  459.     DEBUG1("doing shiftDown, depth = %d\n",currentRootDepth);
  460.     if (currentRootDepth >= MAX_DEPTH-1) {
  461.     alert1("Browser only goes %d levels deep!",(char *)MAX_DEPTH);
  462.     return;
  463.     }
  464.     if (parentEntries[currentRootDepth+1] == NULL) {
  465.     alert0("Nothing to display below!");
  466.     return;
  467.     }
  468.     currentRootDepth += 1;
  469.     DEBUG1("currentRootDepth is now %d\n",currentRootDepth);
  470.     displayEntries(parentEntries[currentRootDepth],0);
  471.     DEBUG0("done shiftDown\n");
  472. }
  473.  
  474. void
  475. shiftBrowserUp()
  476. {
  477.     DEBUG1("doing shiftUp, depth = %d\n",currentRootDepth);
  478.     if (currentRootDepth == 0) {
  479.     beep();
  480.     return;
  481.     }
  482.     currentRootDepth -= 1;
  483.     DEBUG1("currentRootDepth is now %d\n",currentRootDepth);
  484.     displayEntries(parentEntries[currentRootDepth],0);
  485.     DEBUG0("done shiftUp\n");
  486. }
  487.  
  488. void
  489. shiftBrowserTop()
  490. {
  491.     DEBUG1("doing shiftTop, depth = %d\n",currentRootDepth);
  492.     currentRootDepth = 0;
  493.     DEBUG1("currentRootDepth is now %d\n",currentRootDepth);
  494.     displayEntries(db,0);
  495.     DEBUG0("done shiftTop\n");
  496. }
  497.  
  498. /*    -    -    -    -    -    -    -    -    */
  499. /* Routines for getting/setting the state of the browser */
  500. /*
  501.  * Non-zero state => busy
  502.  */
  503.  
  504. void
  505. setBrowserState(state)
  506. int state;
  507. {
  508.     setQuerySensitive(state == BROWSER_READY);
  509.     setAbortSensitive(state != BROWSER_READY);
  510.     browserState = state;
  511. }
  512.  
  513. int
  514. getBrowserState()
  515. {
  516.     return(browserState);
  517. }
  518.  
  519.