home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xpaint-247 / filename.c < prev    next >
C/C++ Source or Header  |  1997-01-03  |  25KB  |  1,043 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)           | */
  3. /* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk)  | */
  4. /* |                                       | */
  5. /* | Permission to use, copy, modify, and to distribute this software  | */
  6. /* | and its documentation for any purpose is hereby granted without   | */
  7. /* | fee, provided that the above copyright notice appear in all       | */
  8. /* | copies and that both that copyright notice and this permission    | */
  9. /* | notice appear in supporting documentation.     There is no           | */
  10. /* | representations about the suitability of this software for           | */
  11. /* | any purpose.  this software is provided "as is" without express   | */
  12. /* | or implied warranty.                           | */
  13. /* |                                       | */
  14. /* +-------------------------------------------------------------------+ */
  15.  
  16. /* $Id: fileName.c,v 1.7 1996/06/09 17:27:49 torsten Exp $ */
  17.  
  18. #include <X11/StringDefs.h>
  19. #include <X11/Intrinsic.h>
  20. #include <X11/Shell.h>
  21. #ifndef VMS
  22. #include <X11/Xaw/Dialog.h>
  23. #include <X11/Xaw/Command.h>
  24. #include <X11/Xaw/Toggle.h>
  25. #include <X11/Xaw/Form.h>
  26. #include <X11/Xaw/Label.h>
  27. #include <X11/Xaw/List.h>
  28. #include <X11/Xaw/AsciiText.h>
  29. #include <X11/Xaw/Text.h>
  30. #include <X11/Xaw/Viewport.h>
  31. #include <X11/Xaw/Scrollbar.h>
  32. #else
  33. #include <X11Xaw/Dialog.h>
  34. #include <X11Xaw/Command.h>
  35. #include <X11Xaw/Toggle.h>
  36. #include <X11Xaw/Form.h>
  37. #include <X11Xaw/Label.h>
  38. #include <X11Xaw/List.h>
  39. #include <X11Xaw/AsciiText.h>
  40. #include <X11Xaw/Text.h>
  41. #include <X11Xaw/Viewport.h>
  42. #include <X11Xaw/Scrollbar.h>
  43. #endif
  44.  
  45. #include "Paint.h"
  46. #include "PaintP.h"
  47. #include "xpaint.h"
  48. #include "misc.h"
  49. #include "image.h"
  50. #include <stdio.h>
  51. #include <sys/types.h>
  52. #include <sys/stat.h>
  53. #if defined(SYSV) || defined(SVR4)
  54. #include <dirent.h>
  55. #else
  56. #ifndef VMS
  57. #include <sys/dir.h>
  58. #else
  59. #include <dir.h>
  60. #include <dirent.h>
  61. #endif  /* VMS */
  62. #endif
  63.  
  64. #include <pwd.h>
  65.  
  66. #include "rw/rwTable.h"
  67. #include "graphic.h"
  68. #include "protocol.h"
  69.  
  70. #define MAX_PATH    1024
  71.  
  72. #ifndef NOSTDHDRS
  73. #include <stdlib.h>
  74. #include <unistd.h>
  75. #endif
  76.  
  77. /*
  78. **  swiped from X11/Xfuncproto.h
  79. **   since qsort() may or may not be defined with a constant sub-function
  80.  */
  81. #ifndef _Xconst
  82. #if __STDC__ || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&4)
  83. #define _Xconst const
  84. #else
  85. #define _Xconst
  86. #endif
  87. #endif                /* _Xconst */
  88.  
  89. static void *lastId = NULL;
  90.  
  91. void *
  92. GetFileNameGetLastId()
  93. {
  94.     if (lastId == NULL)
  95.     return RWtableGetReaderID();
  96.     return lastId;
  97. }
  98.  
  99. /*
  100. **  "Std" Save functions
  101.  */
  102.  
  103. /*
  104.  * This function is called by all image save functions.
  105.  * If 'flag' is True, save the entire image; otherwise, save the region.
  106.  */
  107. static void 
  108. stdSaveCommonCallback(Widget paint, char *file, Boolean flag, RWwriteFunc f)
  109. {
  110.     Pixmap pix, mask = None;
  111.     int width, height;
  112.     Colormap cmap;
  113.     Image *image;
  114.  
  115.     if (*file == '\0') {
  116.     Notice(paint, "No file name supplied");
  117.     return;
  118.     }
  119.     StateSetBusy(True);
  120.     if (flag) {
  121.     PwGetPixmap(paint, &pix, &width, &height);
  122.     } else {
  123.     if (!PwRegionGet(paint, &pix, &mask)) {
  124.         Notice(paint, "Unable to get region");
  125.         StateSetBusy(False);
  126.         return;
  127.     }
  128.     }
  129.     XtVaGetValues(paint, XtNcolormap, &cmap, NULL);
  130.  
  131.     if ((image = PixmapToImage(paint, pix, cmap)) == NULL) {
  132.     Notice(paint, "Unable to create image for saving");
  133.     StateSetBusy(False);
  134.     return;
  135.     }
  136.     if (mask != None)
  137.     PixmapToImageMask(paint, image, mask);
  138.  
  139.     image->refCount++;
  140.     if (f(file, image)) {
  141.     Notice(paint, "Error saving file:\n   %s", RWGetMsg());
  142.     } else if (flag) {
  143.     PaintWidget p = (PaintWidget) paint;
  144.  
  145.     XtVaSetValues(paint, XtNdirty, False, NULL);
  146.     if (p->paint.filename != NULL)
  147.         free(p->paint.filename);
  148.     p->paint.filename = xmalloc(strlen(file) + 1);
  149.     strcpy(p->paint.filename, file);
  150.     EnableRevert(paint);
  151.     }
  152.     image->refCount--;
  153.     ImageDelete(image);
  154.     StateSetBusy(False);
  155. }
  156.  
  157. static void 
  158. saveRegionFileCallback(Widget paint, XtPointer str, XtPointer func)
  159. {
  160.     stdSaveCommonCallback(paint, (char *) str, False, (RWwriteFunc) func);
  161. }
  162.  
  163. static void 
  164. saveFileCallback(Widget paint, XtPointer str, XtPointer func)
  165. {
  166.     char *cp;
  167.  
  168.     stdSaveCommonCallback(paint, (char *) str, True, (RWwriteFunc) func);
  169.  
  170.     if ((cp = strrchr(str, '/')) == NULL)
  171.     cp = str;
  172.     else
  173.     cp++;
  174.  
  175.     XtVaSetValues(GetShell(paint), XtNtitle, str, XtNiconName, cp, NULL);
  176. }
  177.  
  178. void 
  179. StdSaveRegionFile(Widget w, XtPointer paintArg, XtPointer junk)
  180. {
  181.     Widget paint = (Widget) paintArg;
  182.  
  183.     if (PwRegionGet(paint, NULL, NULL))
  184.     GetFileName(paint, True, NULL, saveRegionFileCallback, NULL);
  185.     else
  186.     Notice(paint, "No region selected presently");
  187. }
  188.  
  189. void 
  190. StdSaveAsFile(Widget w, XtPointer paintArg, XtPointer junk)
  191. {
  192.     Widget paint = (Widget) paintArg;
  193.     String name;
  194.     String nm = XtName(GetShell(paint));
  195.  
  196.     XtVaGetValues(GetShell(paint), XtNtitle, &name, NULL);
  197.  
  198.     if (strcmp(name, DEFAULT_TITLE) == 0 || strcmp(nm, name) == 0)
  199.     name = NULL;
  200.  
  201.     GetFileName(paint, True, name, saveFileCallback, NULL);
  202. }
  203.  
  204. void 
  205. StdSaveFile(Widget w, XtPointer paintArg, XtPointer junk)
  206. {
  207.     Widget paint = (Widget) paintArg;
  208.     String name = NULL;
  209.     String nm = XtName(GetShell(paint));
  210.     RWwriteFunc f = NULL;
  211.     void *id;
  212.  
  213.     if (strcmp(nm, "Canvas") == 0) {
  214.     XtVaGetValues(GetShell(paint), XtNtitle, &name, NULL);
  215.  
  216.     if (strcmp(name, DEFAULT_TITLE) == 0 || strcmp(nm, name) == 0)
  217.         name = NULL;
  218.     }
  219.     if (name != NULL) {
  220.     if ((id = getArgType(paint)) != NULL) {
  221.         f = (RWwriteFunc) RWtableGetWriter(id);
  222.     } else if ((id = GraphicGetReaderId(paint)) != NULL) {
  223.         f = (RWwriteFunc) RWtableGetWriter(RWtableGetEntry(id));
  224.     }
  225.     if (f != NULL) {
  226.         stdSaveCommonCallback(paint, name, True, f);
  227.         return;
  228.  
  229.     }
  230.     }
  231.     GetFileName(paint, True, name, saveFileCallback, NULL);
  232. }
  233.  
  234. /*
  235. **
  236.  */
  237. void *
  238. ReadMagic(char *file)
  239. {
  240.     RWreadFunc f = RWtableGetReader(RWtableGetEntry(MAGIC_READER));
  241.  
  242.     return (void *) f(file);
  243. }
  244.  
  245. /*
  246. **  The code begins
  247.  */
  248. typedef struct arg_s {
  249.     XtCallbackProc okFunc;
  250.     void *type;
  251.     Boolean isRead, isSimple;
  252.     Widget w, text, scrollbar;
  253.     XtPointer closure;
  254.     char dirname[MAX_PATH];
  255.     Widget list, cwd_w, info;
  256.     int first;
  257.     Boolean isPoped;
  258.     /*
  259.     **    Use for caching, list purposes
  260.      */
  261.     Widget parent;
  262.     int browserType;
  263.     struct arg_s *next;
  264. } arg_t;
  265.  
  266. static void 
  267. fileTypeCallback(Widget w, XtPointer argArg, XtPointer junk)
  268. {
  269.     arg_t *arg = (arg_t *) argArg;
  270.     String nm = XtName(w);
  271.  
  272.     arg->type = RWtableGetEntry(nm);
  273. }
  274.  
  275. static void 
  276. emptyList(arg_t * arg)
  277. {
  278.     String *strs;
  279.     int i, n;
  280.  
  281.     if (arg->first) {
  282.     arg->first = False;
  283.     return;
  284.     }
  285.     XtVaGetValues(arg->list, XtNnumberStrings, &n, XtNlist, &strs, NULL);
  286.  
  287.     for (i = 0; i < n; i++)
  288.     XtFree((XtPointer) strs[i]);
  289.     XtFree((XtPointer) strs);
  290. }
  291.  
  292. static char *
  293. doDirname(arg_t * arg, char *file)
  294. {
  295.     static char newPath[MAX_PATH];
  296.     char *cp;
  297.  
  298.     if (file == NULL) {
  299. #ifdef NOSTDHDRS
  300.     getwd(newPath);
  301. #else
  302.     getcwd(newPath, sizeof(newPath));
  303. #endif
  304.     return newPath;
  305.     }
  306. #ifndef VMS
  307.     if (*file == '~') {
  308.     struct passwd *pw;
  309.  
  310.     file++;
  311.     if (*file == '/' || *file == '\0') {
  312.         pw = getpwuid(getuid());
  313.     } else {
  314.         char buf[80], *bp = buf;
  315.  
  316.         while (*file != '/' && *file != '\0')
  317.         *bp++ = *file++;
  318.         *bp = '\0';
  319.         pw = getpwnam(buf);
  320.     }
  321.     if (pw == NULL)
  322.         return NULL;
  323.     while (*file == '/')
  324.         file++;
  325.     strcpy(newPath, pw->pw_dir);
  326.     } else if (*file == '/') {
  327.     file++;
  328.     newPath[0] = '\0';
  329.     } else {
  330.     strcpy(newPath, arg->dirname);
  331.     }
  332.     if (strcmp(newPath, "/") != 0)
  333.     strcat(newPath, "/");
  334.     while (*file != '\0') {
  335.     char *ep;
  336.  
  337.     if ((ep = strchr(file, '/')) == NULL)
  338.         ep = file + strlen(file);
  339.     if (strncmp(file, "./", 2) == 0 || strcmp(file, ".") == 0)
  340.         goto bottom;
  341.     if (strncmp(file, "../", 3) == 0 || strcmp(file, "..") == 0) {
  342.         /*
  343.         **    First strip trailing '/'
  344.          */
  345.         char *cp = newPath + strlen(newPath) - 1;
  346.         if (cp != newPath)
  347.         *cp = '\0';
  348.         cp = strrchr(newPath, '/');
  349.         if (cp == newPath)
  350.         strcpy(newPath, "/");
  351.         else
  352.         *cp = '\0';
  353.         goto bottom;
  354.     }
  355.     strncat(newPath, file, ep - file);
  356.       bottom:
  357.     file = ep;
  358.     if (*file == '/')
  359.         strcat(newPath, "/");
  360.     while (*file == '/')
  361.         file++;
  362.     }
  363.  
  364.     /*
  365.     **    Strip any trailing '/'s
  366.      */
  367.     cp = newPath + strlen(newPath) - 1;
  368.     if (*cp == '/' && cp != newPath)
  369.     *cp = '\0';
  370. #else                      /* si un ], on dit que c'est un repertoire */
  371.                 if ((cp = strchr(file,']')) == NULL)
  372.                {
  373.                      getcwd(newPath, sizeof(newPath));
  374.                   strcat(newPath,(const) file);
  375.                 }
  376.                 else
  377.                    strcpy (newPath, (const) file);
  378.  
  379. #endif   /* VMS */        
  380.  
  381.  
  382.     return newPath;
  383. }
  384.  
  385. static int 
  386. strqsortcmp(char **a, char **b)
  387. {
  388.     String astr = *a;
  389.     String bstr = *b;
  390.     String aend = astr + strlen(astr) - 1;
  391.     String bend = bstr + strlen(bstr) - 1;
  392.  
  393.     if (strncmp(astr, "../", 3) == 0)
  394.     return -1;
  395.     if (strncmp(bstr, "../", 3) == 0)
  396.     return 1;
  397.  
  398.     if (*aend == '/' && *bend != '/')
  399.     return -1;
  400.     if (*aend != '/' && *bend == '/')
  401.     return 1;
  402.     return strcmp(astr, bstr);
  403. }
  404.  
  405. static void 
  406. setCWD(arg_t * arg, char *dir)
  407. {
  408.     DIR *dirp;
  409. #if defined(SYSV) || defined(SVR4) || defined(__alpha)
  410.     struct dirent *e;
  411. #else
  412.     struct direct *e;
  413. #endif
  414.     int count = 0, i = 0;
  415.     int dirCount = 0, fileCount = 0;
  416.     String *list;
  417.     char fileStr[MAX_PATH], *filePtr;
  418.     static char infoStr[256];
  419.     struct stat statbuf;
  420.     Widget sb;
  421.  
  422.     if (dir == NULL)
  423.     dir = arg->dirname;
  424.  
  425.     if (stat(dir, &statbuf) < 0 || (statbuf.st_mode & S_IFDIR) == 0)
  426.     return;
  427.  
  428.     if ((dirp = opendir(dir)) == NULL)
  429.     return;
  430.  
  431.     StateSetBusyWatch(True);
  432.  
  433.     while (readdir(dirp) != NULL)
  434.     count++;
  435.     rewinddir(dirp);
  436.  
  437.     list = (String *) XtCalloc(sizeof(String *), count + 1);
  438.  
  439.     strcpy(fileStr, dir == NULL ? arg->dirname : dir);
  440.     filePtr = fileStr + strlen(fileStr);
  441.     *filePtr++ = '/';
  442.     while ((e = readdir(dirp)) != NULL) {
  443.     struct stat statbuf;
  444.     char *nm = e->d_name;
  445.  
  446.     if (nm[0] == '.') {
  447.         /*
  448.         **    Skip '.'
  449.          */
  450.         if (nm[1] == '\0')
  451.         continue;
  452.         if (nm[1] == '.' && nm[2] == '\0') {
  453.         list[i++] = XtNewString("../ (Go up 1 directory level)");
  454.         continue;
  455.         }
  456.     }
  457.     strcpy(filePtr, nm);
  458.     if (stat(fileStr, &statbuf) < 0) {
  459.         list[i++] = XtNewString(nm);
  460.         continue;
  461.     }
  462.     if ((statbuf.st_mode & S_IFDIR) != 0) {
  463.         list[i] = XtMalloc(sizeof(char) * strlen(nm) + 2);
  464.         strcpy(list[i], nm);
  465.         strcat(list[i], "/");
  466.         i++;
  467.         dirCount++;
  468.         continue;
  469.     }
  470.     /*
  471.     **  Now only if it is a file.
  472.      */
  473.     if ((statbuf.st_mode & (S_IFMT & ~S_IFLNK)) == 0) {
  474.         list[i++] = XtNewString(nm);
  475.         fileCount++;
  476.     }
  477.     }
  478.  
  479.     closedir(dirp);
  480.  
  481.     emptyList(arg);
  482.  
  483.     qsort(list, i, sizeof(String),
  484.       (int (*)(_Xconst void *, _Xconst void *)) strqsortcmp);
  485.  
  486.     if (dir != NULL) {
  487.     strcpy(arg->dirname, dir);
  488.     XtVaSetValues(arg->cwd_w, XtNlabel, dir, NULL);
  489.     }
  490.     XawListChange(arg->list, list, i, 0, True);
  491.     XtVaSetValues(arg->text, XtNstring, "", NULL);
  492.     sprintf(infoStr, "%d Directories, %d Files", dirCount, fileCount);
  493.     XtVaSetValues(arg->info, XtNlabel, infoStr, NULL);
  494.  
  495.     if ((sb = XtNameToWidget(arg->scrollbar, "vertical")) != None) {
  496.     float top = 0.0;
  497.  
  498.     XawScrollbarSetThumb(sb, top, -1.0);
  499.     XtCallCallbacks(sb, XtNjumpProc, (XtPointer) & top);
  500.     }
  501.     StateSetBusyWatch(False);
  502. }
  503.  
  504. static void 
  505. okCallback(Widget w, XtPointer argArg, XtPointer junk)
  506. {
  507.     arg_t *arg = (arg_t *) argArg;
  508.     String str;
  509.     RWreadFunc f;
  510.     struct stat statbuf;
  511.     char *file;
  512.     char *cp;
  513.     char *nm;
  514.  
  515.     XtVaGetValues(arg->text, XtNstring, &str, NULL);
  516.     if (str == NULL || *str == '\0') {
  517.     XawListReturnStruct *lr = XawListShowCurrent(arg->list);
  518.  
  519.     if (lr->list_index == XAW_LIST_NONE)
  520.         return;
  521.     str = lr->string;
  522.     }
  523.     /*
  524.     **    Got a valid string, check to see if it is a directory
  525.     **      if not try and read/write the file.
  526.      */
  527.     if ((file = doDirname(arg, str)) == NULL) {
  528.     Notice(w, "No such file or directory:\n        %s", str);
  529.     return;
  530.     }
  531.     if (stat(file, &statbuf) >= 0 && (statbuf.st_mode & S_IFDIR) != 0) {
  532.     setCWD(arg, file);
  533.     return;
  534.     }
  535.     if ((cp = strrchr(file, '/')) != NULL) {
  536.     *cp = '\0';
  537.     if (stat(file, &statbuf) >= 0 && (statbuf.st_mode & S_IFDIR) != 0)
  538.         setCWD(arg, file);
  539.     *cp = '/';
  540.     }
  541.     arg->isPoped = False;
  542.     XtPopdown(GetShell(w));
  543.  
  544.     if (arg->isSimple) {
  545.     arg->okFunc(arg->w, (XtPointer) arg->closure, (XtPointer) file);
  546.     return;
  547.     }
  548.     if (arg->isRead)
  549.     f = (RWreadFunc) RWtableGetReader(arg->type);
  550.     else
  551.     f = (RWreadFunc) RWtableGetWriter(arg->type);
  552.  
  553.     if (arg->type != NULL &&
  554.     strcmp(nm = RWtableGetId(arg->type), MAGIC_READER) != 0)
  555.     lastId = (void *) nm;
  556.     else
  557.     lastId = NULL;
  558.  
  559.     StateSetBusy(True);
  560.     if (arg->okFunc != NULL) {
  561.     if (!arg->isRead) {
  562.         arg->okFunc(arg->w, file, (XtPointer) f);
  563.     } else {
  564.         Image *image = f(file);
  565.         if (image == NULL)
  566.         Notice(w, "Unable to open input file \"%s\"\n    %s", file, RWGetMsg());
  567.         else
  568.         arg->okFunc(arg->w, (XtPointer) file, (XtPointer) image);
  569.     }
  570.     }
  571.     StateSetBusy(False);
  572. }
  573.  
  574. static void 
  575. cancelCallback(Widget w, XtPointer argArg, XtPointer junk)
  576. {
  577.     arg_t *arg = (arg_t *) argArg;
  578.     arg->isPoped = False;
  579.     XtPopdown(GetShell(w));
  580. }
  581.  
  582. static void 
  583. listCallback(Widget bar, XtPointer argArg, XtPointer itemArg)
  584. {
  585.     XawListReturnStruct *item = (XawListReturnStruct *) itemArg;
  586.     arg_t *arg = (arg_t *) argArg;
  587.     String str, label;
  588.  
  589.     if (strncmp(item->string, "../", 3) == 0)
  590.     label = "../";
  591.     else
  592.     label = item->string;
  593.  
  594.     XtVaGetValues(arg->text, XtNstring, &str, NULL);
  595.  
  596.     if (strcmp(str, label) == 0)
  597.     okCallback(bar, argArg, NULL);
  598.     else
  599.     XtVaSetValues(arg->text, XtNstring, label, NULL);
  600. }
  601.  
  602. static Widget
  603. buildBrowser(Widget parent, char *title, arg_t * arg)
  604. {
  605.     static Boolean inited = False;
  606.     static XtTranslations trans, toglt;
  607.     Widget form;
  608.     Widget title_w, name, list, vport, cwd, info;
  609.  
  610.     if (!inited) {
  611.     inited = True;
  612.  
  613.     trans = XtParseTranslationTable("#override\n\
  614.                          <Key>Return: no-op()\n\
  615.                          <Key>Linefeed: no-op()\n\
  616.                          Ctrl<Key>M: no-op()\n\
  617.                          Ctrl<Key>J: no-op()\n");
  618.     toglt = XtParseTranslationTable("<BtnDown>,<BtnUp>: set() notify()");
  619.     }
  620. #ifdef NOSTDHDRS
  621.     getwd(arg->dirname);
  622. #else
  623.     getcwd(arg->dirname, sizeof(arg->dirname));
  624. #endif
  625.  
  626.     form = XtVaCreateManagedWidget("broswer",
  627.                    formWidgetClass, parent,
  628.                    XtNborderWidth, 0,
  629.                    XtNright, XtChainRight,
  630.                    XtNleft, XtChainLeft,
  631.                    XtNtop, XtChainTop,
  632.                    NULL);
  633.  
  634.     title_w = XtVaCreateManagedWidget("title",
  635.                       labelWidgetClass, form,
  636.                       XtNborderWidth, 0,
  637.                       XtNlabel, title,
  638.                       XtNtop, XtChainTop,
  639.                       XtNbottom, XtChainTop,
  640.                       XtNjustify, XtJustifyLeft,
  641.                       NULL);
  642.  
  643.     name = XtVaCreateManagedWidget("name",
  644.                    asciiTextWidgetClass, form,
  645.                    XtNfromVert, title_w,
  646.                    XtNeditType, XawtextEdit,
  647.                    XtNwrap, XawtextWrapNever,
  648.                    XtNresize, XawtextResizeWidth,
  649.                    XtNtranslations, trans,
  650.                    XtNbottom, XtChainTop,
  651.                    XtNtop, XtChainTop,
  652.                    XtNwidth, 250,
  653.                    NULL);
  654.  
  655.     vport = XtVaCreateManagedWidget("vport",
  656.                     viewportWidgetClass, form,
  657.                     XtNfromVert, name,
  658.                     XtNtop, XtChainTop,
  659.                     XtNbottom, XtChainBottom,
  660.                     XtNallowVert, True,
  661.                     XtNallowHoriz, True,
  662.                     XtNuseBottom, True,
  663.                     XtNuseRight, True,
  664.                     XtNwidth, 250,
  665.                     XtNheight, 200,
  666.                     NULL);
  667.  
  668.     list = XtVaCreateManagedWidget("files",
  669.                    listWidgetClass, vport,
  670.                    XtNborderWidth, 1,
  671.                    XtNverticalList, True,
  672.                    XtNforceColumns, True,
  673.                    XtNdefaultColumns, 1,
  674.                    XtNnumberStrings, 0,
  675.                    NULL);
  676.  
  677.     cwd = XtVaCreateManagedWidget("cwd",
  678.                   labelWidgetClass, form,
  679.                   XtNlabel, arg->dirname,
  680.                   XtNborderWidth, 0,
  681.                   XtNfromVert, vport,
  682.                   XtNtop, XtChainBottom,
  683.                   XtNbottom, XtChainBottom,
  684.                   XtNjustify, XtJustifyLeft,
  685.                   XtNresizable, True,
  686.                   NULL);
  687.     info = XtVaCreateManagedWidget("info",
  688.                    labelWidgetClass, form,
  689.                    XtNborderWidth, 0,
  690.                    XtNfromVert, cwd,
  691.                    XtNtop, XtChainBottom,
  692.                    XtNbottom, XtChainBottom,
  693.                    XtNjustify, XtJustifyLeft,
  694.                    NULL);
  695.  
  696.     XtAddCallback(list, XtNcallback, listCallback, (XtPointer) arg);
  697.  
  698.     arg->info = info;
  699.     arg->cwd_w = cwd;
  700.     arg->list = list;
  701.     arg->text = name;
  702.     arg->scrollbar = vport;
  703.  
  704.     arg->first = True;
  705.  
  706.     setCWD(arg, doDirname(arg, NULL));
  707.  
  708.     return form;
  709. }
  710.  
  711. static Widget
  712. buildOpenBroswer(Widget w, arg_t * arg)
  713. {
  714.     Widget shell, browser, okButton, cancelButton, form;
  715.     Widget toggle, firstToggle = None;
  716.     XtAccelerators accel;
  717.     XtTranslations toglt;
  718.     int i;
  719.     char **list;
  720.  
  721.     shell = XtVaCreatePopupShell("filebrowser",
  722.                    transientShellWidgetClass, GetToplevel(w),
  723.                  NULL);
  724.     form = XtVaCreateManagedWidget("form",
  725.                    formWidgetClass, shell,
  726.                    XtNborderWidth, 0,
  727.                    NULL);
  728.     browser = buildBrowser(form, "Open File Named:", arg);
  729.  
  730.     accel = XtParseAcceleratorTable("#override\n\
  731.                      <Key>Return: set() notify() unset()\n\
  732.                      <Key>Linefeed: set() notify() unset()");
  733.  
  734.     okButton = XtVaCreateManagedWidget("ok",
  735.                        commandWidgetClass, form,
  736.                        XtNfromHoriz, browser,
  737.                        XtNaccelerators, accel,
  738.                        XtNbottom, XtChainTop,
  739.                        XtNleft, XtChainRight,
  740.                        XtNright, XtChainRight,
  741.                        NULL);
  742.     cancelButton = XtVaCreateManagedWidget("cancel",
  743.                        commandWidgetClass, form,
  744.                        XtNfromHoriz, okButton,
  745.                        XtNbottom, XtChainTop,
  746.                        XtNleft, XtChainRight,
  747.                        XtNright, XtChainRight,
  748.                        NULL);
  749.  
  750.     toggle = okButton;
  751.     toglt = XtParseTranslationTable("<BtnDown>,<BtnUp>: set() notify()");
  752.  
  753.     list = RWtableGetReaderList();
  754.  
  755.     for (i = 0; list[i] != NULL; i++) {
  756.     toggle = XtVaCreateManagedWidget(list[i],
  757.                      toggleWidgetClass, form,
  758.                      XtNtranslations, toglt,
  759.                      XtNradioGroup, firstToggle,
  760.                      XtNfromVert, toggle,
  761.                      XtNfromHoriz, browser,
  762.                      XtNtop, XtChainBottom,
  763.                      XtNbottom, XtChainBottom,
  764.                      XtNleft, XtChainRight,
  765.                      XtNright, XtChainRight,
  766.                      NULL);
  767.     if (firstToggle == None) {
  768.         arg->type = NULL;
  769.         XtVaSetValues(toggle, XtNstate, True,
  770.               XtNvertDistance, 100,
  771.               NULL);
  772.         firstToggle = toggle;
  773.     }
  774.     XtAddCallback(toggle, XtNcallback, fileTypeCallback, (XtPointer) arg);
  775.     }
  776.  
  777.     arg->isSimple = False;
  778.     arg->isRead = True;
  779.  
  780.     XtAddCallback(okButton, XtNcallback, okCallback, (XtPointer) arg);
  781.     XtAddCallback(cancelButton, XtNcallback, cancelCallback, (XtPointer) arg);
  782.     AddDestroyCallback(shell,
  783.                (DestroyCallbackFunc) cancelCallback, (XtPointer) arg);
  784.  
  785.     XtSetKeyboardFocus(form, arg->text);
  786.     XtInstallAccelerators(arg->text, okButton);
  787.  
  788.     return shell;
  789. }
  790.  
  791. static Widget
  792. buildSaveBroswer(Widget w, arg_t * arg)
  793. {
  794.     Widget shell, browser, okButton, cancelButton, form;
  795.     Widget toggle, firstToggle = None;
  796.     XtAccelerators accel;
  797.     XtTranslations toglt;
  798.     int i;
  799.     char **list, *rdr = NULL;
  800.  
  801.     shell = XtVaCreatePopupShell("filebrowser",
  802.                    transientShellWidgetClass, GetToplevel(w),
  803.                  NULL);
  804.     form = XtVaCreateManagedWidget("form",
  805.                    formWidgetClass, shell,
  806.                    XtNborderWidth, 0,
  807.                    NULL);
  808.     browser = buildBrowser(form, "Save In File:", arg);
  809.  
  810.     accel = XtParseAcceleratorTable("#override\n\
  811.                      <Key>Return: set() notify() unset()\n\
  812.                      <Key>Linefeed: set() notify() unset()");
  813.  
  814.     okButton = XtVaCreateManagedWidget("ok",
  815.                        commandWidgetClass, form,
  816.                        XtNfromHoriz, browser,
  817.                        XtNaccelerators, accel,
  818.                        XtNbottom, XtChainTop,
  819.                        NULL);
  820.     cancelButton = XtVaCreateManagedWidget("cancel",
  821.                        commandWidgetClass, form,
  822.                        XtNfromHoriz, okButton,
  823.                        XtNbottom, XtChainTop,
  824.                        NULL);
  825.  
  826.     toggle = okButton;
  827.     toglt = XtParseTranslationTable("<BtnDown>,<BtnUp>: set() notify()");
  828.     list = RWtableGetWriterList();
  829.  
  830.     if (RWtableGetWriter(GraphicGetReaderId(w)) != NULL) {
  831.     rdr = (char *) GraphicGetReaderId(w);
  832.     }
  833.     for (i = 0; list[i] != NULL; i++) {
  834.     toggle = XtVaCreateManagedWidget(list[i],
  835.                      toggleWidgetClass, form,
  836.                      XtNtranslations, toglt,
  837.                      XtNradioGroup, firstToggle,
  838.                      XtNfromVert, toggle,
  839.                      XtNfromHoriz, browser,
  840.                      XtNtop, XtChainBottom,
  841.                      XtNbottom, XtChainBottom,
  842.                      NULL);
  843.     if (firstToggle == None) {
  844.         arg->type = NULL;
  845.         XtVaSetValues(toggle, XtNvertDistance, 100, NULL);
  846.         firstToggle = toggle;
  847.         if (rdr == NULL)
  848.         XtVaSetValues(toggle, XtNstate, True, NULL);
  849.     }
  850.     if (rdr != NULL && strcmp(rdr, list[i]) == 0) {
  851.         arg->type = RWtableGetEntry(list[i]);
  852.         XtVaSetValues(toggle, XtNstate, True, NULL);
  853.     }
  854.     XtAddCallback(toggle, XtNcallback, fileTypeCallback, (XtPointer) arg);
  855.     }
  856.  
  857.     arg->isSimple = False;
  858.     arg->isRead = False;
  859.  
  860.     XtAddCallback(okButton, XtNcallback, okCallback, (XtPointer) arg);
  861.     XtAddCallback(cancelButton, XtNcallback, cancelCallback, (XtPointer) arg);
  862.     AddDestroyCallback(shell,
  863.                (DestroyCallbackFunc) cancelCallback, (XtPointer) arg);
  864.  
  865.     XtSetKeyboardFocus(form, arg->text);
  866.     XtInstallAccelerators(arg->text, okButton);
  867.  
  868.     return shell;
  869. }
  870.  
  871. static Widget
  872. buildSimpleBroswer(Widget w, arg_t * arg, Boolean isSave)
  873. {
  874.     Widget shell, browser, okButton, cancelButton, form;
  875.     XtAccelerators accel;
  876.  
  877.     shell = XtVaCreatePopupShell("filebrowser",
  878.                    transientShellWidgetClass, GetToplevel(w),
  879.                  NULL);
  880.     form = XtVaCreateManagedWidget("form",
  881.                    formWidgetClass, shell,
  882.                    XtNborderWidth, 0,
  883.                    NULL);
  884.     browser = buildBrowser(form, isSave ? "Save In File:"
  885.                : "Load from File:"
  886.                ,arg);
  887.  
  888.     accel = XtParseAcceleratorTable("#override\n\
  889.                      <Key>Return: set() notify() unset()\n\
  890.                      <Key>Linefeed: set() notify() unset()");
  891.  
  892.     okButton = XtVaCreateManagedWidget("ok",
  893.                        commandWidgetClass, form,
  894.                        XtNfromHoriz, browser,
  895.                        XtNaccelerators, accel,
  896.                        XtNbottom, XtChainTop,
  897.                        NULL);
  898.     cancelButton = XtVaCreateManagedWidget("cancel",
  899.                        commandWidgetClass, form,
  900.                        XtNfromHoriz, okButton,
  901.                        XtNbottom, XtChainTop,
  902.                        NULL);
  903.  
  904.     arg->isSimple = True;
  905.  
  906.     XtAddCallback(okButton, XtNcallback, okCallback, (XtPointer) arg);
  907.     XtAddCallback(cancelButton, XtNcallback, cancelCallback, (XtPointer) arg);
  908.     AddDestroyCallback(shell,
  909.                (DestroyCallbackFunc) cancelCallback, (XtPointer) arg);
  910.  
  911.     XtSetKeyboardFocus(form, arg->text);
  912.     XtInstallAccelerators(arg->text, okButton);
  913.  
  914.     return shell;
  915. }
  916.  
  917. /*
  918. **  
  919. **
  920.  */
  921.  
  922. static arg_t *argList = NULL;
  923.  
  924. static void 
  925. freeArg(Widget w, arg_t * arg)
  926. {
  927.     arg_t *c = argList, **pp = &argList;
  928.  
  929.     while (c != arg && c != NULL) {
  930.     pp = &c->next;
  931.     c = c->next;
  932.     }
  933.  
  934.     *pp = arg->next;
  935.  
  936.     XtDestroyWidget(GetShell(arg->text));
  937.     XtFree((XtPointer) arg);
  938. }
  939.  
  940. void *
  941. getArgType(Widget w)
  942. {
  943.     arg_t *cur;
  944.  
  945.     w = GetShell(w);
  946.  
  947.     for (cur = argList; cur != NULL; cur = cur->next)
  948.     if (cur->parent == w &&
  949.         (cur->browserType == 0 ||
  950.          cur->browserType == 1))
  951.         break;
  952.  
  953.     if (cur == NULL)
  954.     return NULL;
  955.     return cur->type;
  956. }
  957.  
  958.  
  959. static arg_t *
  960. getArg(Widget w, Boolean type, Boolean * built)
  961. {
  962.     Widget shell, p = GetShell(w);
  963.     arg_t *cur;
  964.  
  965.     *built = False;
  966.  
  967.     for (cur = argList; cur != NULL; cur = cur->next)
  968.     if (p == cur->parent && cur->browserType == type)
  969.         return cur;
  970.  
  971.     cur = XtNew(arg_t);
  972.     cur->parent = p;
  973.     cur->browserType = type;
  974.  
  975.     switch (type) {
  976.     case 0:
  977.     shell = buildOpenBroswer(w, cur);
  978.     break;
  979.     case 1:
  980.     shell = buildSaveBroswer(w, cur);
  981.     break;
  982.     case 2:
  983.     shell = buildSimpleBroswer(w, cur, True);
  984.     break;
  985.     case 3:
  986.     shell = buildSimpleBroswer(w, cur, False);
  987.     break;
  988.     }
  989.  
  990.     cur->next = argList;    /* Add cur to front of list */
  991.     argList = cur;
  992.  
  993.     XtAddCallback(p, XtNdestroyCallback,
  994.           (XtCallbackProc) freeArg, (XtPointer) cur);
  995.  
  996.     *built = True;
  997.  
  998.     return cur;
  999. }
  1000.  
  1001. void 
  1002. GetFileName(Widget w, int type, char *def, XtCallbackProc okFunc, XtPointer data)
  1003. {
  1004.     arg_t *arg;
  1005.     Boolean built;
  1006.     Position x, y;
  1007.  
  1008.     XtVaGetValues(GetShell(w), XtNx, &x, XtNy, &y, NULL);
  1009.  
  1010.     arg = getArg(w, type, &built);
  1011.     arg->closure = data;
  1012.  
  1013.     XtVaSetValues(GetShell(arg->text), XtNx, x + 24, XtNy, y + 24, NULL);
  1014.  
  1015.     if (def != NULL && *def != '\0') {
  1016.     char *cp, dirname[MAX_PATH];
  1017.     strcpy(dirname, def);
  1018.     cp = strrchr(dirname, '/');
  1019.  
  1020.     if (cp != NULL && cp != dirname)
  1021.         *cp++ = '\0';
  1022.     else if (cp == NULL)
  1023.         cp = dirname;
  1024.  
  1025.     if (built)        /* This browser has not been used before, init it. */
  1026.         setCWD(arg, doDirname(arg, dirname));
  1027.  
  1028.     XtVaSetValues(arg->text, XtNstring, cp,
  1029.               XtNinsertPosition, strlen(cp),
  1030.               NULL);
  1031.     } else if (!built) {
  1032.     /*
  1033.     **  This browser has been used before, rescan directory.
  1034.      */
  1035.     setCWD(arg, NULL);
  1036.     }
  1037.     arg->okFunc = okFunc;
  1038.     arg->w = w;
  1039.  
  1040.     arg->isPoped = True;
  1041.     XtPopup(GetShell(arg->text), XtGrabNone);
  1042. }
  1043.