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 / FmFwActions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-09  |  20.6 KB  |  872 lines

  1. /*---------------------------------------------------------------------------
  2.   Module FmFwActions
  3.  
  4.   (c) Simon Marlow 1990-92
  5.   (c) Albert Graef 1994
  6.  
  7.   Action procedures for widgets in a file window
  8. ---------------------------------------------------------------------------*/
  9.  
  10.  
  11. #include <stdio.h>
  12. #include <unistd.h>
  13.  
  14. #include <X11/Intrinsic.h>
  15. #include <X11/StringDefs.h>
  16. #include <X11/Xaw/Toggle.h>
  17.  
  18. #include "Am.h"
  19. #include "Fm.h"
  20.  
  21. /*---------------------------------------------------------------------------
  22.   PUBLIC DATA
  23. ---------------------------------------------------------------------------*/
  24.  
  25. MoveInfo move_info;
  26. Boolean dragging = False;
  27. Cursor drag_cursor;
  28.  
  29. /*---------------------------------------------------------------------------
  30.   STATIC DATA
  31. ---------------------------------------------------------------------------*/
  32.  
  33. static char from[MAXPATHLEN], to[MAXPATHLEN];
  34. static int fromi, toi;
  35.  
  36. /*---------------------------------------------------------------------------
  37.   PRIVATE FUNCTIONS
  38. ---------------------------------------------------------------------------*/
  39.  
  40. static int findWidget(Widget w, FileWindowRec **fw_ret)
  41. {
  42.   int i;
  43.   FileWindowRec *fw;
  44.  
  45.   for (fw = file_windows; fw; fw = fw->next) {
  46.     if (fw->icon_box == w || fw->label == w) {
  47.       *fw_ret = fw;
  48.       return -1;
  49.     }
  50.     for (i = 0; i < fw->n_files; i++)
  51.       if (fw->files[i]->icon.toggle == w) {
  52.     *fw_ret = fw;
  53.     return i;
  54.       }
  55.   }
  56.   *fw_ret = NULL;
  57.   return 0;
  58. }
  59.  
  60. /*---------------------------------------------------------------------------*/
  61.  
  62. static int moveFiles()
  63. {
  64.   int i, n_moved = 0;
  65.  
  66.   if (from[fromi-1] != '/') {
  67.     from[fromi++] = '/';
  68.     from[fromi] = '\0';
  69.   }
  70.  
  71.   if (to[toi-1] != '/') {
  72.     to[toi++] = '/';
  73.     to[toi] = '\0';
  74.   }
  75.  
  76.   for (i=0; i < move_info.fw->n_files; i++)
  77.     if (move_info.fw->files[i]->selected) {
  78.       if (!strcmp(move_info.fw->files[i]->name, ".") ||
  79.       !strcmp(move_info.fw->files[i]->name, "..")) {
  80.     error("Cannot move . or ..", "");
  81.     continue;
  82.       }
  83.       strcpy(from+fromi, move_info.fw->files[i]->name);
  84.       strcpy(to+toi, move_info.fw->files[i]->name);
  85.       if (exists(to) && resources.confirm_overwrite) {
  86.     char s[0xff];
  87.     sprintf(s, "Move: file %s already exists at destination",
  88.         move_info.fw->files[i]->name);
  89.     if (!confirm(s, "Overwrite?", ""))
  90.       if (aborted)
  91.         break;
  92.       else
  93.         continue;
  94.       }
  95.       if (rename(from,to)) {
  96.     char s[0xff];
  97.     sprintf(s, "Error moving %s:", move_info.fw->files[i]->name);
  98.     sysError(s);
  99.       } else
  100.     n_moved++;
  101.     }
  102.  
  103.   return n_moved;
  104. }
  105.  
  106. /*---------------------------------------------------------------------------*/
  107.  
  108. static int copyFiles()
  109. {
  110.   int i, n_copied = 0;
  111.  
  112.   if (from[fromi-1] != '/') {
  113.     from[fromi++] = '/';
  114.     from[fromi] = '\0';
  115.   }
  116.  
  117.   if (to[toi-1] != '/') {
  118.     to[toi++] = '/';
  119.     to[toi] = '\0';
  120.   }
  121.  
  122.   for (i=0; i < move_info.fw->n_files; i++)
  123.     if (move_info.fw->files[i]->selected) {
  124.       if (!strcmp(move_info.fw->files[i]->name, ".") ||
  125.       !strcmp(move_info.fw->files[i]->name, "..")) {
  126.     error("Cannot copy . or ..", "");
  127.     continue;
  128.       }
  129.       strcpy(from+fromi, move_info.fw->files[i]->name);
  130.       strcpy(to+toi, move_info.fw->files[i]->name);
  131.       if (exists(to) && resources.confirm_overwrite) {
  132.     char s[0xff];
  133.     sprintf(s, "Copy: file %s already exists at destination",
  134.         move_info.fw->files[i]->name);
  135.     if (!confirm(s, "Overwrite?", ""))
  136.       if (aborted)
  137.         break;
  138.       else
  139.         continue;
  140.       }
  141.       if (rcopy(from,to)) {
  142.     char s[0xff];
  143.     sprintf(s, "Error copying %s:", move_info.fw->files[i]->name);
  144.     sysError(s);
  145.       } else
  146.     n_copied++;
  147.     }
  148.  
  149.   return n_copied;
  150. }
  151.  
  152. /*---------------------------------------------------------------------------*/
  153.  
  154. static int setupMoveCopy(FileWindowRec *fw, int i)
  155. {
  156.   strcpy(from, move_info.fw->directory);
  157.  
  158.   if (i != -1 && S_ISDIR(fw->files[i]->stats.st_mode)
  159.       && strcmp(fw->files[i]->name, ".")) {
  160.     if (chdir(fw->directory) || chdir(fw->files[i]->name) || !getwd(to)) {
  161.       sysError("System error:");
  162.       return 0;
  163.     }
  164.   } else
  165.     strcpy(to, fw->directory);
  166.     
  167.   toi = strlen(to);
  168.   fromi = strlen(from);
  169.  
  170.   return 1;
  171. }
  172.  
  173. /*---------------------------------------------------------------------------*/
  174.  
  175. static void fileEndMove(FileWindowRec *fw, int i)
  176. {
  177.   if (!setupMoveCopy(fw, i)) return;
  178.  
  179.   if (!strcmp(from, to)) {
  180.     error("Move:", "Source and destination are identical");
  181.     return;
  182.   }
  183.  
  184.   if (access(to, W_OK)) {
  185.     error("No write access to this directory","");
  186.     return;
  187.   }
  188.  
  189.   freeze = True;
  190.  
  191.   if (resources.confirm_moves) {
  192.     char s1[0xff], s2[0xff], s3[0xff];
  193.     sprintf(s1, "Moving %d item%c", move_info.fw->n_selections,
  194.         move_info.fw->n_selections > 1 ? 's' : ' ');
  195.     sprintf(s2, "from: %s", from);
  196.     sprintf(s3, "to: %s", to);
  197.     if (!confirm(s1, s2, s3))
  198.       goto out;
  199.   }
  200.  
  201.   if (moveFiles()) {
  202.     markForUpdate(from); markForUpdate(to);
  203.     intUpdate();
  204.   }
  205.  
  206.  out:
  207.   freeze = False;
  208. }
  209.  
  210. /*---------------------------------------------------------------------------*/
  211.  
  212. static void fileEndCopy(FileWindowRec *fw, int i)
  213. {
  214.   if (!setupMoveCopy(fw, i)) return;
  215.  
  216.   if (!strcmp(from, to)) {
  217.     error("Copy:", "Source and destination are identical");
  218.     return;
  219.   }
  220.  
  221.   if (access(to, W_OK)) {
  222.     error("No write access to this directory","");
  223.     return;
  224.   }
  225.  
  226.   freeze = True;
  227.  
  228.   if (resources.confirm_copies) {
  229.     char s1[0xff], s2[0xff], s3[0xff];
  230.     sprintf(s1, "Copying %d item%c", move_info.fw->n_selections,
  231.         move_info.fw->n_selections > 1 ? 's' : ' ');
  232.     sprintf(s2, "from: %s", from);
  233.     sprintf(s3, "to: %s", to);
  234.     if (!confirm(s1, s2, s3))
  235.       goto out;
  236.   }
  237.  
  238.   if (copyFiles()) {
  239.     markForUpdate(to);
  240.     intUpdate();
  241.   }
  242.  
  243.  out:
  244.   freeze = False;
  245. }
  246.  
  247. /*---------------------------------------------------------------------------*/
  248.  
  249. static void fileEndExec(FileWindowRec *fw, int i)
  250. {
  251.   int l;
  252.   char *path;
  253.   char **argv;
  254.  
  255.   l = strlen(fw->directory);
  256.   path = (char *)alloca(l+strlen(fw->files[i]->name)+2);
  257.   strcpy(path, fw->directory);
  258.   if (path[l-1] != '/')
  259.     path[l++] = '/';
  260.   strcpy(path+l, fw->files[i]->name);
  261.  
  262.   argv = (char **) XtMalloc(2 * sizeof(char *));
  263.   argv[0] = XtNewString(path);
  264.   argv[1] = NULL;
  265.  
  266.   argv = expandArgv(argv);
  267.   executeApplication(path, move_info.fw->directory, argv);
  268.   freeArgv(argv);
  269. }
  270.  
  271. /*---------------------------------------------------------------------------*/
  272.  
  273. static void fileEndAction(FileWindowRec *fw, int i)
  274. {
  275.   int l;
  276.   char *path;
  277.   char **argv;
  278.   char *action = varPopup(fw->files[i]->type->icon_bm,
  279.               fw->files[i]->type->drop_action);
  280.  
  281.   if (!action) return;
  282.  
  283.   l = strlen(fw->directory);
  284.   path = (char *)alloca(l+strlen(fw->files[i]->name)+2);
  285.   strcpy(path, fw->directory);
  286.   if (path[l-1] != '/')
  287.     path[l++] = '/';
  288.   strcpy(path+l, fw->files[i]->name);
  289.  
  290.   argv = makeArgv2(action, path);
  291.   argv = expandArgv(argv);
  292.   executeApplication(user.shell, move_info.fw->directory, argv);
  293.   freeArgv(argv);
  294. }
  295.  
  296. /*---------------------------------------------------------------------------*/
  297.  
  298. /* perform a click-drag, returning the widget that the user released the 
  299.    button on */
  300.  
  301. static Widget drag(Widget w, int button, FileWindowRec *fw,
  302.            Boolean *on_root_return)
  303. {
  304.   Cursor c;
  305.   XEvent e;
  306.   int i, x, y;
  307.   Window child;
  308.  
  309.   move_info.fw = fw;
  310.   
  311.   if (fw->n_selections == 1) {
  312.     for (i=0; !fw->files[i]->selected && i<fw->n_files;
  313.      i++);
  314.     if (S_ISDIR(fw->files[i]->stats.st_mode)) {
  315.       move_info.type = Directory;
  316.       c = curs[DIR_CUR];
  317.     }
  318.     else if (S_ISLNK(fw->files[i]->stats.st_mode)) {
  319.       move_info.type = SingleFile;
  320.       c = curs[FILE_CUR];
  321.     }
  322.     else if (fw->files[i]->stats.st_mode & 
  323.          (S_IXUSR | S_IXGRP | S_IXOTH)) {
  324.       move_info.type = Executable;
  325.       c = curs[EXEC_CUR];
  326.     }
  327.     else {
  328.       move_info.type = SingleFile;
  329.       c = curs[FILE_CUR];
  330.     }
  331.   }
  332.   else {
  333.     move_info.type = MultipleFiles;
  334.     c = curs[FILES_CUR];
  335.   }
  336.   drag_cursor = c;
  337.  
  338.   XGrabPointer(XtDisplay(w), XtWindow(w), True,
  339.            EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  340.            GrabModeAsync, GrabModeAsync, None, c, CurrentTime);
  341.  
  342.   move_info.dragged_from = w;
  343.   freeze = dragging = True;
  344.   
  345.   for (;;) {
  346.     XtAppNextEvent(app_context, &e);
  347.     switch (e.type) {
  348.     case ButtonPress:        /* Ignore button presses */
  349.       continue;
  350.     case ButtonRelease:      /* Ignore button releases except 2 */
  351.       if (e.xbutton.button != button)
  352.     continue;
  353.       break;
  354.     default:
  355.       XtDispatchEvent(&e);
  356.       continue;
  357.     }
  358.     break;
  359.   }
  360.  
  361.   XUngrabPointer(XtDisplay(aw.shell),CurrentTime);
  362.   XtDispatchEvent(&e);
  363.   freeze = dragging = False;
  364.   
  365.   /* Find out if the drag was released on the root window (child = None) */
  366.   XTranslateCoordinates(XtDisplay(w),e.xbutton.window,e.xbutton.root,
  367.             e.xbutton.x,e.xbutton.y,&x,&y,&child);
  368.   if (child == None)
  369.     *on_root_return = True;
  370.   else
  371.     *on_root_return = False;
  372.  
  373.   return XtWindowToWidget(XtDisplay(w),e.xbutton.window);
  374. }
  375.  
  376. /*---------------------------------------------------------------------------
  377.   PUBLIC FUNCTIONS
  378. ---------------------------------------------------------------------------*/
  379.  
  380. void filePopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
  381. {
  382.   int i;
  383.   FileWindowRec *fw;
  384.   Display *dpy;
  385.   Window root, child;
  386.   int x, y, x_win, y_win;
  387.   unsigned int mask;
  388.  
  389.   i = findWidget(w, &fw);
  390.   if (!fw) {
  391. /*
  392.     error("Internal error:", "widget not found in filePopup");
  393. */
  394.     return;
  395.   }
  396.  
  397.   popup_fw = fw;
  398.   fileSelect(w, event, params, num_params);
  399.  
  400.   if (S_ISLNK(fw->files[i]->stats.st_mode)) {
  401.     grayOut(file_popup_items[0]);
  402.     grayOut(file_popup_items[1]);
  403.   } else {
  404.     fillIn(file_popup_items[0]);
  405.     fillIn(file_popup_items[1]);
  406.   }
  407.  
  408.   dpy = XtDisplay(aw.shell);
  409.   
  410.   XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &x, &y, 
  411.         &x_win, &y_win, &mask);
  412.   
  413.   XtVaSetValues(file_popup_widget, XtNx, (XtArgVal) x, XtNy, (XtArgVal) y,
  414.         NULL);
  415.   
  416.   XtPopupSpringLoaded(file_popup_widget);
  417. }  
  418.  
  419. /*---------------------------------------------------------------------------*/
  420.  
  421. void dirPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
  422. {
  423.   int i;
  424.   FileWindowRec *fw;
  425.   Display *dpy;
  426.   Window root, child;
  427.   int x, y, x_win, y_win;
  428.   unsigned int mask;
  429.  
  430.   i = findWidget(w, &fw);
  431.   if (!fw) {
  432. /*
  433.     error("Internal error:", "widget not found in dirPopup");
  434. */
  435.     return;
  436.   }
  437.  
  438.   popup_fw = fw;
  439.   fileSelect(w, event, params, num_params);
  440.  
  441.   if (!strcmp(fw->files[i]->name, ".") ||
  442.       !strcmp(fw->files[i]->name, "..")) {
  443.     grayOut(dir_popup_items[2]);
  444.     grayOut(dir_popup_items[3]);
  445.     grayOut(dir_popup_items[6]);
  446.   } else {
  447.     fillIn(dir_popup_items[2]);
  448.     fillIn(dir_popup_items[3]);
  449.     fillIn(dir_popup_items[6]);
  450.   }
  451.  
  452.   dpy = XtDisplay(aw.shell);
  453.   
  454.   XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &x, &y, 
  455.         &x_win, &y_win, &mask);
  456.   
  457.   XtVaSetValues(dir_popup_widget, XtNx, (XtArgVal) x, XtNy, (XtArgVal) y,
  458.         NULL);
  459.   
  460.   XtPopupSpringLoaded(dir_popup_widget);
  461. }  
  462.  
  463. /*---------------------------------------------------------------------------*/
  464.  
  465. void fileToggle(Widget w, XEvent *event, String *params, Cardinal *num_params)
  466. {
  467.   int i;
  468.   FileWindowRec *fw;
  469.   Pixel pix;
  470.  
  471.   i = findWidget(w, &fw);
  472.   if (!fw) {
  473. /*
  474.     error("Internal error:", "widget not found in fileToggle");
  475. */
  476.     return;
  477.   }
  478.     
  479.   XtVaGetValues(w, fw->files[i]->selected?XtNbackground:XtNforeground, &pix,
  480.         NULL);
  481.   XtVaSetValues(w, XtNborder, (XtArgVal) pix, NULL);
  482.  
  483.   if (fw->files[i]->selected) {
  484.     fw->files[i]->selected = False;
  485.     fw->n_selections--;
  486.     fw->n_bytes_selected -= fw->files[i]->stats.st_size;
  487.   }
  488.   else {
  489.     fw->files[i]->selected = True;
  490.     fw->n_selections++;
  491.     fw->n_bytes_selected += fw->files[i]->stats.st_size;
  492.   }
  493.   updateStatus(fw);
  494. }
  495.  
  496. /*---------------------------------------------------------------------------*/
  497.  
  498. void fileSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
  499. {
  500.   int i, j;
  501.   FileWindowRec *fw;
  502.   Pixel back, fore;
  503.  
  504.   j = findWidget(w, &fw);
  505.   if (!fw) {
  506. /*
  507.     error("Internal error:", "widget not found in fileSelect");
  508. */
  509.     return;
  510.   }
  511.   
  512.   for (i=0; i<fw->n_files; i++)
  513.     if (fw->files[i]->selected) {
  514.       XtCallActionProc(fw->files[i]->icon.toggle, "unset", event, NULL, 0);
  515.       XtVaGetValues(fw->files[i]->icon.toggle, XtNbackground, &back, NULL);
  516.       XtVaSetValues(fw->files[i]->icon.toggle, XtNborder, (XtArgVal) back,
  517.             NULL);
  518.       fw->files[i]->selected = False;
  519.     }
  520.  
  521.   XtVaGetValues(w, XtNforeground, &fore, NULL);
  522.   XtVaSetValues(w, XtNborder, (XtArgVal) fore, NULL);
  523.  
  524.   fw->files[j]->selected = True;
  525.   fw->n_selections = 1;
  526.   fw->n_bytes_selected = fw->files[j]->stats.st_size;
  527.   updateStatus(fw);
  528. }
  529.  
  530. /*---------------------------------------------------------------------------*/
  531.  
  532. void fileHighlight(Widget w, XEvent *event, String *params, 
  533.            Cardinal *num_params)
  534. {
  535.   int i;
  536.   FileWindowRec *fw;
  537.  
  538.   if (!dragging)
  539.     return;
  540.  
  541.   i = findWidget(w,&fw);
  542.   if (!fw) {
  543. /*
  544.     error("Internal error:","Widget not found in fileHighlight");
  545. */
  546.     return;
  547.   }
  548.  
  549.   if ((i == -1 && !permission(&fw->stats,W_OK)) || 
  550.       (i != -1 && S_ISDIR(fw->files[i]->stats.st_mode) &&
  551.       !permission(&fw->files[i]->stats, P_WRITE)))
  552.     XChangeActivePointerGrab(XtDisplay(w),
  553.                EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  554.                curs[NOENTRY_CUR], CurrentTime);
  555.  
  556.   if ( i != -1 && (fw != move_info.fw || !fw->files[i]->selected))
  557.     XtCallActionProc(w, "highlight", event, NULL, 0);
  558. }
  559.  
  560. /*---------------------------------------------------------------------------*/
  561.  
  562. void fileMaybeHighlight(Widget w, XEvent *event, String *params, 
  563.             Cardinal *num_params)
  564. {
  565.   int i;
  566.   FileWindowRec *fw;
  567.  
  568.   if (!dragging)
  569.     return;
  570.  
  571.   i = findWidget(w,&fw);
  572.   if (!fw) {
  573. /*
  574.     error("Internal error:","Widget not found in fileMaybeHighlight");
  575. */
  576.     return;
  577.   }
  578.  
  579.   if (i != -1 && (fw != move_info.fw || !fw->files[i]->selected) &&
  580.       fw->files[i]->type && *fw->files[i]->type->drop_action)
  581.     XtCallActionProc(w, "highlight", event, NULL, 0);
  582. }
  583.  
  584. /*---------------------------------------------------------------------------*/
  585.  
  586. void resetCursor(Widget w, XEvent *event, String *params,Cardinal *num_params)
  587. {
  588.   int i;
  589.   FileWindowRec *fw;
  590.  
  591.   i = findWidget(w,&fw);
  592.   if (!fw) {
  593. /*
  594.     error("Internal error:","Widget not found in resetCursor");
  595. */
  596.     return;
  597.   }
  598.  
  599.   if (i != -1)
  600.     XtCallActionProc(w, "unhighlight", event, NULL, 0);
  601.  
  602.   if (!dragging)
  603.     return;
  604.  
  605.   XChangeActivePointerGrab(XtDisplay(w),
  606.               EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  607.               drag_cursor, CurrentTime);
  608. }
  609.  
  610.  
  611. /*---------------------------------------------------------------------------*/
  612.  
  613. void fileRefresh(Widget w, XEvent *event, String *params, Cardinal *num_params)
  614. {
  615.   FileWindowRec *fw;
  616.   
  617.   findWidget(w, &fw);
  618.   if (fw)
  619.     updateFileDisplay(fw);
  620. }
  621.  
  622. /*---------------------------------------------------------------------------*/
  623.  
  624. void fileOpenDir(Widget w, XEvent *event, String *params,Cardinal *num_params)
  625. {
  626.   FileWindowRec *fw;
  627.   int i;
  628.   char path[MAXPATHLEN];
  629.  
  630.   i = findWidget(w, &fw);
  631.   if (!fw)
  632.     return;
  633.   if (chdir(fw->directory) || chdir(fw->files[i]->name))
  634.     sysError("Can't open folder:");
  635.   else if (!getwd(path))
  636.     sysError("System error:");
  637.   else {
  638.     strcpy(fw->directory, path);
  639.     updateFileDisplay(fw);
  640.   }
  641. }
  642.  
  643. /*---------------------------------------------------------------------------*/
  644.  
  645. void fileBeginDrag(Widget w, XEvent *event, String *params, 
  646.            Cardinal *num_params)
  647. {
  648.   int i, button;
  649.   FileWindowRec *fw;
  650.   Boolean root, move = True;
  651.  
  652.   if (*num_params != 2) {
  653.     error("Internal error:","wrong number of parameters to fileBeginDrag");
  654.     return;
  655.   }
  656.  
  657.   button = *params[0] - '0';
  658.   if (!strcmp(params[1],"copy"))
  659.     move = False;
  660.  
  661.   i =  findWidget(w, &fw);
  662.   if (!fw) {
  663. /*
  664.     error("Internal error:","widget not found in fileBeginDrag");
  665. */
  666.     return;
  667.   }
  668.   
  669.   if (i != -1) {
  670.     if (!fw->files[i]->selected)
  671.       fileSelect(w, event, params, num_params);
  672.   } else
  673.     return;
  674.   
  675.   if (!(w = drag(w,button,fw,&root)))
  676.     return;
  677.  
  678.   /* Open directories if dragged onto the root window */
  679.   if (root && move_info.type == Directory) {
  680.     fileOpenCb(NULL,move_info.fw,NULL);
  681.     return;
  682.   }
  683.  
  684.   i = findWidget(w,&fw);
  685.  
  686.   /* First see whether the target is the application window */
  687.   if (!fw) {
  688.     if (w == aw.icon_box)
  689.       appEndDragInBox();
  690.     else if ((i = findAppWidget(w)) != -1)
  691.       appEndDrag(i);
  692. /*
  693.     else
  694.       error("Internal error:","widget not found in fileBeginDrag");
  695. */
  696.   }
  697.  
  698.   /* Otherwise, if we didn't go anywhere, don't do anything */
  699.   else if (fw == move_info.fw &&
  700.       (i == -1 || fw->files[i]->selected ||
  701.        (!S_ISDIR(fw->files[i]->stats.st_mode) &&
  702.     !(fw->files[i]->stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) &&
  703.     !(fw->files[i]->type && *fw->files[i]->type->drop_action))))
  704.     ;
  705.  
  706.   /* Otherwise, if dragged onto a window or a directory, do the move */
  707.   else if (i == -1 || S_ISDIR(fw->files[i]->stats.st_mode))
  708.     if (move)
  709.       fileEndMove(fw,i);
  710.     else
  711.       fileEndCopy(fw,i);
  712.  
  713.   /* Otherwise, if dragged onto an executable, run the program */
  714.   else if (fw->files[i]->stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
  715.     fileEndExec(fw,i);
  716.  
  717.   /* Otherwise, if the file has a drop action, invoke the action */
  718.   else if (fw->files[i]->type && *fw->files[i]->type->drop_action)
  719.     fileEndAction(fw,i);
  720.  
  721.   /* Otherwise, it must be a normal file so just do the move */
  722.   else if (move)
  723.     fileEndMove(fw,i);
  724.   else
  725.     fileEndCopy(fw,i);
  726. }
  727.   
  728. /*---------------------------------------------------------------------------*/
  729.  
  730. void fileExecFile(Widget w, XEvent *event, String *params, 
  731.           Cardinal *num_params)
  732. {
  733.   int i, l;
  734.   char *path;
  735.   char **argv;
  736.   FileWindowRec *fw;
  737.  
  738.   i = findWidget(w, &fw);
  739.   if (i == -1 || !fw) {
  740. /*
  741.     error("Internal error:","widget not found in fileExecFile");
  742. */
  743.     return;
  744.   }
  745.  
  746.   l = strlen(fw->directory);
  747.   path = (char *)alloca(l+strlen(fw->files[i]->name)+2);
  748.   strcpy(path, fw->directory);
  749.   if (path[l-1] != '/')
  750.     path[l++] = '/';
  751.   strcpy(path+l, fw->files[i]->name);
  752.   argv = (char **) XtMalloc(2 * sizeof(char *));
  753.   argv[0] = XtNewString(fw->files[i]->name);
  754.   argv[1] = NULL;
  755.   executeApplication(path, fw->directory, argv);
  756.  
  757.   freeArgv(argv);
  758. }
  759.  
  760. /*---------------------------------------------------------------------------*/
  761. void fileExecAction(Widget w, XEvent *event, String *params, 
  762.             Cardinal *num_params)
  763. {
  764.   int i;
  765.   FileWindowRec *fw;
  766.   char **argv;
  767.  
  768.   i = findWidget(w, &fw);
  769.   if (i == -1 || !fw) {
  770. /*
  771.     error("Internal error:","widget not found in fileExecAction");
  772. */
  773.     return;
  774.   }
  775.  
  776.   if (fw->files[i]->type) {
  777.     if (*fw->files[i]->type->push_action)
  778.       if (!strcmp(fw->files[i]->type->push_action, "EDIT"))
  779.     doEdit(fw->directory, fw->files[i]->name);
  780.       else if (!strcmp(fw->files[i]->type->push_action, "VIEW"))
  781.     doView(fw->directory, fw->files[i]->name);
  782.       else if (!strcmp(fw->files[i]->type->push_action, "LOAD")) {
  783.     int j, l;
  784.     if (!resources.appmgr) return;
  785.     pushApplicationsFile();
  786.     l = strlen(fw->directory);
  787.     strcpy(resources.app_file, fw->directory);
  788.     if (resources.app_file[l-1] != '/')
  789.       resources.app_file[l++] = '/';
  790.     strcpy(resources.app_file+l, fw->files[i]->name);
  791.     for(j=0; j<aw.n_apps; j++)
  792.       freeApplicationResources(&aw.apps[j]);
  793.     XTFREE(aw.apps);
  794.     readApplicationData(resources.app_file);
  795.     updateApplicationDisplay();
  796.       } else {
  797.         int k = 0;
  798.     char *action = varPopup(fw->files[i]->type->icon_bm,
  799.                 fw->files[i]->type->push_action);
  800.  
  801.     if (!action) return;
  802.  
  803.     argv = (char **) XtMalloc( (user.arg0flag ? 6 : 5) * sizeof(char *));
  804.     argv[k++] = user.shell;
  805.     argv[k++] = "-c";
  806.     argv[k++] = action;
  807.         if (user.arg0flag)
  808.           argv[k++] = user.shell;
  809.     argv[k++] = fw->files[i]->name;
  810.     argv[k] = NULL;
  811.  
  812.     executeApplication(user.shell, fw->directory, argv);
  813.  
  814.     XTFREE(argv);
  815.       }
  816.   } else
  817.     doEdit(fw->directory, fw->files[i]->name);
  818. }
  819.  
  820. /*---------------------------------------------------------------------------*/
  821. void doEdit(char *directory, char *fname)
  822. {
  823.   char path[MAXPATHLEN];
  824.   char **argv;
  825.  
  826.   if (resources.default_editor) {
  827.  
  828.     strcpy(path, resources.default_editor);
  829.     strcat(path, " ");
  830.     strcat(path, fname);
  831.  
  832.     argv = (char **) XtMalloc(4 * sizeof(char *));
  833.     argv[0] = user.shell;
  834.     argv[1] = "-c";
  835.     argv[2] = path;
  836.     argv[3] = NULL;
  837.  
  838.     executeApplication(user.shell, directory, argv);
  839.   
  840.     XTFREE(argv);
  841.   }
  842.  
  843.   else
  844.     error("No default editor", "");
  845. }
  846. /*---------------------------------------------------------------------------*/
  847. void doView(char *directory, char *fname)
  848. {
  849.   char path[MAXPATHLEN];
  850.   char **argv;
  851.  
  852.   if (resources.default_viewer) {
  853.  
  854.     strcpy(path, resources.default_viewer);
  855.     strcat(path, " ");
  856.     strcat(path, fname);
  857.  
  858.     argv = (char **) XtMalloc(4 * sizeof(char *));
  859.     argv[0] = user.shell;
  860.     argv[1] = "-c";
  861.     argv[2] = path;
  862.     argv[3] = NULL;
  863.  
  864.     executeApplication(user.shell, directory, argv);
  865.   
  866.     XTFREE(argv);
  867.   }
  868.  
  869.   else
  870.     error("No default viewer", "");
  871. }
  872.