home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / xap / xfm / xfm-1.000 / xfm-1 / xfm-1.3.2 / src / FmAwActions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-13  |  15.3 KB  |  572 lines

  1. /*---------------------------------------------------------------------------
  2.   Module FmAwActions
  3.   
  4.   (c) Simon Marlow 1990-92
  5.   (c) Albert Graef 1994
  6.  
  7.   Action procedures for widgets in the application window
  8. ---------------------------------------------------------------------------*/
  9.  
  10. #include <string.h>
  11.  
  12. #include <X11/Intrinsic.h>
  13. #include <X11/StringDefs.h>
  14. #include <X11/Xaw/Toggle.h>
  15.  
  16. #include "Am.h"
  17.  
  18. /*---------------------------------------------------------------------------
  19.   PRIVATE FUNCTIONS
  20. ---------------------------------------------------------------------------*/
  21.  
  22. /* determine the cursor type for an application */
  23.  
  24. static Cursor cursorType(char *name, char *directory, char *fname)
  25. {
  26.   if (!*fname)
  27.     return curs[EXEC_CUR];
  28.   else {
  29.     struct stat stats;
  30.     int l = *directory?strlen(directory):strlen(user.home);
  31.     char *path = (char *)alloca(2+strlen(fname)+l);
  32.     
  33.     strcpy(path, *directory?directory:user.home);
  34.  
  35.     if (l) {
  36.       if (path[l-1] != '/')
  37.     path[l++] = '/';
  38.       strcpy(path+l, fname);
  39.     } else
  40.       strcpy(path, fname);
  41.  
  42.     if (lstat(path, &stats))
  43.       return curs[FILE_CUR];
  44.     else if (S_ISDIR(stats.st_mode))
  45.       return curs[DIR_CUR];
  46.     else if (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
  47.       return curs[EXEC_CUR];
  48.     else
  49.       return curs[FILE_CUR];
  50.   }
  51. }
  52.  
  53. /*---------------------------------------------------------------------------*/
  54.  
  55. /* perform a click-drag, returning the widget that the user released the 
  56.    button on */
  57.  
  58. static Boolean dragging_app = False;
  59.  
  60. static Widget drag(Widget w, int button,
  61.            Boolean *on_root_return)
  62. {
  63.   Cursor c;
  64.   XEvent e;
  65.   int i, x, y;
  66.   Window child;
  67.  
  68.   if (aw.n_selections == 1) {
  69.     for (i=0; !aw.apps[i].selected && i<aw.n_apps;
  70.      i++);
  71.     c = cursorType(aw.apps[i].name, aw.apps[i].directory, aw.apps[i].fname);
  72.   } else
  73.     c = curs[FILES_CUR];
  74.  
  75.   XGrabPointer(XtDisplay(w), XtWindow(w), True,
  76.            EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  77.            GrabModeAsync, GrabModeAsync, None, c, CurrentTime);
  78.  
  79.   freeze = dragging_app = True;
  80.   
  81.   for (;;) {
  82.     XtAppNextEvent(app_context, &e);
  83.     switch (e.type) {
  84.     case ButtonPress:        /* Ignore button presses */
  85.       continue;
  86.     case ButtonRelease:      /* Ignore button releases except 2 */
  87.       if (e.xbutton.button != button)
  88.     continue;
  89.       break;
  90.     default:
  91.       XtDispatchEvent(&e);
  92.       continue;
  93.     }
  94.     break;
  95.   }
  96.  
  97.   XUngrabPointer(XtDisplay(aw.shell),CurrentTime);
  98.   XtDispatchEvent(&e);
  99.   freeze = dragging_app = False;
  100.   
  101.   /* Find out if the drag was released on the root window (child = None) */
  102.   XTranslateCoordinates(XtDisplay(w),e.xbutton.window,e.xbutton.root,
  103.             e.xbutton.x,e.xbutton.y,&x,&y,&child);
  104.   if (child == None)
  105.     *on_root_return = True;
  106.   else
  107.     *on_root_return = False;
  108.  
  109.   return XtWindowToWidget(XtDisplay(w),e.xbutton.window);
  110. }
  111.  
  112. /*---------------------------------------------------------------------------
  113.   PUBLIC FUNCTIONS
  114. ---------------------------------------------------------------------------*/
  115.  
  116. int findAppWidget(Widget w)
  117. {
  118.   int i;
  119.  
  120.   for (i=0; i<aw.n_apps; i++)
  121.     if (aw.apps[i].toggle == w)
  122.       return i;
  123.   return -1;
  124. }
  125.  
  126. /*---------------------------------------------------------------------------*/
  127.  
  128. void appPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
  129. {
  130.   Display *dpy;
  131.   Window root, child;
  132.   int x, y, x_win, y_win;
  133.   unsigned int mask;
  134.   int i = findAppWidget(w);
  135.  
  136.   dpy = XtDisplay(aw.shell);
  137.  
  138.   XQueryPointer(dpy, XtWindow(w), &root, &child, &x, &y, 
  139.         &x_win, &y_win, &mask);
  140.  
  141.   /* check whether icon was selected */
  142.   if (child != None) {
  143.     XTranslateCoordinates(dpy, XtWindow(w), child, x_win, y_win,
  144.               &x_win, &y_win, &child);
  145.     if (child != None) w = XtWindowToWidget(dpy, child);
  146.   }
  147.  
  148.   i = findAppWidget(w);
  149.   if (i != -1) appSelect(w, event, params, num_params);
  150.  
  151.   if (i == -1) {
  152.     struct stat stats;
  153.     if (aw.n_selections == 0) {
  154.       grayOut(app_popup_items[3]);
  155.       grayOut(app_popup_items[4]);
  156.       grayOut(app_popup_items[7]);
  157.       grayOut(app_popup_items[10]);
  158.     } else {
  159.       fillIn(app_popup_items[3]);
  160.       fillIn(app_popup_items[4]);
  161.       fillIn(app_popup_items[7]);
  162.       fillIn(app_popup_items[10]);
  163.     }
  164.     if (stat(resources.app_clip, &stats))
  165.       grayOut(app_popup_items[5]);
  166.     else
  167.       fillIn(app_popup_items[5]);
  168.  
  169.     XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &x, &y, 
  170.           &x_win, &y_win, &mask);
  171.   
  172.     XtVaSetValues(app_popup_widget, XtNx, (XtArgVal) x, XtNy, (XtArgVal) y,
  173.           NULL);
  174.   
  175.     XtPopupSpringLoaded(app_popup_widget);
  176.   } else {
  177.     XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &x, &y, 
  178.           &x_win, &y_win, &mask);
  179.   
  180.     XtVaSetValues(app_popup_widget1, XtNx, (XtArgVal) x, XtNy, (XtArgVal) y,
  181.           NULL);
  182.   
  183.     XtPopupSpringLoaded(app_popup_widget1);
  184.   }
  185. }  
  186.  
  187. /*---------------------------------------------------------------------------*/
  188.  
  189. void appMaybeHighlight(Widget w, XEvent *event, String *params, 
  190.                Cardinal *num_params)
  191. {
  192.   int i;
  193.  
  194.   if (dragging) {
  195.     i = findAppWidget(w);
  196.     if (*aw.apps[i].drop_action)
  197.       XtCallActionProc(w, "highlight", event, NULL, 0);
  198.   } else if (dragging_app)
  199.     XtCallActionProc(w, "highlight", event, NULL, 0);
  200. }
  201.  
  202. /*---------------------------------------------------------------------------*/
  203.  
  204. void runApp(Widget w, XEvent *event, String *params, Cardinal *num_params)
  205. {
  206.   int i;
  207.   char **argv;
  208.   char directory[MAXPATHLEN];
  209.  
  210.   i = findAppWidget(w);
  211.   strcpy(directory, aw.apps[i].directory);
  212.   if (*directory)
  213.     fnexpand(directory);
  214.   else
  215.     strcpy(directory, user.home);
  216.  
  217.   if (*aw.apps[i].push_action)
  218.     if (!strcmp(aw.apps[i].push_action, "EDIT"))
  219.       doEdit(directory, aw.apps[i].fname);
  220.     else if (!strcmp(aw.apps[i].push_action, "VIEW"))
  221.       doView(directory, aw.apps[i].fname);
  222.     else if (!strcmp(aw.apps[i].push_action, "OPEN")) {
  223.       int l = strlen(directory);
  224.       if (directory[l-1] != '/')
  225.     directory[l++] = '/';
  226.       strcpy(directory+l, aw.apps[i].fname);
  227.       newFileWindow(directory, resources.default_display_type,
  228.             False);
  229.     } else if (!strcmp(aw.apps[i].push_action, "LOAD")) {
  230.       int j, l = strlen(directory);
  231.       zzz();
  232.       pushApplicationsFile();
  233.       strcpy(resources.app_file, directory);
  234.       if (resources.app_file[l-1] != '/')
  235.     resources.app_file[l++] = '/';
  236.       strcpy(resources.app_file+l, aw.apps[i].fname);
  237.       for(j=0; j<aw.n_apps; j++)
  238.     freeApplicationResources(&aw.apps[j]);
  239.       XTFREE(aw.apps);
  240.       readApplicationData(resources.app_file);
  241.       updateApplicationDisplay();
  242.       wakeUp();
  243.     } else {
  244.       char *action = varPopup(aw.apps[i].icon_bm, aw.apps[i].push_action);
  245.       if (!action) return;
  246.       if (*aw.apps[i].fname)
  247.     argv = makeArgv2(action, aw.apps[i].fname);
  248.       else
  249.     argv = makeArgv(action);
  250.       executeApplication(user.shell, directory, argv);
  251.       freeArgv(argv);
  252.     }
  253. }
  254.  
  255. /*---------------------------------------------------------------------------*/
  256.  
  257. void appBeginDrag(Widget w, XEvent *event, String *params, 
  258.           Cardinal *num_params)
  259. {
  260.   int i, button;
  261.   Boolean on_root_return, move = True;
  262.  
  263.   if (*num_params != 2) {
  264.     error("Internal error:","wrong number of parameters to appBeginDrag");
  265.     return;
  266.   }
  267.  
  268.   button = *params[0] - '0';
  269.   if (!strcmp(params[1],"copy"))
  270.     move = False;
  271.  
  272.   i =  findAppWidget(w);
  273.   
  274.   if (i != -1) {
  275.     if (!aw.apps[i].selected)
  276.       appSelect(w, event, params, num_params);
  277.   } else
  278.     return;
  279.   
  280.   if (!(w = drag(w,button,&on_root_return)))
  281.     return;
  282.   else if (on_root_return)
  283.     return;
  284.  
  285.   if (w == aw.icon_box)
  286.     if (move)
  287.       appEndMoveInBox();
  288.     else
  289.       appEndCopyInBox();
  290.   else if ((i = findAppWidget(w)) != -1)
  291.     if (move)
  292.       appEndMove(i);
  293.     else
  294.       appEndCopy(i);
  295. }
  296.   
  297. /*---------------------------------------------------------------------------*/
  298.  
  299. void appEndMoveInBox(void)
  300. {
  301.   char s[0xff];
  302.   int j, k, l;
  303.   AppRec *apps;
  304.  
  305.   if (aw.n_selections == 0) return;
  306.  
  307.   if (resources.confirm_moves) {
  308.     sprintf(s, "Moving %d item%s in", aw.n_selections,
  309.         aw.n_selections > 1 ? "s" : "" );
  310.     if (!confirm(s, "the application window", ""))
  311.       return;
  312.   }
  313.  
  314.   apps = (AppRec*) XtMalloc(aw.n_apps*sizeof(AppRec));
  315.   for (j = k = 0, l = aw.n_apps - aw.n_selections; j < aw.n_apps; j++)
  316.     if (aw.apps[j].selected)
  317.       memcpy(&apps[l++], &aw.apps[j], sizeof(AppRec));
  318.     else
  319.       memcpy(&apps[k++], &aw.apps[j], sizeof(AppRec));
  320.   XTFREE(aw.apps);
  321.   aw.apps = apps;
  322.   updateApplicationDisplay();
  323.   writeApplicationData(resources.app_file);
  324. }
  325.  
  326. /*---------------------------------------------------------------------------*/
  327.  
  328. void appEndMove(int i)
  329. {
  330.   char s[0xff];
  331.   int j, k, l, m;
  332.   AppRec *apps;
  333.  
  334.   if (aw.n_selections == 0 || aw.apps[i].selected) return;
  335.  
  336.   if (resources.confirm_moves) {
  337.     sprintf(s, "Moving %d item%s in", aw.n_selections,
  338.         aw.n_selections > 1 ? "s" : "" );
  339.     if (!confirm(s, "the application window", ""))
  340.       return;
  341.   }
  342.  
  343.   apps = (AppRec*) XtMalloc(aw.n_apps*sizeof(AppRec));
  344.   for (j = l = 0; j < i; j++)
  345.     if (!aw.apps[j].selected) l++;
  346.   for (j = k = 0, m = l + aw.n_selections; j < aw.n_apps; j++)
  347.     if (aw.apps[j].selected)
  348.       memcpy(&apps[l++], &aw.apps[j], sizeof(AppRec));
  349.     else if (j < i)
  350.       memcpy(&apps[k++], &aw.apps[j], sizeof(AppRec));
  351.     else
  352.       memcpy(&apps[m++], &aw.apps[j], sizeof(AppRec));
  353.   XTFREE(aw.apps);
  354.   aw.apps = apps;
  355.   updateApplicationDisplay();
  356.   writeApplicationData(resources.app_file);
  357. }
  358.  
  359. /*---------------------------------------------------------------------------*/
  360.  
  361. static void copyApps(void)
  362. {
  363.   int j, n_apps = aw.n_apps;
  364.  
  365.   aw.apps = (AppList) XTREALLOC(aw.apps, (aw.n_apps+aw.n_selections) *
  366.                       sizeof(AppRec));
  367.   for (j=0; j<n_apps; j++)
  368.     if (aw.apps[j].selected) {
  369.       Pixmap icon_bm;
  370.       Boolean loaded = False;
  371.       if (aw.apps[j].loaded)
  372.     if ((icon_bm = readIcon(aw.apps[j].icon)) == None) {
  373.       error("Can't read icon for", aw.apps[j].name);
  374.       icon_bm = defaultIcon(aw.apps[j].name, aw.apps[j].directory,
  375.                 aw.apps[j].fname);
  376.     } else
  377.       loaded = True;
  378.       else
  379.     icon_bm = aw.apps[j].icon_bm;
  380.       aw.apps[aw.n_apps].name = XtNewString(aw.apps[j].name);
  381.       aw.apps[aw.n_apps].directory = XtNewString(aw.apps[j].directory);
  382.       aw.apps[aw.n_apps].fname = XtNewString(aw.apps[j].fname);
  383.       aw.apps[aw.n_apps].icon = XtNewString(aw.apps[j].icon);
  384.       aw.apps[aw.n_apps].push_action = XtNewString(aw.apps[j].push_action);
  385.       aw.apps[aw.n_apps].drop_action = XtNewString(aw.apps[j].drop_action);
  386.       aw.apps[aw.n_apps].icon_bm = icon_bm;
  387.       aw.apps[aw.n_apps].loaded = loaded;
  388.       aw.apps[aw.n_apps].form = aw.apps[aw.n_apps].toggle =
  389.     aw.apps[aw.n_apps].label = NULL;
  390.       aw.n_apps++;
  391.     }
  392. }
  393.  
  394. /*---------------------------------------------------------------------------*/
  395.  
  396. void appEndCopyInBox(void)
  397. {
  398.   char s[0xff];
  399.   if (aw.n_selections == 0) return;
  400.  
  401.   if (resources.confirm_copies) {
  402.     sprintf(s, "Copying %d item%s in", aw.n_selections,
  403.         aw.n_selections > 1 ? "s" : "" );
  404.     if (!confirm(s, "the application window", ""))
  405.       return;
  406.   }
  407.  
  408.   copyApps();
  409.   updateApplicationDisplay();
  410.   writeApplicationData(resources.app_file);
  411. }
  412.  
  413. /*---------------------------------------------------------------------------*/
  414.  
  415. void appEndCopy(int i)
  416. {
  417.   char s[0xff];
  418.   int n_apps = aw.n_apps;
  419.   AppRec *apps;
  420.  
  421.   if (aw.n_selections == 0) return;
  422.  
  423.   if (resources.confirm_copies) {
  424.     sprintf(s, "Copying %d item%s in", aw.n_selections,
  425.         aw.n_selections > 1 ? "s" : "" );
  426.     if (!confirm(s, "the application window", ""))
  427.       return;
  428.   }
  429.  
  430.   copyApps();
  431.   apps = (AppRec*) XtMalloc(aw.n_apps * sizeof(AppRec));
  432.   memcpy(apps, aw.apps, i*sizeof(AppRec));
  433.   memcpy(&apps[i], &aw.apps[n_apps], (aw.n_apps-n_apps)*sizeof(AppRec));
  434.   memcpy(&apps[i+aw.n_apps-n_apps], &aw.apps[i], (n_apps-i)*sizeof(AppRec));
  435.   XTFREE(aw.apps);
  436.   aw.apps = apps;
  437.   updateApplicationDisplay();
  438.   writeApplicationData(resources.app_file);
  439. }
  440.  
  441. /*---------------------------------------------------------------------------*/
  442.  
  443. void appEndDrag(int i)
  444. {
  445.   char **argv;
  446.  
  447.   if (*aw.apps[i].drop_action) {
  448.     char *action = varPopup(aw.apps[i].icon_bm, aw.apps[i].drop_action);
  449.     if (!action) return;
  450.     if (*aw.apps[i].fname) {
  451.       int l;
  452.       char path[MAXPATHLEN];
  453.       strcpy(path, aw.apps[i].directory);
  454.       if (*path)
  455.     fnexpand(path);
  456.       else
  457.     strcpy(path, user.home);
  458.       l = strlen(path);
  459.       if (path[l-1] != '/')
  460.     path[l++] = '/';
  461.       strcpy(path+l, aw.apps[i].fname);
  462.       argv = makeArgv2(action, path);
  463.     } else
  464.       argv = makeArgv(action);
  465.     argv = expandArgv(argv);
  466.     executeApplication(user.shell, move_info.fw->directory, argv);
  467.     freeArgv(argv);
  468.   }
  469. }
  470.  
  471. /*---------------------------------------------------------------------------*/
  472.  
  473. void appEndDragInBox(void)
  474. {
  475.   int i;
  476.  
  477.   for (i=0; i<move_info.fw->n_files; i++)
  478.     if (move_info.fw->files[i]->selected) {
  479.       if (S_ISDIR(move_info.fw->files[i]->stats.st_mode)) {
  480.     installApplication(move_info.fw->files[i]->name,
  481.                move_info.fw->directory,
  482.                move_info.fw->files[i]->name,
  483.                move_info.fw->files[i]->type?
  484.                move_info.fw->files[i]->type->icon:"",
  485.                "OPEN",
  486.                "");
  487.       } else if (move_info.fw->files[i]->stats.st_mode &
  488.          (S_IXUSR | S_IXGRP | S_IXOTH)) {
  489.     char *push_action, *drop_action;
  490.     push_action = move_info.fw->files[i]->name;
  491.     drop_action = (char *)alloca(strlen(push_action)+4);
  492.     strcpy(drop_action, push_action);
  493.     strcat(drop_action, " $*");
  494.     installApplication(move_info.fw->files[i]->name,
  495.                move_info.fw->directory,
  496.                "",
  497.                move_info.fw->files[i]->type?
  498.                move_info.fw->files[i]->type->icon:"",
  499.                push_action,
  500.                drop_action);
  501.       } else if (move_info.fw->files[i]->type) {
  502.     installApplication(move_info.fw->files[i]->name,
  503.                move_info.fw->directory,
  504.                move_info.fw->files[i]->name,
  505.                move_info.fw->files[i]->type->icon,
  506.                move_info.fw->files[i]->type->push_action,
  507.                move_info.fw->files[i]->type->drop_action);
  508.       } else {
  509.     installApplication(move_info.fw->files[i]->name,
  510.                move_info.fw->directory,
  511.                move_info.fw->files[i]->name,
  512.                "",
  513.                "EDIT",
  514.                "");
  515.       }
  516.     }
  517.   updateApplicationDisplay();
  518.   writeApplicationData(resources.app_file);
  519. }
  520.  
  521. /*---------------------------------------------------------------------------*/
  522.  
  523. void appSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
  524. {
  525.   int i, j;
  526.   Pixel back, fore;
  527.   
  528.   j = findAppWidget(w);
  529.   if (j == -1) {
  530.     error("Internal error:", "widget not found in appSelect");
  531.     return;
  532.   }
  533.   
  534.   for (i=0; i<aw.n_apps; i++)
  535.     if (aw.apps[i].selected) {
  536.       XtVaGetValues(aw.apps[i].toggle, XtNbackground, &back, NULL);
  537.       XtVaSetValues(aw.apps[i].toggle, XtNborder, (XtArgVal) back, NULL);
  538.       aw.apps[i].selected = False;
  539.     }
  540.  
  541.   XtVaGetValues(w, XtNforeground, &fore, NULL);
  542.   XtVaSetValues(w, XtNborder, (XtArgVal) fore, NULL);
  543.   
  544.   aw.apps[j].selected = True;
  545.   aw.n_selections = 1;
  546. }
  547.  
  548. /*---------------------------------------------------------------------------*/
  549.  
  550. void appToggle(Widget w, XEvent *event, String *params, Cardinal *num_params)
  551. {
  552.   int i;
  553.   Pixel pix;
  554.   
  555.   i = findAppWidget(w);
  556.   if (i == -1) {
  557.     error("Internal error:", "widget not found in appToggle");
  558.     return;
  559.   }
  560.   
  561.   XtVaGetValues(w, aw.apps[i].selected?XtNbackground:XtNforeground, &pix,
  562.         NULL);
  563.   XtVaSetValues(w, XtNborder, (XtArgVal) pix, NULL);
  564.   
  565.   aw.apps[i].selected = !aw.apps[i].selected;
  566.   if (aw.apps[i].selected)
  567.     aw.n_selections++;
  568.   else
  569.     aw.n_selections--;
  570. }
  571.  
  572.