home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / alt / toolkits / xview / 1166 < prev    next >
Encoding:
Text File  |  1992-12-31  |  11.9 KB  |  506 lines

  1. Path: sparky!uunet!cs.utexas.edu!news
  2. From: cpg@cs.utexas.edu (Carlos M. Puchol)
  3. Newsgroups: alt.toolkits.xview
  4. Subject: Re: HELP! Find all files of a directory in Xview
  5. Date: 31 Dec 1992 11:29:44 -0600
  6. Organization: Department of Computer Sciences, UT Austin
  7. Lines: 494
  8. Message-ID: <lk6bg8INN6ks@thor.cs.utexas.edu>
  9. References: <lk0avrINN228@thor.cs.utexas.edu> <RICKG.92Dec29084107@irondude.eng.sun.com> <hue.725789508@coney>
  10. NNTP-Posting-Host: thor.cs.utexas.edu
  11.  
  12. In article <hue.725789508@coney> hue@island.COM (Pond Scum) writes:
  13. >rickg@eng.sun.com (The Tankster) writes:
  14. >>according to the SunSoft toolkit strategy annoncement that
  15. >>appeared awhile back, the XView toolkit itself will eventually
  16. >>contain such an object.  i guess it depends on when you need it...
  17. >
  18. >Here in the Graphic Arts Division of Island Graphics we have at least
  19. >four different file requesters (fortunately they are in four separate
  20. >applications, not all in the same one).  I needed one and didn't find one
  21.  
  22. ...
  23.  
  24. >So a month ago I decided to write the "ultimate file requester" which would
  25. >hopefully make everyone here happy.  The main goal was to make it easy
  26. >to use, and not force anyone into buying into my particular style of
  27. >programming or force them to carry a lot of baggage around, so I did
  28. >it as an XView extension.  Also, I wanted to emulate the behavior of
  29.  
  30. Well, sounds pretty nice to me. Judging from the name of the uuencoded file,
  31. it is a snapshot of your "ultimate file requester". Are you going to contribute
  32. your code to the net :-)
  33.  
  34. BTW, the code I posted had a minor error. I have fixed it and I had intorduced
  35. sorting for the file & direcotry names (There wasn't at the beginning!).
  36. Now it also remembers the CWD from invocation to invocation.
  37.  
  38. Help yourself.
  39.  
  40. -- Carlos
  41.  
  42. /*
  43.  *      XGed : Graph Editor for the X Window System
  44.  *
  45.  *      Carlos Puchol (cpg@cs.utexas.edu)
  46.  *
  47.  *    This file is public domain. Do with it what you please.
  48.  *    I am not to be held responsible for any damage caused by the use of this
  49.  *    code. I would appreciate if you quote the authors, if you use this code.
  50.  *
  51.  *      %W%     %G%
  52.  */
  53.  
  54. /*************************************************************************\
  55.  *                                                                       *
  56.  * FILE: dir_list.c                                                      *
  57.  *                                                                       *
  58.  * EXPORTED ROUTINES:                                                    *
  59.  *                                                                       *
  60.  * - get_filename_popup(char *label, void (*action)())                   *
  61.  *                                                                       *
  62.  *     This procedure creates two scrolling lists, one with directories  *
  63.  *     and one with files.  It allows the user to search through         *
  64.  *     directories for files and then select a file. The label is        *
  65.  *     attached to the frame and the actual button "ok" button.          *
  66.  *                                                                       *
  67.  *     The procedure "action" will be called when the button is pressed  *
  68.  *     or <cr> is pressed in the "file" line. It will be called with     *
  69.  *     the absolute file name of the selected file.                      *
  70.  *                                                                       *
  71.  *     The popup window will remember the "current" directory from       *
  72.  *     invocation to invocation.                                         *
  73.  *                                                                       *
  74.  * - destroy_filename_frame()                                            *
  75.  *                                                                       *
  76.  *     You can guess what it does!                                       *
  77.  *                                                                       *
  78. \*************************************************************************/
  79.  
  80. #include <stdio.h>
  81. #include <stdlib.h>
  82. #include <xview/xview.h>
  83. #include <xview/panel.h>
  84. #include <dirent.h>
  85. #include <sys/stat.h>
  86. #include <sys/types.h>
  87. #include <sys/param.h>
  88. #include <xvged_objects.h>
  89.  
  90. #define DESELECT 0
  91. #define SELECT 1
  92. #define ENTRY_KEY 5877
  93. #define NULL_STR ""
  94.  
  95. static Frame frame;
  96. static Panel panel;
  97. static Panel_item pi_dir, pi_file, ti_file, mi_dir, bi_open;
  98. static DIR *dirp;
  99. static struct dirent *entry;
  100. static char *current;
  101.  
  102. static int num_files, num_dirs;
  103. static void (*action_to_call)();
  104.  
  105. static int Action ();
  106. static int Cancel ();
  107. static void setup_list ();
  108. static void dir_proc ();
  109. static void file_proc ();
  110. static int check_read ();
  111. static void create_frame();
  112.  
  113. void  destroy_filename_frame()
  114. {
  115.     xv_destroy_safe (frame);
  116. }
  117.  
  118. void get_filename_popup(label, action)
  119. char    *label;
  120. void    (*action)();
  121. {
  122.     static char initial[MAXPATHLEN]={'\0'};
  123.  
  124.     if (initial[0]=='\0') {
  125.         getwd(initial);
  126.         current = (char *) malloc (strlen (initial) + 1);
  127.         memset (current, '\0', strlen (initial) + 1);
  128.         strcat (current, initial);
  129.         create_frame();
  130.     }
  131.     xv_set(bi_open, PANEL_LABEL_STRING, label, NULL);
  132.     xv_set(frame, FRAME_LABEL, label, NULL);
  133.  
  134. /*    xv_set(frame, FRAME_LABEL, label, NULL); */
  135.  
  136.     action_to_call=action;
  137.  
  138.     if (check_read (current, NULL_STR))
  139.         setup_list ();
  140.  
  141.     xv_set(frame, XV_SHOW, TRUE, NULL);
  142.  
  143. }
  144.  
  145. static void create_frame()
  146. {
  147.  
  148.     frame = (Frame) xv_create (NULL, FRAME,
  149.                    FRAME_LABEL, "File Open",
  150.                    NULL);
  151.  
  152.     panel = (Panel) xv_create (frame, PANEL, NULL);
  153.  
  154.     mi_dir = (Panel_item) xv_create (panel, PANEL_MESSAGE,
  155.                      PANEL_LABEL_STRING, current,
  156.                      PANEL_LABEL_BOLD, TRUE,
  157.                      XV_X, 20,
  158.                      XV_Y, 20,
  159.                      NULL);
  160.  
  161.     ti_file = (Panel_item) xv_create (panel, PANEL_TEXT,
  162.                       PANEL_LABEL_STRING, "File:",
  163.                       PANEL_VALUE_DISPLAY_LENGTH, 50,
  164.                       PANEL_VALUE_STORED_LENGTH, 256,
  165.                       PANEL_NEXT_ROW, -1,
  166.                       PANEL_VALUE, NULL_STR,
  167.                       PANEL_NOTIFY_PROC, Action,
  168.                       NULL);
  169.  
  170.     pi_dir = (Panel_item) xv_create (panel, PANEL_LIST,
  171.                      PANEL_LABEL_STRING, "Directories:",
  172.                      PANEL_LIST_DISPLAY_ROWS, 10,
  173.                      PANEL_CHOOSE_ONE, TRUE,
  174.                      PANEL_CHOOSE_NONE, TRUE,
  175.                      PANEL_READ_ONLY, TRUE,
  176.                      PANEL_NOTIFY_PROC, dir_proc,
  177.                      PANEL_NEXT_ROW, -1,
  178.                      PANEL_LIST_WIDTH, 150,
  179.                      PANEL_LAYOUT, PANEL_VERTICAL,
  180.                      NULL);
  181.  
  182.     pi_file = (Panel_item) xv_create (panel, PANEL_LIST,
  183.                       PANEL_LABEL_STRING, "Files:",
  184.                       PANEL_LIST_DISPLAY_ROWS, 10,
  185.                       PANEL_CHOOSE_ONE, TRUE,
  186.                       PANEL_CHOOSE_NONE, TRUE,
  187.                       PANEL_READ_ONLY, TRUE,
  188.                       PANEL_NOTIFY_PROC, file_proc,
  189.                       PANEL_LIST_WIDTH, 150,
  190.                       PANEL_LAYOUT, PANEL_VERTICAL,
  191.                       NULL);
  192.  
  193.     bi_open = (Panel_item) xv_create (panel, PANEL_BUTTON,
  194.                       PANEL_LABEL_STRING, "Open",
  195.                       PANEL_NOTIFY_PROC, Action,
  196.                       XV_X, 370,
  197.                       XV_Y, 73,
  198.                       NULL);
  199.  
  200.     (void) xv_create (panel, PANEL_BUTTON,
  201.               PANEL_LABEL_STRING, "Cancel",
  202.               PANEL_NOTIFY_PROC, Cancel,
  203.               XV_X, 367,
  204.               XV_Y, 103,
  205.               NULL);
  206.  
  207.     window_fit (panel);
  208.     window_fit (frame);
  209.  
  210. }
  211.  
  212.  
  213. /*
  214.  * Re-read the directory entries for the scrolling lists
  215.  */
  216.  
  217. static void setup_list ()
  218. {
  219.     char *tmpname;
  220.     int i;
  221.  
  222.     xv_set (ti_file,
  223.         PANEL_VALUE, NULL_STR,
  224.         NULL);
  225.  
  226.     xv_set (bi_open,
  227.         XV_SHOW, FALSE,
  228.         NULL);
  229.  
  230.     xv_set (mi_dir,
  231.         PANEL_LABEL_STRING, current,
  232.         NULL);
  233.  
  234. /*
  235.  * Hide the scroll lists while re-computing the lists.  Saves on re-draw
  236.  * time.
  237.  */
  238.  
  239.     xv_set (pi_dir,
  240.         XV_SHOW, FALSE,
  241.         NULL);
  242.  
  243.     xv_set (pi_file,
  244.         XV_SHOW, FALSE,
  245.         NULL);
  246.  
  247. /*
  248.  * First delete the old entries
  249.  */
  250.  
  251.     for (i = num_dirs - 1; i >= 0; i--)
  252.         xv_set (pi_dir, PANEL_LIST_DELETE, i, NULL);
  253.  
  254.     for (i = num_files - 1; i >= 0; i--)
  255.         xv_set (pi_file, PANEL_LIST_DELETE, i, NULL);
  256.  
  257.     num_files = 0;
  258.     num_dirs = 0;
  259. /*
  260.  * Now read the new entries
  261.  */
  262.     dirp = opendir (current);
  263.  
  264.     while ((entry = readdir (dirp)) != NULL) {
  265.         tmpname = (char *) malloc (strlen (current) + entry->d_namlen + 2);
  266.         memset (tmpname, '\0', strlen (current) + entry->d_namlen + 2);
  267.         strcat (tmpname, current);
  268.         strcat (tmpname, "/");
  269.         strcat (tmpname, entry->d_name);
  270.         if (dir_test (tmpname)) {
  271. /*
  272.  * A directory
  273.  */
  274.             if (strcmp (entry->d_name, ".")) {
  275.                 for (i=0; i < num_dirs; i++) {
  276.                     if (0 > strcmp (entry->d_name,
  277.                         xv_get (pi_dir, PANEL_LIST_STRING,
  278.                             i, NULL, NULL)))
  279.                     break;
  280.                 }
  281.                 xv_set (pi_dir,
  282.                     PANEL_LIST_INSERT, i,
  283.                     PANEL_LIST_STRING, i, entry->d_name,
  284.                     NULL);
  285.                 num_dirs++;
  286.             }
  287.         }
  288.         else {
  289. /*
  290.  * A file
  291.  */
  292.             if (strncmp (entry->d_name, ".", 1)) {
  293.                 for (i=0; i < num_files; i++) {
  294.                     if (0 > strcmp (entry->d_name,
  295.                         xv_get (pi_file, PANEL_LIST_STRING,
  296.                             i, NULL, NULL)))
  297.                     break;
  298.                 }
  299.                 xv_set (pi_file,
  300.                     PANEL_LIST_INSERT, i,
  301.                     PANEL_LIST_STRING, i, entry->d_name,
  302.                     NULL);
  303.                 num_files++;
  304.             }
  305.         }
  306.         free (tmpname);
  307.     }
  308.  
  309. /*
  310.  * Done, show the new scroll panels
  311.  */
  312.  
  313.     xv_set (pi_dir,
  314.         XV_SHOW, TRUE,
  315.         NULL);
  316.     xv_set (pi_file,
  317.         XV_SHOW, TRUE,
  318.         NULL);
  319.  
  320.     closedir (dirp);
  321. }
  322.  
  323.  
  324. /*
  325.  * Handle the selection of a directory entry in the scroll list
  326.  */
  327.  
  328. static void dir_proc (item, string, client_data, op, event)
  329.      Panel_item item;
  330.      char *string;
  331.      caddr_t client_data;
  332.      Panel_list_op op;
  333.      Event *event;
  334.  
  335. {
  336.     char *oldcurrent;
  337.     int i;
  338.  
  339. /*
  340.  * Make sure the user selected and didn't drag.  Dragging may cause unwanted
  341.  * changes
  342.  */
  343.  
  344. /*
  345.  * Make sure we can read the directory before making any changes
  346.  */
  347.  
  348.     if (op == SELECT && event_id (event) != LOC_DRAG &&
  349.         check_read (current, string)) {
  350.  
  351.         oldcurrent = (char *) malloc (strlen (current) + 1);
  352.         memset (oldcurrent, '\0', strlen (current) + 1);
  353.         strcat (oldcurrent, current);
  354.         free (current);
  355.  
  356.         if (strcmp (string, "..")) {
  357.  
  358. /*
  359.  * Add the new directory to the "current" directory string
  360.  */
  361.  
  362.             current = (char *) malloc (strlen (oldcurrent) + strlen (string) + 2);
  363.             memset (current, '\0', strlen (oldcurrent) + strlen (string) + 2);
  364.             strcat (current, oldcurrent);
  365.             if (strlen (oldcurrent) > 1)
  366.                 strcat (current, "/");
  367.             strcat (current, string);
  368.         }
  369.         else {
  370.  
  371. /*
  372.  * Go back one directory
  373.  */
  374.  
  375.             i = strlen (oldcurrent);
  376.  
  377.             while (oldcurrent[i] != '/') {
  378.                 oldcurrent[i] = '\0';
  379.                 i--;
  380.             }
  381.  
  382. /*
  383.  * Tried to go back from the root directory?
  384.  */
  385.  
  386.             if (i < 1) {
  387.                 oldcurrent[0] = '/';
  388.                 oldcurrent[1] = '\0';
  389.                 i = 1;
  390.             }
  391.             else
  392.                 oldcurrent[i] = '\0';
  393.  
  394.             current = (char *) malloc (i);
  395.             memset (current, '\0', i);
  396.             strcat (current, oldcurrent);
  397.         }
  398.  
  399.         free (oldcurrent);
  400.  
  401.         setup_list ();
  402.     }
  403. }
  404.  
  405.  
  406. /*
  407.  * Handle a selection on the file list
  408.  */
  409.  
  410. static void file_proc (item, string, client_data, op, event)
  411.      Panel_item item;
  412.      char *string;
  413.      caddr_t client_data;
  414.      Panel_list_op op;
  415.      Event *event;
  416.  
  417. {
  418.     if (op == SELECT) {
  419.         xv_set (ti_file,
  420.             PANEL_VALUE, string,
  421.             NULL);
  422.         xv_set (bi_open,
  423.             XV_SHOW, TRUE,
  424.             NULL);
  425.     }
  426.     else if (op == DESELECT) {
  427.         xv_set (ti_file,
  428.             PANEL_VALUE, NULL_STR,
  429.             NULL);
  430.         xv_set (bi_open,
  431.             XV_SHOW, FALSE,
  432.             NULL);
  433.     }
  434. }
  435.  
  436.  
  437. /*
  438.  * Acknowledge an Action button press
  439.  */
  440.  
  441. static int Action (item, event)
  442.      Panel_item item;
  443.      Event *event;
  444.  
  445. {
  446.     if (strcmp (NULL_STR, (char *) xv_get (ti_file, PANEL_VALUE))) {
  447.         xv_set (frame, XV_SHOW, FALSE, NULL);
  448.         xv_set (XGedObjects.BaseFrame, FRAME_BUSY, TRUE, NULL);
  449.         (*action_to_call)(xv_get (ti_file, PANEL_VALUE));
  450.         xv_set (XGedObjects.BaseFrame, FRAME_BUSY, FALSE, NULL);
  451.     }
  452. }
  453.  
  454. static int Cancel (item, event)
  455.      Panel_item item;
  456.      Event *event;
  457.  
  458. {
  459.     xv_set (frame, XV_SHOW, FALSE, NULL);
  460. }
  461.  
  462.  
  463. /*
  464.  * This routine tests to see if a file name is a directory entry
  465.  */
  466.  
  467. static dir_test (filename)
  468.      char *filename;
  469.  
  470. {
  471.     struct stat statbuf;
  472.  
  473.     stat (filename, &statbuf);
  474.     return (S_ISDIR (statbuf.st_mode));
  475. }
  476.  
  477.  
  478. /*
  479.  * Check to see if the directory is readable
  480.  */
  481.  
  482. static int check_read (oldpath, newdir)
  483.      char *oldpath, *newdir;
  484.  
  485. {
  486.     char *both;
  487.     DIR *test_open;
  488.  
  489.     both = (char *) malloc (strlen (oldpath) + strlen (newdir) + 2);
  490.     memset (both, '\0', strlen (oldpath) + strlen (newdir) + 2);
  491.     strcat (both, oldpath);
  492.     strcat (both, "/");
  493.     strcat (both, newdir);
  494.  
  495.     if (!(test_open = opendir (both))) {
  496.         free (both);
  497.         return 0;
  498.     }
  499.     else {
  500.         free (both);
  501.         closedir (test_open);
  502.         return 1;
  503.     }
  504. }
  505.  
  506.