home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume15 / xmail / part04 / directory.c < prev   
C/C++ Source or Header  |  1991-10-29  |  8KB  |  227 lines

  1. /*
  2.  * xmail - X window system interface to the mail program
  3.  *
  4.  * Copyright 1990,1991 by National Semiconductor Corporation
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of National Semiconductor Corporation not
  11.  * be used in advertising or publicity pertaining to distribution of the
  12.  * software without specific, written prior permission.
  13.  *
  14.  * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  15.  * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  16.  * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  17.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  18.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  19.  * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  20.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  21.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  22.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  23.  * PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  26.  *
  27.  */
  28.  
  29.  
  30. #include "global.h"
  31. #include <sys/stat.h>
  32.  
  33. #ifndef    S_ISDIR
  34. #define    S_ISDIR(m)    (((m)&S_IFMT) == S_IFDIR)
  35. #endif
  36.  
  37. #ifdef mips
  38. #include <stdlib.h>
  39. #endif
  40.  
  41. #ifdef USE_DIRENT
  42. #include <dirent.h>
  43. #else
  44. #include <sys/dir.h>
  45. #endif
  46.  
  47.  
  48. /*
  49. ** @(#)SetDirectory() - Create popup list of directory folder names
  50. */
  51. /* ARGSUSED */
  52. XtActionProc
  53. SetDirectory(w, event, params, num_params)
  54. Widget        w;
  55. XEvent        *event;
  56. String        *params;
  57. Cardinal    *num_params;
  58. {
  59.  Arg        args[7];
  60.  Cardinal    label_width, path_length, n, depth, x;
  61.  int        total;
  62.  DIR        *dirp;
  63.  String        name, path;
  64.  Widget        menu, layout, bw, above, to_left;
  65.  char        *s, *List, **ftbl, trans[BUFSIZ], tmp[BUFSIZ];
  66.  struct    stat    st_buf;
  67.  
  68. #ifdef USE_DIRENT
  69.  struct dirent    *dp;
  70. #else
  71.  struct direct    *dp;
  72. #endif
  73.  
  74.  static String dir_Trans =
  75.     "<Btn1Down>: SetDirectory(%s, %s, %d)";
  76.  
  77.  static String m_Trans = "<LeaveWindow>:    MenuPopdown(%s)";
  78.  
  79.  static String b_Trans = "<EnterWindow>:    set() \n\
  80.               <LeaveWindow>:    unset() \n\
  81.               <Btn3Up>:        MyNotify(%d) MenuPopdown(%s)";
  82.  
  83.  static XtCallbackRec callbacks[] = {
  84.         { (XtCallbackProc) GetFolderName, NULL },
  85.         { NULL,          NULL }
  86.        };
  87.  
  88.  
  89.  name = params[0];
  90.  path = params[1];
  91.  path_length = strlen(path);
  92.  (void) sscanf(params[2], "%d", &depth);
  93.  depth++;
  94.  label_width = 0;
  95.  
  96.  for (s = name; *s; s++)
  97.      /*
  98.      ** To avoid problems later on with XtNameToWidget, don't create a
  99.      ** menu if the name contains either a dot (.) or an asterisk (*).
  100.      */
  101.      if (strchr(".*", *s)) break;
  102.  
  103.  if (! (*s && XtNameToWidget(w, name))) {
  104.     SetCursor(WATCH);
  105.     (void) sprintf(trans, m_Trans, name);
  106.     XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(trans));
  107.     menu = XtCreatePopupShell(name, overrideShellWidgetClass, w, args, ONE);
  108.  
  109.     XtSetArg(args[0], XtNdefaultDistance, 1);
  110.     layout = XtCreateManagedWidget("menu", formWidgetClass, menu, args, ONE);
  111.  
  112.     if ((dirp = opendir(path)) == NULL)
  113.        XtError("xmail cannot access passed directory name in SetDirectory()");
  114. /*
  115. ** Copy folder names into a list
  116. */
  117.     n = BUFSIZ;
  118.     List = XtMalloc((unsigned) n);        /* start with a BUFSIZ block */
  119.     List[0] = '\0';
  120.     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
  121.         if (dp->d_name[0] != '.') {        /* skip parent and dot files */
  122.            if (strlen(List) + strlen(dp->d_name) + 2 > n) {
  123.               n += BUFSIZ;
  124.               List = XtRealloc(List, (unsigned) n);
  125.              }
  126.            if (*List) (void) strcat(List, " ");
  127.            (void) strcat(List, dp->d_name);
  128.           }
  129.     List = XtRealloc(List, (unsigned) strlen(List) + 1);
  130.     (void) closedir(dirp);
  131. /*
  132. ** Store pointers to folder names in a table array for sorting
  133. */
  134.     if (List[0]) {            /* if directory isn't empty... */
  135.        for (total=1, s=List; *s; s++)    /* count number of names in the List */
  136.            if (*s == ' ') total++;    /* (increase the folder name count) */
  137.        ftbl = (char **) XtMalloc((unsigned) total * sizeof(char *));
  138.        x = n = 0;
  139.        for (s = List; *s; s++) {    /* stuff word pointers into a table */
  140.            while (*(s+n) && *(s+n) != ' ') n++;
  141.            if (*(s+n)) *(s+n) = '\0';    /* mark off the end of this name */
  142.            ftbl[x++] = s;        /* save this pointer in our table */
  143.            s += n;            /* find start of next folder name */
  144.            n  = 0;
  145.           }
  146. /*
  147. ** (quick) sort our table into ascending alphabetical order
  148. */
  149.        qsort((char *)ftbl, total, sizeof(char *), str_compare);
  150. /*
  151. ** Next, determine proper label width by finding longest word in our table
  152. */
  153.        for (x = n = 0; n < total; n++) {
  154.            if (strlen(ftbl[n]) > strlen(ftbl[x])) x = n;
  155.           }
  156.  
  157.        label_width = XTextWidth(XMail.buttonFont, ftbl[x], strlen(ftbl[x]));
  158.       }
  159.  
  160.     if (label_width) {
  161.        (void) sprintf(trans, b_Trans, depth, name);
  162.  
  163.        XtSetArg(args[0], XtNwidth, label_width + 12);
  164.        XtSetArg(args[1], XtNfont, XMail.buttonFont);
  165.        XtSetArg(args[2], XtNcallback, callbacks);
  166.        XtSetArg(args[3], XtNtranslations, XtParseTranslationTable(trans));
  167. /*
  168. ** create the menu buttons
  169. */
  170.        bw = above = to_left = NULL;
  171.        for (x = 0; x < total; x++) {
  172.            s = XtMalloc((unsigned) path_length + strlen(ftbl[x]) + 2);
  173.            (void) sprintf(s, "%s/%s", path, ftbl[x]);
  174.            (void) strcpy(tmp, ftbl[x]);
  175. /*
  176. ** If this folder file is also a directory, add a trailing slash '/'
  177. */
  178.            if (access(s, R_OK) == 0 &&        /* IF exists and is readable */
  179.               stat(s, &st_buf) == 0 &&        /* got the status okay, and  */
  180.               S_ISDIR(st_buf.st_mode))        /* it IS a directory... then */
  181.               (void) strcat(tmp, "/");
  182.            XtSetArg(args[4], XtNlabel, tmp);
  183.            XtSetArg(args[5], XtNfromHoriz, to_left);            n = 6;
  184.            if (! to_left) XtSetArg(args[n], XtNfromVert, above);    n++;
  185.            bw = XtCreateManagedWidget("menubutton",commandWidgetClass,layout,args,n);
  186.            if (to_left == NULL) above = bw;
  187.            to_left = bw;
  188.            if ((x+1) % 3 == 0)            /* make box three items wide */
  189.               to_left = NULL;
  190. /*
  191. ** If this 'folder' is a directory, add a button popup menu of its files.
  192. */
  193.            if (LASTCH(tmp) == '/') {
  194.               (void) sprintf(trans, dir_Trans, tmp, s, depth);
  195.               XtOverrideTranslations(bw, XtParseTranslationTable(trans));
  196.               AddInfoHandler(bw, Folder_Info[2]);
  197.              } else
  198.               AddInfoHandler(bw, Folder_Info[1]);
  199.            XtFree(s);
  200.           } /* end - for each name in the folder table */
  201.       } /* end - if there exists at least one folder name */
  202. /*
  203. ** If no buttons were created for this menu, destroy the widget.
  204. */
  205.     if (! label_width)
  206.        XtDestroyWidget(menu);
  207.     SetCursor(NORMAL);
  208.    } /* end - if menu had not yet been created */
  209. /*
  210. ** If menu exists, pop it up, after setting x,y coordinates
  211. */
  212.  menu = XtNameToWidget(w, name);
  213.  
  214.  if (! menu || menu->core.being_destroyed)
  215.     XBell(XtDisplay(toplevel), 33);
  216.  else {
  217.     SetPopup(w, event, params, num_params);
  218.  
  219.     XtSetArg(args[0], XtNy, NULL);
  220.     XtGetValues(menu, args, ONE);
  221.     args[0].value -= XMail.menuY;    /* don't offset menu below cursor */
  222.     XtSetValues(menu, args, ONE);
  223.  
  224.     XtPopup(menu, XtGrabNone);
  225.    }
  226. } /* SetDirectory */
  227.