home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFM / XFM-1.3 / XFM-1 / xfm-1.3 / xfm / FmAw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  15.4 KB  |  554 lines

  1. /*-----------------------------------------------------------------------------
  2.   FmAw.c
  3.   
  4.   (c) Simon Marlow 1990-1993
  5.   (c) Albert Graef 1994
  6.  
  7.   Functions & data for creating & maintaining  the application window
  8. -----------------------------------------------------------------------------*/
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <memory.h>
  13. #include <time.h>
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/Shell.h>
  17. #include <X11/StringDefs.h>
  18. #include <X11/Xaw/Form.h>
  19. #include <X11/Xaw/Box.h>
  20. #include <X11/Xaw/Viewport.h>
  21. #include <X11/Xaw/Toggle.h>
  22. #include <X11/Xaw/Label.h>
  23.  
  24. #include "Am.h"
  25.  
  26. #define APPWIDTH 300
  27.  
  28. /*-----------------------------------------------------------------------------
  29.   PUBLIC DATA 
  30. -----------------------------------------------------------------------------*/
  31. AppWindowRec aw;
  32. Widget app_popup_widget, *app_popup_items, app_popup_widget1;
  33.  
  34. /*-----------------------------------------------------------------------------
  35.   STATIC DATA 
  36. -----------------------------------------------------------------------------*/
  37.  
  38. static MenuItemRec app_popup_menu[] = {
  39.   { "install", "Install...", appInstallCb },
  40.   { "delete", "Delete", appRemoveCb },
  41.   { "line1", NULL, NULL },
  42.   { "save", "Save setup", appSaveCb },
  43.   { "load", "Load setup", appLoadCb },
  44.   { "line2", NULL, NULL },
  45.   { "open", "File window", appOpenCb },
  46.   { "line3", NULL, NULL },
  47.   { "quit", "Quit", appCloseCb },
  48. };
  49.  
  50. static MenuItemRec app_popup_menu1[] = {
  51.   { "edit", "Edit...", appEditCb },
  52.   { "move", "Move", appMoveCb },
  53.   { "copy", "Copy", appCopyCb },
  54.   { "line1", NULL, NULL },
  55.   { "delete", "Delete", appRemoveCb },
  56. };
  57.  
  58. /*-----------------------------------------------------------------------------
  59.   Widget Argument lists
  60. -----------------------------------------------------------------------------*/
  61.  
  62. static Arg form_args[] = {
  63.   { XtNdefaultDistance, 0 }
  64. };
  65.  
  66. static Arg viewport_args[] = {
  67.   { XtNfromVert, (XtArgVal) NULL },
  68.   { XtNwidth, APPWIDTH },
  69.   { XtNtop, XtChainTop },
  70.   { XtNbottom, XtChainBottom },
  71.   { XtNleft, XtChainLeft },
  72.   { XtNright, XtChainRight },
  73.   { XtNallowVert, (XtArgVal) True },
  74. };
  75.  
  76. static Arg icon_box_args[] = {
  77.   { XtNwidth, 0 },
  78.   { XtNtranslations, (XtArgVal) NULL }
  79. };
  80.  
  81. static Arg icon_form_args[] = {
  82.   { XtNdefaultDistance, 0 },
  83.   { XtNwidth, 0 }
  84. };
  85.  
  86. static Arg icon_toggle_args[] = {
  87.   { XtNfromHoriz, (XtArgVal) NULL },
  88.   { XtNfromVert, (XtArgVal) NULL },
  89.   { XtNbitmap, (XtArgVal) NULL },
  90.   { XtNtranslations, (XtArgVal) NULL },
  91.   { XtNwidth, 0 },
  92.   { XtNheight, 0 }
  93. };
  94.  
  95. static Arg icon_label_args[] = {
  96.   { XtNfromHoriz, (XtArgVal) NULL },
  97.   { XtNfromVert, (XtArgVal) NULL },
  98.   { XtNlabel, (XtArgVal) NULL },
  99.   { XtNfont, (XtArgVal) NULL },
  100.   { XtNwidth, 0 },
  101.   { XtNinternalWidth, 0 },
  102.   { XtNinternalHeight, 0 }
  103. };
  104.  
  105. /*-----------------------------------------------------------------------------
  106.   Translation tables
  107. -----------------------------------------------------------------------------*/
  108.  
  109. static char app_translations[] = "\
  110.     <Enter>             : appMaybeHighlight()\n\
  111.     <Leave>             : unhighlight()\n\
  112.     <Btn1Up>(2)         : runApp()\n\
  113.     <Btn1Down>,<Btn1Up> : appSelect()\n\
  114.     <Btn2Down>,<Btn2Up> : appToggle()\n";
  115.  
  116. static char iconbox_translations[] = "\
  117.     <Btn2Up>            : dummy()\n\
  118.     <Btn3Up>            : dummy()\n\
  119.     <Btn3Down>          : appPopup()\n";
  120.  
  121. /*-----------------------------------------------------------------------------
  122.   Action tables
  123. -----------------------------------------------------------------------------*/
  124.  
  125. static void dummy(Widget w, XEvent *event, String *params, 
  126.                Cardinal *num_params) {}
  127.  
  128. static XtActionsRec app_actions[] = {
  129.   { "appMaybeHighlight", appMaybeHighlight },
  130.   { "runApp", runApp },
  131.   { "appSelect", appSelect },
  132.   { "appToggle", appToggle },
  133.   { "appPopup", appPopup },
  134.   { "dummy", dummy }
  135. };
  136.  
  137. /*-----------------------------------------------------------------------------
  138.   PRIVATE FUNCTIONS
  139. -----------------------------------------------------------------------------*/
  140.  
  141. static int longestName()
  142. {
  143.   int i, l, longest = 0;
  144.  
  145.   for (i=0; i<aw.n_apps; i++)
  146.     if ((l = XTextWidth(resources.icon_font, aw.apps[i].name, 
  147.             strlen(aw.apps[i].name))) > longest)
  148.       longest = l;
  149.   return longest;
  150. }
  151.  
  152. /*-------------------------------------------------------------------------*/
  153.  
  154. static int parseApp(FILE *fp, char **name, char **directory, char **fname,
  155.             char **icon, char **push_action, char **drop_action)
  156. {
  157.   static char s[MAXAPPSTRINGLEN];
  158.   int l;
  159.  
  160.  start:
  161.   if (feof(fp)||!fgets(s, MAXAPPSTRINGLEN, fp))
  162.     return 0;
  163.   l = strlen(s);
  164.   if (s[l-1] == '\n')
  165.     s[--l] = '\0';
  166.   if (!l || *s == '#')
  167.     goto start;
  168.   if (!(*name = split(s, ':')))
  169.     return -1;
  170.   if (!(*directory = split(NULL, ':')))
  171.     return -1;
  172.   if (!(*fname = split(NULL, ':')))
  173.     return -1;
  174.   if (!(*icon = split(NULL, ':')))
  175.     return -1;
  176.   if (!(*push_action = split(NULL, ':')))
  177.     return -1;
  178.   if (!(*drop_action = split(NULL, ':')))
  179.     return -1;
  180.   return l;
  181. }
  182.  
  183. /*---------------------------------------------------------------------------*/
  184.  
  185. /* determine the default icon of an application */
  186.  
  187. static Pixmap defaultIcon(char *name, char *directory, char *fname)
  188. {
  189.   if (!*fname)
  190.     return bm[EXEC_BM];
  191.   else {
  192.     struct stat stats;
  193.     Boolean sym_link;
  194.     int l;
  195.     char *path;
  196.  
  197.     if (*directory) {
  198.       l = strlen(directory);
  199.       path = strcpy(alloca(l+strlen(fname)+2), directory);
  200.     } else {
  201.       l = strlen(user.home);
  202.       path = strcpy(alloca(l+strlen(fname)+2), user.home);
  203.     }
  204.  
  205.     if (l) {
  206.       if (path[l-1] != '/')
  207.     path[l++] = '/';
  208.       strcpy(path+l, fname);
  209.     } else
  210.       strcpy(path, fname);
  211.  
  212.     if (lstat(path, &stats))
  213.       return bm[FILE_BM];
  214.     else if (S_ISLNK(stats.st_mode)) {
  215.       sym_link = True;
  216.       stat(path, &stats);
  217.     } else
  218.       sym_link = False;
  219.  
  220.     if (S_ISLNK(stats.st_mode))
  221.       return bm[BLACKHOLE_BM];
  222.     else if (S_ISDIR(stats.st_mode))
  223.       if (sym_link)
  224.     return bm[DIRLNK_BM];
  225.       else if (!strcmp(name, ".."))
  226.     return bm[UPDIR_BM];
  227.       else
  228.     return bm[DIR_BM];
  229.     else if (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
  230.       if (sym_link)
  231.     return bm[EXECLNK_BM];
  232.       else
  233.     return bm[EXEC_BM];
  234.     else if (sym_link)
  235.       return bm[SYMLNK_BM];
  236.     else
  237.       return bm[FILE_BM];
  238.   }
  239. }
  240.  
  241. /*-----------------------------------------------------------------------------
  242.   PUBLIC FUNCTIONS
  243. -----------------------------------------------------------------------------*/
  244.  
  245. void createApplicationWindow()
  246. {
  247.   XtTranslations t;
  248.  
  249.   /* Add new actions and parse the translation tables */
  250.   XtAppAddActions(app_context, app_actions, XtNumber(app_actions));
  251.  
  252.   t = XtParseTranslationTable(app_translations);
  253.   icon_toggle_args[3].value = (XtArgVal) t;
  254.  
  255.   t = XtParseTranslationTable(iconbox_translations);
  256.   icon_box_args[1].value = (XtArgVal) t;
  257.  
  258.   icon_label_args[3].value = (XtArgVal) resources.icon_font;
  259.  
  260.   /* create the install application popup */
  261.   createInstallPopup();
  262.  
  263.   /* create the menus */
  264.   app_popup_items = createFloatingMenu("app popup", app_popup_menu,
  265.                        XtNumber(app_popup_menu), 4, aw.shell,
  266.                        NULL, &app_popup_widget);
  267.   createFloatingMenu("app popup 1", app_popup_menu1,
  268.              XtNumber(app_popup_menu1), 4, aw.shell,
  269.              NULL, &app_popup_widget1);
  270.  
  271.   XtRegisterGrabAction(appPopup, True, ButtonPressMask | ButtonReleaseMask,
  272.                GrabModeAsync, GrabModeAsync);
  273.  
  274.   /* create the form */
  275.   aw.form = XtCreateManagedWidget("form", formWidgetClass, aw.shell,
  276.                   form_args, XtNumber(form_args) );
  277.   
  278.   /* create the viewport */
  279.   aw.viewport = XtCreateManagedWidget("viewport", viewportWidgetClass,
  280.     aw.form, viewport_args, XtNumber(viewport_args) );
  281.  
  282.   aw.n_selections = 0;
  283. }
  284.  
  285. /*---------------------------------------------------------------------------*/
  286.  
  287. void createApplicationDisplay()
  288. {
  289.   int i;
  290.   Dimension width;
  291.  
  292.   for (i=0; i<aw.n_apps; i++)
  293.     aw.apps[i].selected = False;
  294.   aw.n_selections = 0;
  295.   
  296.   XtVaGetValues(aw.viewport, XtNwidth, &width, NULL);
  297.   icon_box_args[0].value = (XtArgVal) width;
  298.  
  299.   aw.icon_box = XtCreateWidget("icon box", boxWidgetClass,
  300.     aw.viewport, icon_box_args, XtNumber(icon_box_args) );
  301.  
  302.   if (aw.n_apps == 0)
  303.     XtVaCreateManagedWidget("label", labelWidgetClass, aw.icon_box,
  304.                 XtNlabel, "No configured applications",
  305.                 XtNfont, resources.label_font, NULL);
  306.   else {
  307.     width = longestName();
  308.     if (width < resources.app_icon_width)
  309.       width = resources.app_icon_width;
  310.     icon_form_args[1].value = (XtArgVal) width;
  311.     icon_label_args[4].value = (XtArgVal) width;
  312.     icon_toggle_args[4].value = (XtArgVal) width;
  313.     icon_toggle_args[5].value = (XtArgVal) resources.app_icon_height;
  314.     
  315.     for (i=0; i < aw.n_apps; i++) {
  316.       Pixel back;
  317.       aw.apps[i].form = XtCreateManagedWidget(aw.apps[i].name,
  318.                           formWidgetClass, aw.icon_box,
  319.                           icon_form_args,
  320.                           XtNumber(icon_form_args) );
  321.       icon_toggle_args[2].value = aw.apps[i].icon_bm;
  322.       aw.apps[i].toggle = XtCreateManagedWidget("icon", toggleWidgetClass,
  323.                         aw.apps[i].form,
  324.                         icon_toggle_args,
  325.                         XtNumber(icon_toggle_args) );
  326.       XtVaGetValues(aw.apps[i].toggle, XtNbackground, &back, NULL);
  327.       XtVaSetValues(aw.apps[i].toggle, XtNborder, (XtArgVal) back, NULL);
  328.  
  329.       icon_label_args[1].value = (XtArgVal) aw.apps[i].toggle;
  330.       icon_label_args[2].value = (XtArgVal) aw.apps[i].name;
  331.       aw.apps[i].label = XtCreateManagedWidget("label", labelWidgetClass,
  332.                            aw.apps[i].form,
  333.                            icon_label_args,
  334.                            XtNumber(icon_label_args) );
  335.     };
  336.   }
  337.  
  338.   XtManageChild(aw.icon_box);
  339. }
  340.  
  341. /*---------------------------------------------------------------------------*/
  342.  
  343. void updateApplicationDisplay()
  344. {
  345.   XtDestroyWidget(aw.icon_box);
  346.   createApplicationDisplay();
  347. }
  348.  
  349. /*---------------------------------------------------------------------------*/
  350.  
  351. void readApplicationBitmaps()
  352. {
  353.   int i;
  354.  
  355.   for (i=0; i<aw.n_apps; i++) {
  356.     aw.apps[i].loaded = False;
  357.     if (!aw.apps[i].icon[0])
  358.       aw.apps[i].icon_bm = defaultIcon(aw.apps[i].name, aw.apps[i].directory,
  359.                        aw.apps[i].fname);
  360.     else if ((aw.apps[i].icon_bm = readIcon(aw.apps[i].icon)) == None) {
  361.       fprintf(stderr, "%s: can't read icon for application %s\n",
  362.           progname, aw.apps[i].name);
  363.       aw.apps[i].icon_bm = defaultIcon(aw.apps[i].name, aw.apps[i].directory,
  364.                        aw.apps[i].fname);
  365.     } else
  366.       aw.apps[i].loaded = True;
  367.   }
  368. }
  369.  
  370. /*---------------------------------------------------------------------------*/
  371.  
  372. void readApplicationData(String path)
  373. {
  374.   FILE *fp;
  375.   char *name, *directory, *fname, *icon, *push_action, *drop_action;
  376.   char s[MAXAPPSTRINGLEN];
  377.   int i, p;
  378.   
  379.   aw.n_apps = 0;
  380.   aw.apps = NULL;
  381.   aw.modified = False;
  382.   
  383.   if (!(fp = fopen(path, "r"))) return;
  384.  
  385.   for (i=0; (p = parseApp(fp, &name, &directory, &fname, &icon, &push_action,
  386.               &drop_action)) > 0; i++) {
  387.     aw.apps = (AppList) XTREALLOC(aw.apps, (i+1)*sizeof(AppRec) );
  388.     aw.apps[i].name = XtNewString(strparse(s, name, "\\:"));
  389.     aw.apps[i].directory = XtNewString(strparse(s, directory, "\\:"));
  390.     aw.apps[i].fname = XtNewString(strparse(s, fname, "\\:"));
  391.     aw.apps[i].icon = XtNewString(strparse(s, icon, "\\:"));
  392.     aw.apps[i].push_action = XtNewString(strparse(s, push_action, "\\:"));
  393.     aw.apps[i].drop_action = XtNewString(strparse(s, drop_action, "\\:"));
  394.   }
  395.  
  396.   if (p == -1)
  397.     error("Error in applications file", "");
  398.  
  399.   aw.n_apps = i;
  400.   
  401.   if (fclose(fp))
  402.     sysError("Error reading applications file:");
  403.  
  404.   readApplicationBitmaps();
  405. }
  406.  
  407. /*---------------------------------------------------------------------------*/
  408.  
  409. int writeApplicationData(String path)
  410. {
  411.   FILE *fp;
  412.   int i;
  413.   time_t t;
  414.   char name[2*MAXAPPSTRINGLEN], directory[2*MAXAPPSTRINGLEN],
  415.     fname[2*MAXAPPSTRINGLEN], icon[2*MAXAPPSTRINGLEN],
  416.     push_action[2*MAXAPPSTRINGLEN], drop_action[2*MAXAPPSTRINGLEN];
  417.   
  418.   if (! (fp = fopen(path, "w") )) {
  419.     sysError("Error writing applications file:");
  420.     return -1;
  421.   }
  422.  
  423.   time(&t);
  424.   fprintf(fp,
  425. "#\n\
  426. # xfm applications file\n\
  427. # written by xfm  %s\
  428. #\n\
  429. ##########################################\n\
  430. \n", ctime(&t));
  431.  
  432.   for (i=0; i < aw.n_apps; i++) {
  433.     expand(name, aw.apps[i].name, "\\:");
  434.     expand(directory, aw.apps[i].directory, "\\:");
  435.     expand(fname, aw.apps[i].fname, "\\:");
  436.     expand(icon, aw.apps[i].icon, "\\:");
  437.     expand(push_action, aw.apps[i].push_action, "\\:");
  438.     expand(drop_action, aw.apps[i].drop_action, "\\:");
  439.     fprintf(fp, "%s:%s:%s:%s:%s:%s\n", name, directory, fname, icon,
  440.         push_action, drop_action);
  441.   }
  442.   
  443.   if (fclose(fp)) {
  444.     sysError("Error writing applications file:");
  445.     return -1;
  446.   }
  447.  
  448.   aw.modified = False;
  449.   return 0;
  450. }
  451.  
  452. /*---------------------------------------------------------------------------*/
  453.  
  454. void freeApplicationResources(AppRec *app)
  455. {
  456.   if (app->loaded)
  457.     XFreePixmap(XtDisplay(aw.shell), app->icon_bm);
  458.   XTFREE(app->name);
  459.   XTFREE(app->directory);
  460.   XTFREE(app->fname);
  461.   XTFREE(app->icon);
  462.   XTFREE(app->push_action);
  463.   XTFREE(app->drop_action);
  464. }
  465.  
  466. /*---------------------------------------------------------------------------*/
  467.  
  468. void removeApplication(int i)
  469. {
  470.   int size;
  471.  
  472.   freeApplicationResources(&aw.apps[i]);
  473.   if (size = (aw.n_apps - i - 1) * sizeof(AppRec))
  474.     memcpy(&aw.apps[i], &aw.apps[i+1], size);
  475.   aw.n_apps--;
  476.   aw.apps = (AppRec *) XTREALLOC(aw.apps, aw.n_apps * sizeof(AppRec));
  477.   aw.modified = True;
  478. }  
  479.  
  480. /*---------------------------------------------------------------------------*/
  481.  
  482. void moveApplication(int i)
  483. {
  484.   int size;
  485.   AppRec app;
  486.  
  487.   memcpy(&app, &aw.apps[i], sizeof(AppRec));
  488.   if (size = (aw.n_apps - i - 1) * sizeof(AppRec))
  489.     memcpy(&aw.apps[i], &aw.apps[i+1], size);
  490.   memcpy(&aw.apps[aw.n_apps-1], &app, sizeof(AppRec));
  491.   aw.modified = True;
  492. }  
  493.  
  494. /*---------------------------------------------------------------------------*/
  495.  
  496. void installApplication(char *name, char *directory, char *fname, char *icon,
  497.             char *push_action, char *drop_action)
  498. {
  499.   int i;
  500.   Pixmap icon_bm;
  501.   Boolean loaded = False;
  502.  
  503.   if (!*icon)
  504.     icon_bm = defaultIcon(name, directory, fname);
  505.   else if ((icon_bm = readIcon(icon)) == None) {
  506.     error("Can't read icon for", name);
  507.     icon_bm = defaultIcon(name, directory, fname);
  508.   } else
  509.     loaded = True;
  510.  
  511.   i = aw.n_apps++;
  512.   aw.apps = (AppList) XTREALLOC(aw.apps, aw.n_apps * sizeof(AppRec));
  513.  
  514.   aw.apps[i].name = XtNewString(name);
  515.   aw.apps[i].directory = XtNewString(directory);
  516.   aw.apps[i].fname = XtNewString(fname);
  517.   aw.apps[i].icon = XtNewString(icon);
  518.   aw.apps[i].push_action = XtNewString(push_action);
  519.   aw.apps[i].drop_action = XtNewString(drop_action);
  520.   aw.apps[i].icon_bm = icon_bm;
  521.   aw.apps[i].loaded = loaded;
  522.   aw.apps[i].form = aw.apps[i].toggle = aw.apps[i].label = NULL;
  523.   aw.modified = True;
  524. }
  525.  
  526. /*---------------------------------------------------------------------------*/
  527.  
  528. void replaceApplication(AppRec *app, char *name, char *directory, char *fname,
  529.             char *icon, char *push_action, char *drop_action)
  530. {
  531.   Pixmap icon_bm;
  532.   Boolean loaded = False;
  533.  
  534.   freeApplicationResources(app);
  535.   if (!*icon)
  536.     icon_bm = defaultIcon(name, directory, fname);
  537.   else if ((icon_bm = readIcon(icon)) == None) {
  538.     error("Can't read icon for", name);
  539.     icon_bm = defaultIcon(name, directory, fname);
  540.   } else
  541.     loaded = True;
  542.  
  543.   app->name = XtNewString(name);
  544.   app->directory = XtNewString(directory);
  545.   app->fname = XtNewString(fname);
  546.   app->icon = XtNewString(icon);
  547.   app->push_action = XtNewString(push_action);
  548.   app->drop_action = XtNewString(drop_action);
  549.   app->icon_bm = icon_bm;
  550.   app->loaded = loaded;
  551.   app->form = app->toggle = app->label = NULL;
  552.   aw.modified = True;
  553. }
  554.