home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFILEMAN / XFILEMAN.TAR / xfilemanager / single.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-22  |  29.8 KB  |  1,149 lines

  1. /*
  2.  * Copyright 1993 by Ove Kalkan, Cremlingen, Germany
  3.  *
  4.  * Permission to use, copy, modify, distribute and sell this software and it's
  5.  * documentation for any purpose is hereby granted without fee, rpovided that
  6.  * the above copyright notice and this permission appear in supporting
  7.  * documentation, and that the name of Ove Kalkan not to be used in
  8.  * advertising or publicity pertaining to distributiopn of the software without
  9.  * specific, written prior permission. Ove Kalkan makes no representations
  10.  * about the suitability of this software for any purpose. It is provided
  11.  * as is without express or implied warranty.
  12.  *
  13.  * OVE KALKAN DISPLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  14.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS, IN NO
  15.  * EVENT SHALL OVE KALKAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  16.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  17.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  18.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  19.  * PERFORMANCE OF THIS SOFTWARE.
  20.  *
  21.  * $Header: filename,v 1.0 yyyy/mm/dd hh:mm:ss loginname Exp $
  22.  */
  23.  
  24.  
  25. #include "global.h"
  26.  
  27. #define    ABSDIFF(a,b)    ((long)((a) - (b)) < 0 ? (b) - (a) : (a) - (b))
  28.  
  29.  
  30. /*
  31.  * Global variables
  32.  */
  33.  
  34. static    Time        selc_t = 0;
  35.  
  36. static    int        ws_move_offx;
  37. static    int        ws_move_offy;
  38.  
  39.  
  40. /*********************************************************
  41.  * name:    startSingle
  42.  * description:    Ueberpruefen ob unter dem Zeiger ein
  43.  *        anwaehltbares Item ist und, falls
  44.  *        das Item zum zweiten Mal angewaehlt wurde
  45.  *        und zwischen dem ersten und zweiten
  46.  *        Click nicht mehr als defaults.click_interval
  47.  *        millisekunden lagen, dann zum Doppelclick
  48.  *        handler uebergehen
  49.  * input:    none
  50.  * output:    none
  51.  * date:    14.6.93
  52.  *********************************************************/
  53. XtActionProc    startSingle    (Widget w, XButtonEvent *e,
  54.                 String *s, Cardinal *c)
  55. {
  56.     int    i;
  57.  
  58.     /*
  59.      * Cursor busy
  60.      */
  61.     XDefineCursor (XtDisplay(dir_area), XtWindow(dir_area),
  62.             busy_cursor);
  63.     XDefineCursor (XtDisplay(workspace.window), 
  64.             XtWindow(workspace.window), busy_cursor);
  65.     for (i = 0; i < folder_count; i++)
  66.         XDefineCursor (XtDisplay(folders[i]->window),
  67.                 XtWindow(folders[i]->window),
  68.                 busy_cursor);
  69.     XFlush(XtDisplay(toplevel));
  70.  
  71.     /*
  72.      * Bewerten
  73.      */
  74.     if (w != dir_area && w != workspace.window && folder) {
  75.         int    y;
  76.  
  77.         /*
  78.          * Eintrag aus dem Folder holen
  79.          */
  80.         y = (e->y - 4)/DIR_Y_STEP;
  81.         
  82.         last_v = y;
  83.  
  84.         /*
  85.          * Wenn Eintrag vorher noch nicht angewaehlt, dann neunen anwaehlen
  86.          */
  87.         if (selc_f != last_v || selc_g || folder != selc_fo) {
  88.             /*
  89.              * Neues File angewaehlt, alte Selection loeschen
  90.              */
  91.             clearSingle (NULL, NULL, NULL, NULL);
  92.  
  93.             /*
  94.              * Markieren
  95.              */
  96.             if (last_v < folder->file_count) {
  97.                 selc_f = last_v;
  98.                 selc_fo = folder;
  99.                 drawFile (folder, selc_f, TRUE, TRUE);
  100.             }
  101.         }
  102.         /*
  103.          * Wenn Eintrag schon angewaehlt war, dann auf Doppelclick untersuchen
  104.          */
  105.         else if (selc_f < 16000 && last_v == selc_f && selc_fo &&
  106.              ABSDIFF(e->time,selc_t) < defaults.click_interval) {
  107.             /*
  108.              * Doppelclick -> Je nach Filetype Operation ausfuehren
  109.              */
  110.             File_Glyph    *file = folder->file[selc_f];
  111.  
  112.             /*
  113.              * Pfeil fuer das Parentdir -> Eins im Directorybaum zurueck
  114.              */
  115.             if (selc_fo->fs_type == FS_NORMAL) {
  116.                 if (file->prog_type == FILE_ROOT && folder->dir->parent) {
  117.                     Arg    args[1];
  118.                     char    *s;
  119.  
  120.                     folder->dir = folder->dir->parent;
  121.                     s = getPath(folder->dir);
  122.                     selc_f = 16000;
  123.                     fillFolder(folder);
  124.                     FILE_CHANGED = TRUE;
  125.                     refresh_files(folder->window,NULL,NULL,NULL);
  126.                     XtSetArg(args[0],XtNlabel,(*s == '\0' ? "/" : s));
  127.                     XtSetValues(folder->label,args,1);
  128.                 }
  129.                 /*
  130.                  * Directory angewaehlt, eins im Baum hoch
  131.                  */
  132.                 else if (file->prog_type == FILE_DIR ||
  133.                      file->prog_type == FILE_LDIR) {
  134.                     int    i = 0, j = -1;
  135.  
  136.                     /*
  137.                      * Directory Glyph aus dem folder->dir Glyph heraus suchen
  138.                      */
  139.                     if (!folder->dir->open && !folder->dir->dir_count) {
  140.                         fillDir(folder->dir);
  141.                         folder->dir->open = FALSE;
  142.                     }
  143.                     while (i < folder->dir->dir_count) {
  144.                         if (!(strcmp(folder->dir->dir[i]->name,file->name))) {
  145.                             j = i;
  146.                             i = folder->dir->dir_count;
  147.                         }
  148.                         i++;
  149.                     }
  150.                     /*
  151.                      * Es gab ein solches Glyph, also Glyph fuellen und
  152.                      * Folder neu darstellen
  153.                      */
  154.                     if (j > -1) {
  155.                         if (defaults.multi_window) {
  156.                             Dir_Glyph    *nd;
  157.  
  158.                             nd = folder->dir->dir[j];
  159.                             if (!nd->open && nd->dir_count == 0) {
  160.                                 fillDir(nd);
  161.                                 nd->open = FALSE;
  162.                             }
  163.                             clearSingle (NULL,NULL,NULL,NULL);
  164.                             newFolder (nd);
  165.                         }
  166.                         else {
  167.                             Arg    args[1];
  168.                             char    *s;
  169.  
  170.                             selc_f = 16000;
  171.                             folder->dir = folder->dir->dir[j];
  172.                             s = getPath(folder->dir);
  173.                             if (!folder->dir->open && folder->dir->dir_count == 0) {
  174.                                 fillDir (folder->dir);
  175.                                 folder->dir->open = FALSE;
  176.                             }
  177.                             fillFolder (folder);
  178.                             FILE_CHANGED = TRUE;
  179.                             refresh_files(folder->window,NULL,NULL,NULL);
  180.                             XtSetArg(args[0],XtNlabel,(*s == '\0' ? "/" : s));
  181.                             XtSetValues(folder->label,args,1);
  182.                         }
  183.                     }
  184.                 }
  185.                 /*
  186.                  * Angewaehltes File war ein Tar-Archive
  187.                  */
  188.                 else if (file->prog_type == FILE_TAR || file->prog_type == FILE_CTAR) {
  189.                     Dir_Glyph    *dir;
  190.  
  191.                     if (!(dir = (Dir_Glyph *) malloc(sizeof(Dir_Glyph))))
  192.                         FATAL_ERROR("startSingle: DirGlyph-malloc failed");
  193.  
  194.                     dir->parent = folder->dir;
  195.                     if (!(dir->name = (char *) malloc(strlen(file->name)+1)))
  196.                         FATAL_ERROR("startSingle: Name malloc failed\n");
  197.                     sprintf(dir->name,"%s",file->name);
  198.                     dir->dir_count = 0;
  199.  
  200.                     if (defaults.multi_window) {
  201.                         Dir_Glyph    *nd;
  202.  
  203.                         clearSingle (NULL,NULL,NULL,NULL);
  204.                         newFolder (dir);
  205.                     }
  206.                     else {
  207.                         Arg    args[1];
  208.                         char    *s;
  209.  
  210.                         selc_f = 16000;
  211.                         selc_fo = NULL;
  212.                         folder->dir = dir;
  213.  
  214.                         s = getPath(folder->dir);
  215.                         if (strrstr(dir->name,".tar.z\0") || strrstr(dir->name,".tar.gz\0")
  216.                              || strrstr(dir->name,".tar.Z\0") || strrstr(dir->name,".taz\0")
  217.                              || strrstr(dir->name,".tpz\0") || strrstr(dir->name,".tgz\0")) {
  218.                             folder->fs_type = FS_CTAR;
  219.                             fillCTar (folder);
  220.                         }
  221.                         else {
  222.                             folder->fs_type = FS_TAR;
  223.                             fillTar (folder);
  224.                         }
  225.                         FILE_CHANGED = TRUE;
  226.                         refresh_files(folder->window,NULL,NULL,NULL);
  227.                         XtSetArg(args[0],XtNlabel,(*s == '\0' ? "/" : s));
  228.                         XtSetValues(folder->label,args,1);
  229.                     }
  230.                 }
  231.                 /*
  232.                  * Angewaehltes File hatte die x-Flags gesetzt
  233.                  */
  234.                 else if (file->prog_type == FILE_EXEC) {
  235.                     char    buf[300];
  236.                     char    *s = getPath(folder->dir);
  237.  
  238.                     sprintf(buf,"xterm -geometry 80x4 -e %s/%s &\0",s,file->name);
  239.                     SYSTEM(buf);
  240.                     free(s);
  241.                 }
  242.                 /*
  243.                  * Bei sonstigen Files in der Commandsliste nachsuchen
  244.                  */
  245.                 else if (file->prog_type != FILE_PLAIN) {
  246.                     int    i = 0;
  247.  
  248.                     while (filetypes[i].cmd && filetypes[i].type != file->prog_type)
  249.                         i++;
  250.  
  251.                     if (filetypes[i].type == file->prog_type) {
  252.                         char    buf[200];
  253.                         char    *s = getPath(folder->dir);
  254.                         char    nbuf[200];
  255.  
  256.                         sprintf(nbuf,"%s/%s",s,file->name);
  257.                         sprintf(buf,filetypes[i].cmd,nbuf);
  258.                         SYSTEM(buf);
  259.                         free(s);
  260.                         clearSingle(NULL,NULL,NULL,NULL);
  261.                     }
  262.                 }
  263.             }
  264.             else if (selc_fo->file[selc_f]->prog_type == FILE_ROOT &&
  265.                  folder->dir->parent) {
  266.                 Arg    args[1];
  267.                 char    *s;
  268.  
  269.                 folder->dir = folder->dir->parent;
  270.                 s = getPath(folder->dir);
  271.                 selc_f = 16000;
  272.                 folder->fs_type = FS_NORMAL;
  273.                 fillFolder(folder);
  274.                 FILE_CHANGED = TRUE;
  275.                 refresh_files(folder->window,NULL,NULL,NULL);
  276.                 XtSetArg(args[0],XtNlabel,(*s == '\0' ? "/" : s));
  277.                 XtSetValues(folder->label,args,1);                
  278.             }
  279.         }
  280.         /*
  281.          * Timer updaten
  282.          */
  283.         selc_t = e->time;
  284.     }
  285.     else if (w == dir_area) {
  286.         /*
  287.          * Glyph holen
  288.          */
  289.         last_g = getGlyph(&root, e->x,e->y);
  290.         if (last_g)
  291.             last_y = last_g->y + 8;
  292.         else
  293.             last_y = 16000;
  294.  
  295.         /*
  296.          * Nachsehen ob Eintrag schon angewaehlt war. Wenn nicht, dann
  297.          * neu anwaehlen
  298.          */
  299.         if (last_g != selc_g || (selc_f < 16000 && selc_fo)) {
  300.             /*
  301.              * Alte Selection loeschen
  302.              */
  303.             clearSingle (NULL, NULL, NULL, NULL);
  304.  
  305.             /*
  306.              * Markieren
  307.              */
  308.             if (last_g) {
  309.                 selc_g = last_g;
  310.                 drawDir (dir_area, selc_g, TRUE, TRUE);
  311.             }
  312.         }
  313.         /*
  314.          * Eintrag war schon angewaehlt, Pruefen ob Doppelclick
  315.          */
  316.         else if (selc_g && last_g == selc_g &&
  317.              ABSDIFF(e->time,selc_t) < defaults.click_interval) {    /* Innerhalb der Doppelklickid */
  318.  
  319.             /*
  320.              * Nachpruefen ob Directory lesbar ist
  321.              */
  322.             if (selc_g->flags & DIR_READABLE) {
  323.                 if (defaults.multi_window) {
  324.                     newFolder(selc_g);
  325.                 }
  326.                 else {
  327.                     Arg    args[1];
  328.                     char    *s = getPath(selc_g);
  329.  
  330.                     selc_f = 16000;
  331.                     FILE_CHANGED = TRUE;
  332.                     folders[0]->fs_type = FS_NORMAL;
  333.                     folders[0]->dir = selc_g;
  334.                     fillFolder(folders[0]);
  335.                     refresh_files(folders[0]->window,NULL,NULL,NULL);
  336.                     XtSetArg(args[0],XtNlabel,(*s == '\0' ? "/" : s));
  337.                     XtSetValues(folders[0]->label,args,1);
  338.                 }
  339.                 selc_g->open = FALSE;
  340.             }
  341.         }
  342.         /*
  343.          * Timer updaten
  344.          */
  345.         selc_t = e->time;
  346.     }
  347.     else if (w == workspace.window) {
  348.         int    x,y,i;
  349.  
  350.         /*
  351.          * last_ws und last_w holen
  352.          */
  353.         last_ws = &workspace;
  354.         last_w = 16000;
  355.         x = e->x;
  356.         y = e->y;
  357.  
  358.         for (i = 0; last_w == 16000 && i < last_ws->wse_count; i++)
  359.             if (last_ws->wse[i]->x - last_ws->wse[i]->w/2 <= x &&
  360.                 last_ws->wse[i]->x + last_ws->wse[i]->w/2 > x &&
  361.                 last_ws->wse[i]->y <= y &&
  362.                 last_ws->wse[i]->y + last_ws->wse[i]->h > y)
  363.                 last_w = i;
  364.  
  365.         /*
  366.          * Pruefen ob neuer Eintrag im Workspace angewaehlt
  367.          */
  368.         if ((last_ws != selc_ws || last_w != selc_w)) {/* &&
  369.              last_ws && last_w < 16000) {*/
  370.             /*
  371.              * Alte Selection loeschen
  372.              */
  373.             clearSingle (NULL, NULL, NULL, NULL);
  374.  
  375.             /*
  376.              * Markieren
  377.              */
  378.             if (last_ws && last_w < 16000) {
  379.                 selc_ws = last_ws;
  380.                 selc_w = last_w;
  381.                 drawWSE (last_ws, last_w, TRUE, TRUE);
  382.             }
  383.         }
  384.         /*
  385.          * Auf Doppelclick pruefen
  386.          */
  387.         else if (selc_ws == last_ws && last_w == selc_w &&
  388.              ABSDIFF(e->time,selc_t) < defaults.click_interval &&
  389.              !selc_ws->wse[selc_w]->must_arg) {
  390.             /*
  391.              * Doppelclick -> Programm ausfuehren
  392.              */
  393.             if (selc_ws->wse[selc_w]->do_ask)
  394.                 init_exec (selc_ws->wse[selc_w]->file,NULL);
  395.             else
  396.                 exec_exec (selc_ws->wse[selc_w]->file,NULL);
  397.         }
  398.  
  399.         /*
  400.          * Timer updaten
  401.          */
  402.         selc_t = e->time;        
  403.     }
  404.     GRAB = FALSE;
  405.     /*
  406.      * Cursor ruecksetzen
  407.      */
  408.     XDefineCursor (XtDisplay(dir_area), XtWindow(dir_area),
  409.             def_cursor);
  410.     XDefineCursor (XtDisplay(workspace.window), 
  411.             XtWindow(workspace.window), def_cursor);
  412.     for (i = 0; i < folder_count; i++)
  413.         XDefineCursor (XtDisplay(folders[i]->window),
  414.                 XtWindow(folders[i]->window),
  415.                 def_cursor);
  416.     XFlush(XtDisplay(toplevel));
  417. }
  418.  
  419. /*********************************************************
  420.  * name:    followSingle
  421.  * description:    bei gedrueckter Maustaste das Ziel der Graboperation
  422.  *        markieren
  423.  * input:    none
  424.  * output:    none
  425.  * date:    14.6.93
  426.  *********************************************************/
  427. XtActionProc    followSingle   (Widget w, XButtonEvent *e,
  428.                 String *s, Cardinal *c)
  429. {
  430.     /*
  431.      * Feststellen, in welchem Bereich der Pointer sich befindet
  432.      */
  433.     if (w == dir_area && (selc_g || (selc_fo && selc_f < 16000)))
  434.         followDir (w, (XMotionEvent *) e, s, c);
  435.     else if (folder && w == folder->window &&
  436.          (selc_g || (selc_fo && selc_f < 16000)))
  437.         followFile (w, (XMotionEvent *) e, s, c);
  438.     else if (w == workspace.window && (selc_g || (selc_fo && selc_f < 16000)))
  439.         followWS (w, (XMotionEvent *) e, s, c);
  440.     else if (selc_ws && selc_w < 16000 && GRAB) {
  441.         /* Nicht nur ws_move_shell, da die zu langsam ist */
  442.  
  443.         XEvent    ev;
  444.         XMotionEvent    *event;
  445.         int    mx,my;
  446.         Boolean    got;
  447.  
  448.         mx = e->x_root + ws_move_offx;
  449.         my = e->y_root + ws_move_offy;
  450.  
  451.         do {    /* Weitere Events gleich so auslesen, ohne das Fenster zu verschieben */
  452.             got = FALSE;
  453.             if (XCheckWindowEvent(XtDisplay(ws_move_shell),XtWindow(ws_move_shell),
  454.                         ButtonMotionMask | EnterWindowMask
  455.                         | LeaveWindowMask,&ev)) {
  456.                 event = (XMotionEvent *) &ev;
  457.  
  458.                 got = TRUE;
  459.                 mx = event->x_root + ws_move_offx;
  460.                 my = event->y_root + ws_move_offy;
  461.             }
  462.         } while (got);
  463.  
  464.  
  465.         XMoveWindow(XtDisplay(ws_move_shell),XtWindow(ws_move_shell),mx,my);
  466.     }
  467.  
  468.     /*
  469.      * Auf Grabmode schalten - Nur im Dir-Feld und Folder
  470.      */
  471.     if (!GRAB && (selc_g || (selc_fo && selc_f < 16000 && selc_fo->fs_type == FS_NORMAL) || (selc_ws && selc_w < 16000))) {
  472.         int    i;
  473.  
  474.         XUngrabPointer(XtDisplay(toplevel),CurrentTime);
  475.         if (w == workspace.window) {
  476.             ws_move_offx = last_ws->wse[last_w]->x - last_ws->wse[last_w]->w/2 - e->x;
  477.             ws_move_offy = last_ws->wse[last_w]->y - e->y;
  478.  
  479.             ws_move_shell = XtVaCreatePopupShell("ws_move_shell",overrideShellWidgetClass,
  480.                                 workspace.shell,
  481.                                 XtNwidth,last_ws->wse[last_w]->w,
  482.                                 XtNheight,last_ws->wse[last_w]->h,
  483.                                 XtNx, e->x_root + ws_move_offx,
  484.                                 XtNy, e->y_root + ws_move_offy,
  485.                                 XtNborderWidth, 0,
  486.                                 NULL);
  487.             XtOverrideTranslations(ws_move_shell,XtParseTranslationTable(
  488.                                  "<Expose>: refresh-icon() \n\
  489.                                   <Btn1Up>: end-single() \n\
  490.                                   <Btn1Motion>: follow-single()"));
  491.             XtManageChild(ws_move_shell);
  492.             WORKSPACE_CHANGED = TRUE;
  493.  
  494.             /* Shape setzen, damit der Rand verschwindet */
  495.             if (last_ws->wse[last_w]->shape)
  496.                 XShapeCombineMask(XtDisplay(ws_move_shell),XtWindow(ws_move_shell),
  497.                           ShapeBounding,0,0,last_ws->wse[last_w]->shape,
  498.                           ShapeSet);
  499. /*            else if (!last_ws->wse[last_w]->pmap)
  500.                 XShapeCombineMask(XtDisplay(ws_move_shell),XtWindow(ws_move_shell),
  501.                           ShapeBounding,0,0,Shape_Exec_PM,
  502.                           ShapeSet);
  503. */
  504.             /* Pointer grabben */
  505.             XGrabPointer (XtDisplay(toplevel),XtWindow(workspace.window), True,
  506.                     ButtonReleaseMask | Button1MotionMask,
  507.                     GrabModeAsync, GrabModeAsync, 
  508.                     XtWindow(workspace.window), def_cursor,
  509.                     CurrentTime);
  510.         }
  511.         else {    /* Grabben begann nicht ueber einem Icon */
  512.             XGrabPointer (XtDisplay(toplevel),XtWindow(toplevel), True,
  513.                     ButtonReleaseMask | Button1MotionMask,
  514.                     GrabModeAsync, GrabModeAsync, None, file_cursor,
  515.                     CurrentTime);
  516.             if (merge_window)
  517.                 XtOverrideTranslations(merge_window,XtParseTranslationTable(
  518.                             "<Btn1Motion>: no-op()"));
  519.         }
  520.         GRAB = TRUE;
  521.         REFRESH = TRUE;
  522.     }
  523. }
  524.  
  525. /*********************************************************
  526.  * name:    endSingle
  527.  * description:    Die Maustaste wurde losgelassen. Danach
  528.  *        falls eine Graboperation stattgefunden
  529.  *        hat das Ziel bestimmen und die
  530.  *        entsprechende Operation ausfuehren
  531.  * input:    none
  532.  * output:    none
  533.  * date:    14.6.93
  534.  *********************************************************/
  535. XtActionProc    endSingle      (Widget w, XButtonEvent *e,
  536.                 String *s, Cardinal *c)
  537. {
  538.     Arg    args[2],largs[2];
  539.     int    i;
  540.  
  541.     /*
  542.      * Cursor busy
  543.      */
  544.     XDefineCursor (XtDisplay(dir_area), XtWindow(dir_area),
  545.             busy_cursor);
  546.     XDefineCursor (XtDisplay(workspace.window), 
  547.             XtWindow(workspace.window), busy_cursor);
  548.     for (i = 0; i < folder_count; i++)
  549.         XDefineCursor (XtDisplay(folders[i]->window),
  550.                 XtWindow(folders[i]->window),
  551.                 busy_cursor);
  552.     XFlush(XtDisplay(toplevel));
  553.  
  554.     /*
  555.      * Der Endpunkt der Graboperation lag im Dir-Feld
  556.      */
  557.     if (w == dir_area) {
  558.         Dir_Glyph    *dir;
  559.  
  560.         /*
  561.          * Zunaechst einmal muss anhand der Koordinaten das entsprechde
  562.          * Dir_Glyph heraus gesucht werden
  563.          */
  564.         dir = last_g;
  565.  
  566.         if (dir) {
  567.             /*
  568.              * Nachsehen ob gerade eine Move-Grab operation ausgefuehrt wird
  569.              */
  570.             if (GRAB) {
  571.                 int    i;
  572.  
  573.                 if (selc_g && dir != selc_g) {
  574.                     /*
  575.                      * Verschieben des Directories in das gerade selectierte
  576.                      */
  577.                     struct    stat    buf;
  578.                     uid_t        uid = getuid();
  579.                     char        *got1 = getPath(selc_g);
  580.                     char        *got2 = getPath(dir);
  581.  
  582.                     stat(got1,&buf);
  583.                     if (buf.st_uid != uid)
  584.                         init_copy (got1, got2);
  585.                     else
  586.                         init_move (got1, got2);
  587.                     free (got1);
  588.                     free (got2);
  589.                 }
  590.                 else if (selc_fo && selc_fo->dir != dir) {
  591.                     char    sbuf[255];
  592.                     char    *got1;
  593.                     char    *got2;
  594.  
  595.                     /*
  596.                      * Verschieben des Icons vom folder->window in die Dir-area
  597.                      */
  598.                     got1 = getPath(selc_fo->dir);
  599.                     got2 = getPath(dir);
  600.                     if (strcmp(got1,"/"))
  601.                         sprintf(sbuf,"%s/%s",got1,
  602.                             selc_fo->file[selc_f]->name);
  603.                     else
  604.                         sprintf(sbuf,"/%s",
  605.                             selc_fo->file[selc_f]->name);
  606.                     {
  607.                         struct    stat    buf;
  608.                         uid_t        uid = getuid();
  609.  
  610.                         stat(sbuf,&buf);
  611.                         if (buf.st_uid != uid) {
  612.                             if (defaults.drag_copy)
  613.                                 init_copy (sbuf, got2);
  614.                             else
  615.                                 exec_copy (sbuf, got2);
  616.                         }
  617.                         else {
  618.                             if (defaults.drag_move)
  619.                                 init_move (sbuf, got2);
  620.                             else
  621.                                 exec_move (sbuf, got2);
  622.                         }
  623.                     }
  624.                     free(got1);
  625.                     free(got2);
  626.                 }
  627.                 GRAB = FALSE;
  628.                 /*
  629.                  * Unhighlight target
  630.                  */
  631.                 XDrawRectangle(XtDisplay(dir_area),XtWindow(dir_area),
  632.                            back_gc, last_g->x - 4, last_g->y - 2,
  633.                            32 + XTextWidth (defaults.icon_font,
  634.                         last_g->name,strlen(last_g->name)), 20);
  635.             }
  636.             else if (!GRAB) {
  637.                 /*
  638.                  * Nachpruefen ob Directory geoeffnet ist
  639.                  */
  640.                 if (selc_g->open) {
  641.                     if (selc_g->dir_count > 0)
  642.                         DIR_CHANGED = TRUE;
  643.                     selc_g->open = FALSE;
  644.                     refresh_dirs(NULL,NULL,NULL,NULL);
  645.                 }
  646.                 else {
  647.                     if (selc_g->flags & DIR_READABLE) {
  648.                         fillDir(selc_g);
  649.                         if (selc_g->dir_count > 0)
  650.                             DIR_CHANGED = TRUE;
  651.                         refresh_dirs(NULL,NULL,NULL,NULL);
  652.                     }
  653.                 }
  654.             }
  655.             last_g = NULL;
  656.             last_y = 16000;
  657.         }
  658.     }
  659.     /*
  660.      * Der Endpunkt der Grabaktion lag im File-Feld
  661.      */
  662.     else if (folder && w == folder->window) {
  663.         /*
  664.          * Testen ob zum Schluss noch ein Argument aktiviert war
  665.          */
  666.         if (GRAB) {
  667.             int    i;
  668.  
  669.             if (selc_fo && selc_f < 16000 && last_v != selc_f) {
  670.                 char    sbuf[200];
  671.                 char    dbuf[200];
  672.                 char    *got1;
  673.                 char    *got2;
  674.  
  675.                 got1 = getPath(selc_fo->dir);
  676.                 got2 = getPath(folder->dir);
  677.  
  678.                 if (strcmp(got1,"/"))
  679.                     sprintf(dbuf,"%s/%s",got1,selc_fo->file[selc_f]->name);
  680.                 else
  681.                     sprintf(dbuf,"/%s",folder->file[selc_f]->name);
  682.  
  683.                 if (last_v < 16000) {
  684.                     if (strcmp(got2,"/"))
  685.                         sprintf(sbuf,"%s/%s",got2,folder->file[last_v]->name);
  686.                     else
  687.                         sprintf(sbuf,"/%s",folder->file[last_v]->name);
  688.                 }
  689.                 else
  690.                     sprintf(sbuf,"%s",got2);
  691.  
  692.                 if (last_v < 16000 || folder != selc_fo) {
  693.                     if (last_v < 16000 && 
  694.                         folder->file[last_v]->prog_type == FILE_EXEC)
  695.                         init_exec (sbuf,dbuf);
  696.                     else {
  697.                         struct    stat    buf;
  698.                         uid_t        uid = getuid();
  699.  
  700.                         stat(dbuf,&buf);
  701.                         if (buf.st_uid != uid) {
  702.                             if (defaults.drag_copy)
  703.                                 init_copy (dbuf, sbuf);
  704.                             else
  705.                                 exec_copy (dbuf, sbuf);
  706.                         }
  707.                         else {
  708.                             if (defaults.drag_move)
  709.                                 init_move (dbuf, sbuf);
  710.                             else
  711.                                 exec_move (dbuf, sbuf);
  712.                         }
  713.                     }
  714.                 }
  715.  
  716.                 free(got1);
  717.                 free(got2);
  718.             }
  719.             else if (selc_g) {
  720.                 char    sbuf[200];
  721.                 char    *got1 = getPath(folder->dir);
  722.                 char    *got2 = getPath(selc_g);
  723.  
  724.                 if (last_v < 16000) {
  725.                     if (strcmp(got1,"/"))
  726.                         sprintf(sbuf,"%s/%s",got1,folder->file[last_v]->name);
  727.                     else
  728.                         sprintf(sbuf,"/%s",folder->file[last_v]->name);
  729.                 }
  730.                 else
  731.                     sprintf(sbuf,"%s",got1);
  732.  
  733.  
  734.                 if (last_v < 16000 && folder->file[last_v]->prog_type == FILE_EXEC)
  735.                     init_exec (got2,sbuf);
  736.                 else if (last_v < 16000) {
  737.                     struct    stat    buf;
  738.                     uid_t        uid = getuid();
  739.  
  740.                     stat(got2,&buf);
  741.                     if (buf.st_uid != uid) {
  742.                         if (defaults.drag_copy)
  743.                             init_copy (got2, sbuf);
  744.                         else
  745.                             exec_copy (got2, sbuf);
  746.                     }
  747.                     else {
  748.                         if (defaults.drag_move)
  749.                             init_move (got2, sbuf);
  750.                         else
  751.                             exec_move (got2, sbuf);
  752.                     }
  753.                 }
  754.                 free (got1);
  755.                 free (got2);
  756.             }
  757.             GRAB = FALSE;
  758.             /*
  759.              * unhighlight des Grabtargets
  760.              */
  761.             if (last_fo)
  762.                 XDrawRectangle(XtDisplay(last_fo->window),
  763.                            XtWindow(last_fo->window),
  764.                            back_gc, 16, 
  765.                            last_v*DIR_Y_STEP + 4,
  766.                            last_fo->max_length + 50 + typelength, 20);
  767.         }
  768.         last_v = 16000;
  769.     }
  770.     /*
  771.      * Endpunkt lag im Workspace
  772.      */
  773.     else if (w == workspace.window) {
  774.         if (ws_move_shell)
  775.             XtDestroyWidget(ws_move_shell);
  776.         ws_move_shell = NULL;
  777.         if (GRAB) {    /* Es wurde was gezogen */
  778.             if (last_ws && last_w < 16000) {
  779.                 char    s[1024];
  780.  
  781.                 /*
  782.                  * Aus dem Directoyfolder wurde was gedragged
  783.                  */
  784.                 if (selc_g && last_ws->wse[last_w]->can_arg) {
  785.                     char    *d = getPath(selc_g);
  786.  
  787.                     sprintf(s,"%s %s",last_ws->wse[last_w]->file,d);
  788.                     if (defaults.drag_exec)
  789.                         init_exec(s,NULL);
  790.                     else
  791.                         exec_exec(s,NULL);
  792.                     free(d);
  793.                 }
  794.                 else if (selc_fo && selc_f < 16000 &&
  795.                      last_ws->wse[last_w]->can_arg) {
  796.                     char    *d = getPath(selc_fo->dir);
  797.  
  798.                     if (strcmp(d,"/"))
  799.                         sprintf(s,"%s %s/%s",last_ws->wse[last_w]->file,
  800.                                 d,selc_fo->file[selc_f]->name);
  801.                     else
  802.                         sprintf(s,"%s /%s",last_ws->wse[last_w]->file,
  803.                                 selc_fo->file[selc_f]->name);
  804.                     if (defaults.drag_exec)
  805.                         init_exec(s,NULL);
  806.                     else
  807.                         exec_exec(s,NULL);
  808.                     free(d);                    
  809.                 }
  810.                 /*
  811.                  * Ziel unhighlighten
  812.                  */
  813.                 XDrawRectangle(XtDisplay(toplevel),
  814.                         XtWindow(last_ws->window),
  815.                         back_gc,
  816.                         last_ws->wse[last_w]->x - last_ws->wse[last_w]->w/2 - 1,
  817.                         last_ws->wse[last_w]->y - 1,
  818.                         last_ws->wse[last_w]->w +1, last_ws->wse[last_w]->h + 1);
  819.                 last_ws = NULL;
  820.                 last_w = 16000;
  821.             }
  822.             /*
  823.              * Neuen Eintrag im Workspace erzeugen - provisorisch
  824.              */
  825.             else if (last_ws && selc_fo && selc_f < 16000) {
  826.                 char    *d = getPath(selc_fo->dir);
  827.                 char    s[1024];
  828.  
  829.                 if (strcmp(d,"/"))
  830.                     sprintf(s,"%s/%s",d,selc_fo->file[selc_f]->name);
  831.                 else
  832.                     sprintf(s,"/%s",selc_fo->file[selc_f]->name);
  833.                 free(d);
  834.                 if (!(d = (char *) malloc (strlen(s)+1)))
  835.                     FATAL_ERROR("endSingle: Malloc failed");
  836.                 sprintf(d,"%s",s);
  837.                 addWSEtoWS(last_ws,selc_fo->file[selc_f]->name,d,
  838.                         NULL,TRUE,FALSE,TRUE,10,10);
  839.                 refreshWS(last_ws->window,NULL,NULL,NULL);
  840.             }
  841.             else if (selc_ws && selc_w < 16000) {
  842.                 int    x,y,rx,ry;
  843.                 unsigned int    mask;
  844.                 Window    child,root;
  845.                 int    mx,my;
  846.  
  847.                 XQueryPointer(XtDisplay(selc_ws->window),XtWindow(selc_ws->window),
  848.                         &root,&child,&rx,&ry,&x,&y,&mask);
  849.                 mx = x + ws_move_offx + selc_ws->wse[selc_w]->w/2;
  850.                 my = y + ws_move_offy;
  851.                 selc_ws->wse[selc_w]->x = mx;
  852.                 selc_ws->wse[selc_w]->y = my;
  853.                 XClearWindow(XtDisplay(selc_ws->window),XtWindow(selc_ws->window));
  854.                 refreshWS(selc_ws->window,NULL,NULL,NULL);        
  855.             }
  856.             GRAB = FALSE;
  857.         }
  858.     }
  859.     else if (w == ws_move_shell) {
  860.         int    x,y,rx,ry;
  861.         unsigned int    mask;
  862.         Window    child,root;
  863.         int    mx,my;
  864.  
  865.         if (ws_move_shell)
  866.             XtDestroyWidget(ws_move_shell);
  867.         ws_move_shell = NULL;
  868.         XQueryPointer(XtDisplay(selc_ws->window),XtWindow(selc_ws->window),
  869.                 &root,&child,&rx,&ry,&x,&y,&mask);
  870.         mx = x + ws_move_offx + selc_ws->wse[selc_w]->w/2;
  871.         my = y + ws_move_offy;
  872.         selc_ws->wse[selc_w]->x = mx;
  873.         selc_ws->wse[selc_w]->y = my;
  874.         XClearWindow(XtDisplay(selc_ws->window),XtWindow(selc_ws->window));
  875.         refreshWS(selc_ws->window,NULL,NULL,NULL);        
  876.         GRAB = FALSE;
  877.     }
  878.     else if (w == merge_window && GRAB){
  879.         char    *got;
  880.         char    s[300];
  881.         XawTextBlock    text;
  882.         char    *a;
  883.         XawTextPosition    pos;
  884.  
  885.         if (selc_g) {
  886.             got = getPath(selc_g);
  887.             sprintf(s,"%s\n",got);
  888.             free(got);
  889.         }
  890.         else if (selc_fo && selc_f < 16000) {
  891.             got = getPath(selc_fo->dir);
  892.             if (strcmp(got,"/"))
  893.                 sprintf(s,"%s/%s\n",got,selc_fo->file[selc_f]->name);
  894.             else
  895.                 sprintf(s,"/%s\n",selc_fo->file[selc_f]->name);
  896.             free(got);
  897.         }
  898.         XawTextSetInsertionPoint(merge_window,0);
  899.         text.ptr = s;
  900.         text.length = strlen(s);
  901.         text.format = FMT8BIT;
  902.         text.firstPos = 0;
  903.         if ((pos = XawTextSearch(merge_window,XawsdRight,&text)) == XawTextSearchError) {
  904.             text.ptr = s;
  905.             text.length = strlen(s);
  906.             text.firstPos = 0;
  907.             text.format = FMT8BIT;
  908.             XtVaSetValues(merge_window,XtNeditType,XawtextAppend,NULL);
  909.             XawTextReplace(merge_window,0,0,&text);
  910.             XtVaSetValues(merge_window,XtNeditType,XawtextRead,NULL);
  911.         }
  912.         else {
  913.             XawTextSetSelection(merge_window,pos,pos+text.length);
  914.             WARNING("Item is allready in this package");
  915.         }
  916.         GRAB = FALSE;        
  917.     }
  918.  
  919.     if (merge_window)
  920.         XtOverrideTranslations(merge_window,XtParseTranslationTable(
  921.                         "<Btn1Motion>: extend-adjust()"));
  922.     /*
  923.      * Cursor ruecksetzen
  924.      */
  925.     XUngrabPointer (XtDisplay(toplevel),CurrentTime);
  926.     XDefineCursor (XtDisplay(dir_area), XtWindow(dir_area),
  927.             def_cursor);
  928.     XDefineCursor (XtDisplay(workspace.window), 
  929.             XtWindow(workspace.window), def_cursor);
  930.     for (i = 0; i < folder_count; i++)
  931.         XDefineCursor (XtDisplay(folders[i]->window),
  932.                 XtWindow(folders[i]->window),
  933.                 def_cursor);
  934.     XFlush(XtDisplay(toplevel));
  935. }
  936.  
  937. /*********************************************************
  938.  * name:    clearSingle
  939.  * description:    SingleSelection loeschen
  940.  * input:    none
  941.  * output:    none
  942.  * date:    14.6.93
  943.  *********************************************************/
  944.  
  945. XtActionProc    clearSingle    (Widget w, XEvent *e,
  946.                 String *s, Cardinal *c)
  947. {
  948.     /*
  949.      * Zunaechst nachsehen ob noch ein Single-Select besteht.
  950.      * Wenn ja, dann loeschen.
  951.      */
  952.     if (selc_g) {
  953.         drawDir (dir_area, selc_g, FALSE, TRUE);
  954.         selc_g = NULL;
  955.         selc_f = 16000;
  956.         selc_fo = NULL;
  957.         selc_ws = NULL;
  958.         selc_w = 16000;
  959.     }
  960.     else if (selc_fo && selc_f < 16000) {
  961.         drawFile (selc_fo, selc_f, FALSE, TRUE);
  962.         selc_f = 16000;
  963.         selc_fo = NULL;
  964.         selc_g = NULL;
  965.         selc_ws = NULL;
  966.         selc_w = 16000;
  967.     }
  968.     else if (selc_ws && selc_w < 16000) {
  969.         drawWSE (selc_ws, selc_w, FALSE, TRUE);
  970.         selc_f = 16000;
  971.         selc_fo = NULL;
  972.         selc_g = NULL;
  973.         selc_ws = NULL;
  974.         selc_w = 16000;
  975.     }
  976. }
  977.  
  978.  
  979. /*********************************************************
  980.  * name:    followFile
  981.  * description:    Der Mauszeiger wird im gedrueckten Zustand im Folder bewegt
  982.  * input:    Widget        w    - Das Fenster
  983.  *        XMotionEvent    *e    - Der Event
  984.  *        String        *s    - unused
  985.  *        Cardinal    *c    - unused
  986.  * output:    none
  987.  * author:    Ove Kalkan
  988.  * date:    15.6.93
  989.  *********************************************************/
  990. XtActionProc     followFile (Widget w, XMotionEvent *e, String *s, Cardinal *c)
  991. {
  992.     int        y;
  993.  
  994.     y = (e->y - 4)/DIR_Y_STEP;
  995.     if (folder && y != last_v) {
  996.         if (last_v < 16000 && last_fo) {
  997.             XDrawRectangle(XtDisplay(last_fo->window),
  998.                        XtWindow(last_fo->window),
  999.                        back_gc, 16, last_v*DIR_Y_STEP + 4,
  1000.                        last_fo->max_length + 50 + typelength, 20);
  1001.             last_v = 16000;
  1002.             last_fo = NULL;
  1003.         }
  1004.         if (y < folder->file_count && y >= 0) {
  1005.             File_Glyph    *file;
  1006.             uid_t         uid = getuid();
  1007.             gid_t        gid = getgid();
  1008.  
  1009.             file = folder->file[y];
  1010.             if ((uid == file->uid && S_IWUSR&file->mode) ||
  1011.                        (gid == file->gid && S_IWGRP&file->mode) ||
  1012.                  S_IWOTH&file->mode) {
  1013.                 last_v = y;
  1014.                 last_fo = folder;
  1015.                 if (GRAB && (last_v != selc_f || folder != selc_fo))
  1016.                     XDrawRectangle(XtDisplay(folder->window),XtWindow(folder->window),
  1017.                                selc_gc, 16, last_v*DIR_Y_STEP + 4,
  1018.                                folder->max_length + 50 + typelength, 20);
  1019.             }
  1020.         }
  1021.     }
  1022. }
  1023.  
  1024.  
  1025.  
  1026. /*********************************************************
  1027.  * name:    followDir
  1028.  * description:    Der Mauszeiger wird im gedrueckten Zustand im DirWindow bewegt
  1029.  * input:    Widget        w    - Das Fenster
  1030.  *        XMotionEvent    *e    - Der Event
  1031.  *        String        *s    - unused
  1032.  *        Cardinal    *c    - unused
  1033.  * output:    none
  1034.  * author:    Ove Kalkan
  1035.  * date:    15.6.93
  1036.  *********************************************************/
  1037. XtActionProc     followDir (Widget w, XMotionEvent *e, String *s, Cardinal *c)
  1038. {
  1039.     Dir_Glyph    *dir;
  1040.     int        y;
  1041.  
  1042.     /*
  1043.      * Nachsehen ob eventuell wieder in einem neuen Feld
  1044.      */
  1045.     y = (e->y - last_y < 0) ? (last_y - e->y) : (e->y - last_y);
  1046.     if (y > DIR_Y_STEP/2) {
  1047.         if (last_g) {
  1048.             XDrawRectangle(XtDisplay(dir_area),XtWindow(dir_area),
  1049.                        back_gc, last_g->x - 4, last_g->y - 2,
  1050.                        32 + XTextWidth (defaults.icon_font,
  1051.                     last_g->name,strlen(last_g->name)), 20);
  1052.             last_y = 16000;
  1053.             last_g = NULL;
  1054.         }
  1055.         dir = getGlyph(&root,e->x,e->y);
  1056.         if (dir) {
  1057.             if (dir->flags & DIR_WRITEABLE) {
  1058.                 last_g = dir;
  1059.                 if (GRAB && selc_g != last_g && (selc_fo == NULL || selc_f == 16000 || selc_fo->dir != dir))
  1060.                     XDrawRectangle(XtDisplay(dir_area),XtWindow(dir_area),
  1061.                                selc_gc, last_g->x - 4, last_g->y - 2,
  1062.                                32 + XTextWidth (defaults.icon_font,
  1063.                             last_g->name,strlen(last_g->name)), 20);
  1064.                 last_y = dir->y + 8;
  1065.             }
  1066.         }
  1067.     }
  1068. }
  1069.  
  1070.  
  1071. /*********************************************************
  1072.  * name:    followWS
  1073.  * description:    Auf ButtonMotionEvents im Workspace achten
  1074.  * input:    MotionEvent *e    - Der Event mit den
  1075.  *                  Koordinaten
  1076.  * output:    none
  1077.  * author:    Ove Kalkan
  1078.  * date:    29.6.1993
  1079.  *********************************************************/
  1080. XtActionProc     followWS (Widget w, XMotionEvent *e, String *s, Cardinal *c)
  1081. {
  1082.     int        x,y,i;
  1083.     WS_Glyph     *new_ws;
  1084.     Dimension    new_w = 16000;
  1085.  
  1086.     /*
  1087.      * last_ws und last_w holen
  1088.      */
  1089.     new_ws = &workspace;
  1090.  
  1091.     x = e->x;
  1092.     y = e->y;
  1093.  
  1094.     for (i = 0; new_w == 16000 && i < new_ws->wse_count; i++)
  1095.         if (new_ws->wse[i]->x - new_ws->wse[i]->w/2 <= x &&
  1096.             new_ws->wse[i]->x + new_ws->wse[i]->w/2 > x &&
  1097.             new_ws->wse[i]->y <= y &&
  1098.             new_ws->wse[i]->y + new_ws->wse[i]->h > y)
  1099.             new_w = i;
  1100.  
  1101.     /*
  1102.      * Altes Member dehighlighten
  1103.      */
  1104.     if (new_ws != last_ws || new_w != last_w) {
  1105.         if (last_ws && last_w < 16000) {
  1106.             XDrawRectangle(XtDisplay(toplevel),
  1107.                     XtWindow(last_ws->window),
  1108.                     back_gc, 
  1109.                     last_ws->wse[last_w]->x - last_ws->wse[last_w]->w/2 - 1,
  1110.                     last_ws->wse[last_w]->y - 1,
  1111.                     last_ws->wse[last_w]->w + 1, last_ws->wse[last_w]->h + 1);
  1112.             last_ws = NULL;
  1113.             last_w = 16000;
  1114.         }
  1115.         last_ws = new_ws;
  1116.         if (new_ws && new_w < 16000) {
  1117.             last_w = new_w;
  1118.             last_ws = new_ws;
  1119.             if (last_ws->wse[last_w]->can_arg)
  1120.                 XDrawRectangle(XtDisplay(toplevel),
  1121.                         XtWindow(last_ws->window),
  1122.                         selc_gc,
  1123.                         last_ws->wse[last_w]->x - last_ws->wse[last_w]->w/2 - 1,
  1124.                         last_ws->wse[last_w]->y - 1,
  1125.                         last_ws->wse[last_w]->w + 1, last_ws->wse[last_w]->h + 1);
  1126.         }
  1127.     }        
  1128. }
  1129.  
  1130.  
  1131. /*********************************************************
  1132.  * name:    refresh_icon
  1133.  * description:    neuzeichnen des Inhalts des gerade verschobenen Icons
  1134.  * input:    Das uebliche fuer XtActionProcs
  1135.  * output:    none
  1136.  * author:    Ove Kalkan
  1137.  * date:    10.8.1993
  1138.  *********************************************************/
  1139.  
  1140. XtActionProc    refresh_icon   (Widget w, XExposeEvent *e, 
  1141.                 String *s, Cardinal *c)
  1142. {
  1143.     if (selc_ws->wse[selc_w]->pmap)
  1144.         XCopyArea(XtDisplay(w),selc_ws->wse[selc_w]->pmap,XtWindow(w),selc_gc,
  1145.                 0,0,selc_ws->wse[selc_w]->w,selc_ws->wse[selc_w]->h,0,0);
  1146.     else
  1147.         XCopyArea(XtDisplay(w),File_Exec_PM,XtWindow(w),selc_gc,
  1148.                 0,0,16,16,0,0);
  1149. }