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 / FmFwActions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-16  |  19.8 KB  |  841 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.   char *fromdir, *todir;
  178.  
  179.   if (!setupMoveCopy(fw, i)) return;
  180.  
  181.   fromdir = strcpy(alloca(fromi+1), from);
  182.   todir = strcpy(alloca(toi+1), to);
  183.  
  184.   if (!strcmp(from, to)) {
  185.     error("Move:", "Source and destination are identical");
  186.     return;
  187.   }
  188.  
  189.   if (access(to, W_OK)) {
  190.     error("No write access to this directory","");
  191.     return;
  192.   }
  193.  
  194.   freeze = True;
  195.  
  196.   if (resources.confirm_moves) {
  197.     char s1[0xff], s2[0xff], s3[0xff];
  198.     sprintf(s1, "Moving %d item%c", move_info.fw->n_selections,
  199.         move_info.fw->n_selections > 1 ? 's' : ' ');
  200.     sprintf(s2, "from: %s", from);
  201.     sprintf(s3, "to: %s", to);
  202.     if (!confirm(s1, s2, s3))
  203.       goto out;
  204.   }
  205.  
  206.   if (moveFiles()) {
  207.     markForUpdate(fromdir); markForUpdate(todir);
  208.     intUpdate();
  209.   }
  210.  
  211.  out:
  212.   freeze = False;
  213. }
  214.  
  215. /*---------------------------------------------------------------------------*/
  216.  
  217. static void fileEndCopy(FileWindowRec *fw, int i)
  218. {
  219.   char *todir;
  220.  
  221.   if (!setupMoveCopy(fw, i)) return;
  222.  
  223.   todir = strcpy(alloca(toi+1), to);
  224.  
  225.   if (!strcmp(from, to)) {
  226.     error("Copy:", "Source and destination are identical");
  227.     return;
  228.   }
  229.  
  230.   if (access(to, W_OK)) {
  231.     error("No write access to this directory","");
  232.     return;
  233.   }
  234.  
  235.   freeze = True;
  236.  
  237.   if (resources.confirm_copies) {
  238.     char s1[0xff], s2[0xff], s3[0xff];
  239.     sprintf(s1, "Copying %d item%c", move_info.fw->n_selections,
  240.         move_info.fw->n_selections > 1 ? 's' : ' ');
  241.     sprintf(s2, "from: %s", from);
  242.     sprintf(s3, "to: %s", to);
  243.     if (!confirm(s1, s2, s3))
  244.       goto out;
  245.   }
  246.  
  247.   if (copyFiles()) {
  248.     markForUpdate(todir);
  249.     intUpdate();
  250.   }
  251.  
  252.  out:
  253.   freeze = False;
  254. }
  255.  
  256. /*---------------------------------------------------------------------------*/
  257.  
  258. static void fileEndExec(FileWindowRec *fw, int i)
  259. {
  260.   int l;
  261.   char *path;
  262.   char **argv;
  263.  
  264.   l = strlen(fw->directory);
  265.   path = alloca(l+strlen(fw->files[i]->name)+2);
  266.   strcpy(path, fw->directory);
  267.   if (path[l-1] != '/')
  268.     path[l++] = '/';
  269.   strcpy(path+l, fw->files[i]->name);
  270.  
  271.   argv = (char **) XtMalloc(2 * sizeof(char *));
  272.   argv[0] = XtNewString(fw->files[i]->name);
  273.   argv[1] = NULL;
  274.  
  275.   argv = expandArgv(argv);
  276.   executeApplication(path, move_info.fw->directory, argv);
  277.   freeArgv(argv);
  278. }
  279.  
  280. /*---------------------------------------------------------------------------*/
  281.  
  282. static void fileEndAction(FileWindowRec *fw, int i)
  283. {
  284.   int l;
  285.   char *path;
  286.   char **argv;
  287.   char *action = varPopup(fw->files[i]->type->icon_bm,
  288.               fw->files[i]->type->drop_action);
  289.  
  290.   if (!action) return;
  291.  
  292.   l = strlen(fw->directory);
  293.   path = alloca(l+strlen(fw->files[i]->name)+2);
  294.   strcpy(path, fw->directory);
  295.   if (path[l-1] != '/')
  296.     path[l++] = '/';
  297.   strcpy(path+l, fw->files[i]->name);
  298.  
  299.   argv = makeArgv2(action, path);
  300.   argv = expandArgv(argv);
  301.   executeApplication(user.shell, move_info.fw->directory, argv);
  302.   freeArgv(argv);
  303. }
  304.  
  305. /*---------------------------------------------------------------------------*/
  306.  
  307. /* perform a click-drag, returning the widget that the user released the 
  308.    button on */
  309.  
  310. static Widget drag(Widget w, int button, FileWindowRec *fw,
  311.            Boolean *on_root_return)
  312. {
  313.   Cursor c;
  314.   XEvent e;
  315.   int i, x, y;
  316.   Window child;
  317.  
  318.   move_info.fw = fw;
  319.   
  320.   if (fw->n_selections == 1) {
  321.     for (i=0; !fw->files[i]->selected && i<fw->n_files;
  322.      i++);
  323.     if (S_ISDIR(fw->files[i]->stats.st_mode)) {
  324.       move_info.type = Directory;
  325.       c = curs[DIR_CUR];
  326.     }
  327.     else if (S_ISLNK(fw->files[i]->stats.st_mode)) {
  328.       move_info.type = SingleFile;
  329.       c = curs[FILE_CUR];
  330.     }
  331.     else if (fw->files[i]->stats.st_mode & 
  332.          (S_IXUSR | S_IXGRP | S_IXOTH)) {
  333.       move_info.type = Executable;
  334.       c = curs[EXEC_CUR];
  335.     }
  336.     else {
  337.       move_info.type = SingleFile;
  338.       c = curs[FILE_CUR];
  339.     }
  340.   }
  341.   else {
  342.     move_info.type = MultipleFiles;
  343.     c = curs[FILES_CUR];
  344.   }
  345.   drag_cursor = c;
  346.  
  347.   XGrabPointer(XtDisplay(w), XtWindow(w), True,
  348.            EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  349.            GrabModeAsync, GrabModeAsync, None, c, CurrentTime);
  350.  
  351.   move_info.dragged_from = w;
  352.   freeze = dragging = True;
  353.   
  354.   for (;;) {
  355.     XtAppNextEvent(app_context, &e);
  356.     switch (e.type) {
  357.     case ButtonPress:        /* Ignore button presses */
  358.       continue;
  359.     case ButtonRelease:      /* Ignore button releases except 2 */
  360.       if (e.xbutton.button != button)
  361.     continue;
  362.       break;
  363.     default:
  364.       XtDispatchEvent(&e);
  365.       continue;
  366.     }
  367.     break;
  368.   }
  369.  
  370.   XUngrabPointer(XtDisplay(aw.shell),CurrentTime);
  371.   XtDispatchEvent(&e);
  372.   freeze = dragging = False;
  373.   
  374.   /* Find out if the drag was released on the root window (child = None) */
  375.   XTranslateCoordinates(XtDisplay(w),e.xbutton.window,e.xbutton.root,
  376.             e.xbutton.x,e.xbutton.y,&x,&y,&child);
  377.   if (child == None)
  378.     *on_root_return = True;
  379.   else
  380.     *on_root_return = False;
  381.  
  382.   return XtWindowToWidget(XtDisplay(w),e.xbutton.window);
  383. }
  384.  
  385. /*---------------------------------------------------------------------------
  386.   PUBLIC FUNCTIONS
  387. ---------------------------------------------------------------------------*/
  388.  
  389. void filePopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
  390. {
  391.   int i;
  392.   FileWindowRec *fw;
  393.   Display *dpy;
  394.   Window root, child;
  395.   int x, y, x_win, y_win;
  396.   unsigned int mask;
  397.  
  398.   i = findWidget(w, &fw);
  399.   if (!fw) {
  400. /*
  401.     error("Internal error:", "widget not found in filePopup");
  402. */
  403.     return;
  404.   }
  405.  
  406.   popup_fw = fw;
  407.   fileSelect(w, event, params, num_params);
  408.  
  409.   if (S_ISLNK(fw->files[i]->stats.st_mode))
  410.     grayOut(file_popup_items[0]);
  411.   else
  412.     fillIn(file_popup_items[0]);
  413.  
  414.   dpy = XtDisplay(aw.shell);
  415.   
  416.   XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &x, &y, 
  417.         &x_win, &y_win, &mask);
  418.   
  419.   XtVaSetValues(file_popup_widget, XtNx, (XtArgVal) x, XtNy, (XtArgVal) y,
  420.         NULL);
  421.   
  422.   XtPopupSpringLoaded(file_popup_widget);
  423. }  
  424.  
  425. /*---------------------------------------------------------------------------*/
  426.  
  427. void dirPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
  428. {
  429.   int i;
  430.   FileWindowRec *fw;
  431.   Display *dpy;
  432.   Window root, child;
  433.   int x, y, x_win, y_win;
  434.   unsigned int mask;
  435.  
  436.   i = findWidget(w, &fw);
  437.   if (!fw) {
  438. /*
  439.     error("Internal error:", "widget not found in dirPopup");
  440. */
  441.     return;
  442.   }
  443.  
  444.   popup_fw = fw;
  445.   fileSelect(w, event, params, num_params);
  446.  
  447.   if (!strcmp(fw->files[i]->name, ".") ||
  448.       !strcmp(fw->files[i]->name, "..")) {
  449.     grayOut(dir_popup_items[2]);
  450.     grayOut(dir_popup_items[3]);
  451.     grayOut(dir_popup_items[4]);
  452.   } else {
  453.     fillIn(dir_popup_items[2]);
  454.     fillIn(dir_popup_items[3]);
  455.     fillIn(dir_popup_items[4]);
  456.   }
  457.  
  458.   dpy = XtDisplay(aw.shell);
  459.   
  460.   XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &x, &y, 
  461.         &x_win, &y_win, &mask);
  462.   
  463.   XtVaSetValues(dir_popup_widget, XtNx, (XtArgVal) x, XtNy, (XtArgVal) y,
  464.         NULL);
  465.   
  466.   XtPopupSpringLoaded(dir_popup_widget);
  467. }  
  468.  
  469. /*---------------------------------------------------------------------------*/
  470.  
  471. void fileToggle(Widget w, XEvent *event, String *params, Cardinal *num_params)
  472. {
  473.   int i;
  474.   FileWindowRec *fw;
  475.   Pixel pix;
  476.  
  477.   i = findWidget(w, &fw);
  478.   if (!fw) {
  479. /*
  480.     error("Internal error:", "widget not found in fileToggle");
  481. */
  482.     return;
  483.   }
  484.     
  485.   XtVaGetValues(w, fw->files[i]->selected?XtNbackground:XtNforeground, &pix,
  486.         NULL);
  487.   XtVaSetValues(w, XtNborder, (XtArgVal) pix, NULL);
  488.  
  489.   if (fw->files[i]->selected) {
  490.     fw->files[i]->selected = False;
  491.     fw->n_selections--;
  492.     fw->n_bytes_selected -= fw->files[i]->stats.st_size;
  493.   }
  494.   else {
  495.     fw->files[i]->selected = True;
  496.     fw->n_selections++;
  497.     fw->n_bytes_selected += fw->files[i]->stats.st_size;
  498.   }
  499.   updateStatus(fw);
  500. }
  501.  
  502. /*---------------------------------------------------------------------------*/
  503.  
  504. void fileSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
  505. {
  506.   int i, j;
  507.   FileWindowRec *fw;
  508.   Pixel back, fore;
  509.  
  510.   j = findWidget(w, &fw);
  511.   if (!fw) {
  512. /*
  513.     error("Internal error:", "widget not found in fileSelect");
  514. */
  515.     return;
  516.   }
  517.   
  518.   for (i=0; i<fw->n_files; i++)
  519.     if (fw->files[i]->selected) {
  520.       XtCallActionProc(fw->files[i]->icon.toggle, "unset", event, NULL, 0);
  521.       XtVaGetValues(fw->files[i]->icon.toggle, XtNbackground, &back, NULL);
  522.       XtVaSetValues(fw->files[i]->icon.toggle, XtNborder, (XtArgVal) back,
  523.             NULL);
  524.       fw->files[i]->selected = False;
  525.     }
  526.  
  527.   XtVaGetValues(w, XtNforeground, &fore, NULL);
  528.   XtVaSetValues(w, XtNborder, (XtArgVal) fore, NULL);
  529.  
  530.   fw->files[j]->selected = True;
  531.   fw->n_selections = 1;
  532.   fw->n_bytes_selected = fw->files[j]->stats.st_size;
  533.   updateStatus(fw);
  534. }
  535.  
  536. /*---------------------------------------------------------------------------*/
  537.  
  538. void fileHighlight(Widget w, XEvent *event, String *params, 
  539.            Cardinal *num_params)
  540. {
  541.   int i;
  542.   FileWindowRec *fw;
  543.  
  544.   if (!dragging)
  545.     return;
  546.  
  547.   i = findWidget(w,&fw);
  548.   if (!fw) {
  549. /*
  550.     error("Internal error:","Widget not found in fileHighlight");
  551. */
  552.     return;
  553.   }
  554.  
  555.   if (i == -1 && !permission(&fw->stats,W_OK) || 
  556.       i != -1 && S_ISDIR(fw->files[i]->stats.st_mode) &&
  557.       !permission(&fw->files[i]->stats, P_WRITE))
  558.     XChangeActivePointerGrab(XtDisplay(w),
  559.                EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  560.                curs[NOENTRY_CUR], CurrentTime);
  561.  
  562.   if ( i != -1 && (fw != move_info.fw || !fw->files[i]->selected))
  563.     XtCallActionProc(w, "highlight", event, NULL, 0);
  564. }
  565.  
  566. /*---------------------------------------------------------------------------*/
  567.  
  568. void fileMaybeHighlight(Widget w, XEvent *event, String *params, 
  569.             Cardinal *num_params)
  570. {
  571.   int i;
  572.   FileWindowRec *fw;
  573.  
  574.   if (!dragging)
  575.     return;
  576.  
  577.   i = findWidget(w,&fw);
  578.   if (!fw) {
  579. /*
  580.     error("Internal error:","Widget not found in fileMaybeHighlight");
  581. */
  582.     return;
  583.   }
  584.  
  585.   if (i != -1 && (fw != move_info.fw || !fw->files[i]->selected) &&
  586.       fw->files[i]->type && *fw->files[i]->type->drop_action)
  587.     XtCallActionProc(w, "highlight", event, NULL, 0);
  588. }
  589.  
  590. /*---------------------------------------------------------------------------*/
  591.  
  592. void resetCursor(Widget w, XEvent *event, String *params,Cardinal *num_params)
  593. {
  594.   int i;
  595.   FileWindowRec *fw;
  596.  
  597.   i = findWidget(w,&fw);
  598.   if (!fw) {
  599. /*
  600.     error("Internal error:","Widget not found in resetCursor");
  601. */
  602.     return;
  603.   }
  604.  
  605.   if (i != -1)
  606.     XtCallActionProc(w, "unhighlight", event, NULL, 0);
  607.  
  608.   if (!dragging)
  609.     return;
  610.  
  611.   XChangeActivePointerGrab(XtDisplay(w),
  612.               EnterWindowMask | LeaveWindowMask | ButtonReleaseMask, 
  613.               drag_cursor, CurrentTime);
  614. }
  615.  
  616.  
  617. /*---------------------------------------------------------------------------*/
  618.  
  619. void fileRefresh(Widget w, XEvent *event, String *params, Cardinal *num_params)
  620. {
  621.   FileWindowRec *fw;
  622.   
  623.   findWidget(w, &fw);
  624.   if (fw)
  625.     updateFileDisplay(fw);
  626. }
  627.  
  628. /*---------------------------------------------------------------------------*/
  629.  
  630. void fileOpenDir(Widget w, XEvent *event, String *params,Cardinal *num_params)
  631. {
  632.   FileWindowRec *fw;
  633.   int i;
  634.   char path[MAXPATHLEN];
  635.  
  636.   i = findWidget(w, &fw);
  637.   if (!fw)
  638.     return;
  639.   if (chdir(fw->directory) || chdir(fw->files[i]->name))
  640.     sysError("Can't open folder:");
  641.   else if (!getwd(path))
  642.     sysError("System error:");
  643.   else {
  644.     strcpy(fw->directory, path);
  645.     updateFileDisplay(fw);
  646.   }
  647. }
  648.  
  649. /*---------------------------------------------------------------------------*/
  650.  
  651. void fileBeginDrag(Widget w, XEvent *event, String *params, 
  652.            Cardinal *num_params)
  653. {
  654.   int i, button;
  655.   FileWindowRec *fw;
  656.   Boolean root, move = True;
  657.  
  658.   if (*num_params != 2) {
  659.     error("Internal error:","wrong number of parameters to fileBeginDrag");
  660.     return;
  661.   }
  662.  
  663.   button = *params[0] - '0';
  664.   if (!strcmp(params[1],"copy"))
  665.     move = False;
  666.  
  667.   i =  findWidget(w, &fw);
  668.   if (!fw) {
  669. /*
  670.     error("Internal error:","widget not found in fileBeginDrag");
  671. */
  672.     return;
  673.   }
  674.   
  675.   if (i != -1) {
  676.     if (!fw->files[i]->selected)
  677.       fileSelect(w, event, params, num_params);
  678.   } else
  679.     return;
  680.   
  681.   if (!(w = drag(w,button,fw,&root)))
  682.     return;
  683.  
  684.   /* Open directories if dragged onto the root window */
  685.   if (root && move_info.type == Directory) {
  686.     fileOpenCb(NULL,move_info.fw,NULL);
  687.     return;
  688.   }
  689.  
  690.   i = findWidget(w,&fw);
  691.  
  692.   /* First see whether the target is the application window */
  693.   if (!fw) {
  694.     if (w == aw.icon_box)
  695.       appEndMoveInBox();
  696.     else if ((i = findAppWidget(w)) != -1)
  697.       appEndMove(i);
  698. /*
  699.     else
  700.       error("Internal error:","widget not found in fileBeginDrag");
  701. */
  702.   }
  703.  
  704.   /* Otherwise, if we didn't go anywhere, don't do anything */
  705.   else if (fw == move_info.fw &&
  706.       (i == -1 || fw->files[i]->selected ||
  707.        (!S_ISDIR(fw->files[i]->stats.st_mode) &&
  708.     !(fw->files[i]->stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) &&
  709.     !(fw->files[i]->type && *fw->files[i]->type->drop_action))))
  710.     ;
  711.  
  712.   /* Otherwise, if dragged onto a window or a directory, do the move */
  713.   else if (i == -1 || S_ISDIR(fw->files[i]->stats.st_mode))
  714.     if (move)
  715.       fileEndMove(fw,i);
  716.     else
  717.       fileEndCopy(fw,i);
  718.  
  719.   /* Otherwise, if dragged onto an executable, run the program */
  720.   else if (fw->files[i]->stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
  721.     fileEndExec(fw,i);
  722.  
  723.   /* Otherwise, if the file has a drop action, invoke the action */
  724.   else if (fw->files[i]->type && *fw->files[i]->type->drop_action)
  725.     fileEndAction(fw,i);
  726.  
  727.   /* Otherwise, it must be a normal file so just do the move */
  728.   else if (move)
  729.     fileEndMove(fw,i);
  730.   else
  731.     fileEndCopy(fw,i);
  732. }
  733.   
  734. /*---------------------------------------------------------------------------*/
  735.  
  736. void fileExecFile(Widget w, XEvent *event, String *params, 
  737.           Cardinal *num_params)
  738. {
  739.   int i;
  740.   char **argv;
  741.   FileWindowRec *fw;
  742.  
  743.   i = findWidget(w, &fw);
  744.   if (i == -1 || !fw) {
  745. /*
  746.     error("Internal error:","widget not found in fileExecFile");
  747. */
  748.     return;
  749.   }
  750.  
  751.   argv = (char **) XtMalloc(2 * sizeof(char *));
  752.   argv[0] = XtNewString(fw->files[i]->name);
  753.   argv[1] = NULL;
  754.   executeApplication(fw->files[i]->name, fw->directory, argv);
  755.  
  756.   freeArgv(argv);
  757. }
  758.  
  759. /*---------------------------------------------------------------------------*/
  760. void fileExecAction(Widget w, XEvent *event, String *params, 
  761.             Cardinal *num_params)
  762. {
  763.   int i;
  764.   FileWindowRec *fw;
  765.   char **argv;
  766.  
  767.   i = findWidget(w, &fw);
  768.   if (i == -1 || !fw) {
  769. /*
  770.     error("Internal error:","widget not found in fileExecAction");
  771. */
  772.     return;
  773.   }
  774.  
  775.   if (fw->files[i]->type) {
  776.     if (*fw->files[i]->type->push_action)
  777.       if (!strcmp(fw->files[i]->type->push_action, "EDIT"))
  778.     doEdit(fw->directory, fw->files[i]->name);
  779.       else if (!strcmp(fw->files[i]->type->push_action, "LOAD")) {
  780.     int j, l;
  781.     if (!resources.appmgr) return;
  782.     l = strlen(fw->directory);
  783.     if (resources.auto_save && aw.modified)
  784.       writeApplicationData(resources.app_file);
  785.     strcpy(resources.app_file, fw->directory);
  786.     if (resources.app_file[l-1] != '/')
  787.       resources.app_file[l++] = '/';
  788.     strcpy(resources.app_file+l, fw->files[i]->name);
  789.     for(j=0; j<aw.n_apps; j++)
  790.       freeApplicationResources(&aw.apps[j]);
  791.     XTFREE(aw.apps);
  792.     readApplicationData(resources.app_file);
  793.     updateApplicationDisplay();
  794.       } else {
  795.     char *action = varPopup(fw->files[i]->type->icon_bm,
  796.                 fw->files[i]->type->push_action);
  797.  
  798.     if (!action) return;
  799.  
  800.     argv = (char **) XtMalloc(5 * sizeof(char *));
  801.     argv[0] = user.shell;
  802.     argv[1] = "-c";
  803.     argv[2] = action;
  804.     argv[3] = fw->files[i]->name;
  805.     argv[4] = NULL;
  806.  
  807.     executeApplication(user.shell, fw->directory, argv);
  808.  
  809.     XTFREE(argv);
  810.       }
  811.   } else
  812.     doEdit(fw->directory, fw->files[i]->name);
  813. }
  814.  
  815. /*---------------------------------------------------------------------------*/
  816. void doEdit(char *directory, char *fname)
  817. {
  818.   char path[MAXPATHLEN];
  819.   char **argv;
  820.  
  821.   if (resources.default_editor) {
  822.  
  823.     strcpy(path, resources.default_editor);
  824.     strcat(path, " ");
  825.     strcat(path, fname);
  826.  
  827.     argv = (char **) XtMalloc(4 * sizeof(char *));
  828.     argv[0] = user.shell;
  829.     argv[1] = "-c";
  830.     argv[2] = path;
  831.     argv[3] = NULL;
  832.  
  833.     executeApplication(user.shell, directory, argv);
  834.   
  835.     XTFREE(argv);
  836.   }
  837.  
  838.   else
  839.     error("No default editor", "");
  840. }
  841.