dtwm: basic multihead(xinerama only) support
[oweals/cde.git] / cde / programs / dtfile / Desktop.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: Desktop.c /main/13 1999/09/10 09:42:26 mgreess $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *   FILE:           Desktop.c
27  *
28  *   COMPONENT_NAME: Desktop File Manager (dtfile)
29  *
30  *   DESCRIPTION:    Contains functions related to Desktop operations.
31  *
32  *   FUNCTIONS: BuildDesktopLinks
33  *              BuildNewOrderlist
34  *              CalculateRootCoordinates
35  *              CheckDesktopMarquee
36  *              CleanUpWSName
37  *              CreatePopupMenu
38  *              DTActionCallback
39  *              DTFileIsSelected
40  *              DeselectDTFile
41  *              DeselectAllDTFiles
42  *              DesktopObjectChanged
43  *              DesktopObjectRemoved
44  *              SelectDTFile
45  *              DrawAInput
46  *              DropOnDesktopObject
47  *              FreeCachedIcons
48  *              FreeDesktopWindow
49  *              FreeUpOldWorkspace
50  *              GenerateShape
51  *              GetWorkspaceNum
52  *              InitializeDesktopGrid
53  *              InitializeDesktopWindows
54  *              InitializeNewWorkspaces
55  *              IsAFileOnDesktop2
56  *              LoadDesktopInfo
57  *              MakeDesktopWindow
58  *              OpenFolder
59  *              ProcessBufferDropOnFolderDT
60  *              ProcessDTSelection
61  *              ProcessDropOnDesktopObject
62  *              ProcessMoveCopyLinkDT
63  *              ProcessNewViewDT
64  *              PutOnDTCB
65  *              RegisterIconDropsDT
66  *              RegisterInGrid
67  *              RegisterPanelInGrid
68  *              RemoveDT
69  *              RemoveMovedObjectFromDT
70  *              RunDTCommand
71  *              SaveDesktopInfo
72  *              SetupDesktopWindow
73  *              TimerEvent
74  *              UnpostDTTextField
75  *              WorkSpaceRemoved
76  *              popupMenu
77  *              renameDT
78  *
79  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
80  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
81  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
82  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
83  *
84  ****************************************************************************
85  ************************************<+>*************************************/
86 #include <sys/types.h>
87 #include <stdio.h>
88 #include <errno.h>
89 #include <sys/stat.h>
90 #include <dirent.h>
91
92 #include <Xm/XmP.h>
93 #include <Xm/Xm.h>
94 #include <Xm/MwmUtil.h>
95 #include <X11/ShellP.h>
96 #include <X11/Shell.h>
97 #include <X11/Xutil.h>
98 #include <X11/Xatom.h>
99
100 #ifdef SHAPE
101 #include <X11/extensions/shape.h>
102 #endif
103
104 #include <Xm/DrawingA.h>
105 #include <Xm/Frame.h>
106 #include <Xm/PushBG.h>
107 #include <Xm/RowColumn.h>
108 #include <Xm/CascadeBG.h>
109 #include <Xm/LabelG.h>
110 #include <Xm/SeparatoG.h>
111 #include <Xm/VirtKeys.h>
112
113 #include <Dt/Icon.h>
114 #include <Dt/IconP.h>
115 #include <Dt/IconFile.h>
116 #include <Dt/Connect.h>
117 #include <Dt/Dts.h>
118 #include <Dt/Wsm.h>
119 #include <Dt/WsmM.h>
120 #include <Dt/UserMsg.h>
121 #include <Dt/DtNlUtils.h>
122
123 #include <Xm/DragIcon.h>
124 #include <Xm/DragC.h>
125 #include <Dt/Dnd.h>
126 #include <Dt/HourGlass.h>
127
128 #include <Dt/ActionP.h>
129 #include <Dt/Action.h>
130 #include <Dt/Session.h>
131 #include <Dt/SharedProcs.h>
132
133 #include <Tt/tttk.h>
134
135 #include "Encaps.h"
136 #include "SharedProcs.h"
137 #include "Desktop.h"
138 #include "FileMgr.h"
139 #include "Main.h"
140 #include "Prefs.h"
141 #include "Help.h"
142 #include "SharedMsgs.h"
143
144 extern char *dt_path;
145
146 /* Don't use '#define'; leads to multiple copies of the string */
147 static char DESKTOP_SAVE_NAME[] =  ".!dtdesktop";
148
149 DesktopData *desktop_data;
150 Widget widget_dragged;
151 DesktopRec *sacredDesktop;
152 unsigned char *desktop_grid;
153 unsigned short int desktop_grid_size;
154
155
156 static void ProcessNewViewDT ( DesktopRec *desktopWindow ) ;
157 static void ProcessMoveCopyLinkDT ( char *command,
158                                     DesktopRec *desktopWindow,
159                                     DtDndDropCallbackStruct *drop_parameters ) ;
160 static void ProcessBufferDropOnFolderDT ( char *command,
161                                     DesktopRec *desktopWindow,
162                                     DtDndDropCallbackStruct *drop_parameters ) ;
163 static FileViewData * BuildNewOrderlist(
164                       FileViewData *order_list,
165                       Widget icon,
166                       char *hostName,
167                       char *dirName,
168                       char *file,
169                       Boolean is_registered,
170                       Boolean IsToolBox) ;
171 static void FreeDesktopWindow ( DesktopRec *desktopWindow ) ;
172 static void FreeCachedIcons ( int iconsToBeFreed ) ;
173 static void CreatePopupMenu ( Widget drawA ) ;
174 static void popupMenu (
175                       Widget w,
176                       XtPointer client_data,
177                       XtPointer call_data) ;
178 static void OpenFolder (
179                       Widget w,
180                       XtPointer client_data,
181                       XtPointer call_data) ;
182 static void renameDT (
183                       Widget w,
184                       XtPointer client_data,
185                       XtPointer call_data) ;
186 static void BuildDesktopLinks ( Display *display ) ;
187 static int InitializeNewWorkspaces (
188                       Display *display,
189                       char *workspaceName) ;
190 static void TimerEvent(
191                       Widget widget,
192                       XtIntervalId *id) ;
193 static void DropOnDesktopObject (
194                       Widget w,
195                       XtPointer client_data,
196                       XtPointer call_data) ;
197 static void DrawAInput (
198                       Widget w,
199                       XtPointer client_data,
200                       XEvent *event,
201                       Boolean *contDispatch) ;
202 static void CalculateRootCoordinates (
203                       int ws_num,
204                       int width,
205                       int height,
206                       int *root_x,
207                       int *root_y) ;
208
209 static int GetWorkspaceNum(
210                       char *workspace_name,
211                       int NumWorkspaces,
212                       int *workspace_index);
213 static void FreeUpOldWorkspace(
214                       int oldNumWorkspaces,
215                       int old_ws_num,
216                       int ws_num,
217                       int old_index,
218                       int new_index);
219
220 #define NULL_STRING "NULL"
221
222
223 /************************************************************************
224  *
225  *  InitializeDesktopWindows
226  *
227  ************************************************************************/
228
229 void
230 InitializeDesktopWindows(
231        int number_cache,
232        Display *display)
233 {
234    DesktopRec *desktop;
235
236    int n, i, new_size;
237    Arg args[20];
238    char   *popup_name;
239    Widget pu_shell, frame, drawA;
240    XtTranslations trans_table;
241
242    if(desktop_data == NULL)
243    {
244       desktop_data = (DesktopDataPtr)XtMalloc(sizeof(DesktopData));
245       desktop_data->desktopWindows =
246                (DesktopRec ** )XtMalloc(sizeof(DesktopRec *) * number_cache);
247
248       desktop_data->popupMenu = (PopupRec *)XtMalloc(sizeof(PopupRec));
249       desktop_data->popupMenu->popup = NULL;
250       desktop_data->popupMenu->action_pane_file_type = NULL;
251       desktop_data->numCachedIcons = 0;
252       desktop_data->popup_name_count = 0;
253       desktop_data->numIconsUsed = 0;
254       new_size = number_cache;
255
256       /*
257        *  Build desktop directories and get the number of workspaces for
258        *  this screen.
259        */
260       BuildDesktopLinks(display);
261    }
262    else
263    {
264       new_size = number_cache + desktop_data->numCachedIcons +
265                                              desktop_data->numIconsUsed;
266       desktop_data->desktopWindows =
267                (DesktopRec ** )XtRealloc((char *)desktop_data->desktopWindows,
268                                             sizeof(DesktopRec *) * new_size);
269    }
270
271    for(i = desktop_data->numCachedIcons + desktop_data->numIconsUsed;
272                                                       i < new_size; i++)
273    {
274       desktop = (DesktopRec *)XtMalloc(sizeof(DesktopRec));
275       popup_name = (char *)XtMalloc(strlen("popup_name") + 11);
276       sprintf( popup_name, "popup_name%d", desktop_data->popup_name_count);
277
278       n = 0;
279       XtSetArg (args[n], XmNmwmFunctions, NULL); n++;
280       XtSetArg (args[n], XmNmwmDecorations, NULL); n++;
281       XtSetArg (args[n], XmNallowShellResize, True); n++;
282       XtSetArg (args[n], XmNvisual, CopyFromParent); n++;
283       desktop->shell = pu_shell =
284       XtCreatePopupShell(popup_name,
285                          topLevelShellWidgetClass, toplevel, args, n);
286       /* We need to save the background color for the popup shell.  When
287        * we activate a text edit widget for the label of a workspace object,
288        * the shell's background_pixel color will change.  If we don't save
289        * the old background color and reuse the icon gadget, the background
290        * will be different
291        */
292       XtSetArg(args[0], XmNbackground, &desktop->background);
293       XtGetValues(desktop->shell, args, 1);
294
295       XtFree(popup_name);
296       popup_name = NULL;
297
298       n = 0;
299       XtSetArg (args[n], XmNmarginWidth, 1); n++;
300       XtSetArg (args[n], XmNmarginHeight, 1); n++;
301       XtSetArg (args[n], XmNshadowThickness, 2); n++;
302       XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT); n++;
303       XtSetArg (args[n], XmNautoUnmanage, False); n++;
304       XtSetArg (args[n], XmNbackgroundPixmap, XmUNSPECIFIED_PIXMAP); n++;
305       desktop->frame = frame = XmCreateFrame(pu_shell, "frame", args, n);
306       XtManageChild (frame);
307
308       n = 0;
309       XtSetArg (args[n], XmNmarginWidth, 1); n++;
310       XtSetArg (args[n], XmNmarginHeight, 1); n++;
311       XtSetArg (args[n], XmNshadowThickness, 0); n++;
312       XtSetArg (args[n], XmNautoUnmanage, False); n++;
313       XtSetArg (args[n], XmNbackgroundPixmap, XmUNSPECIFIED_PIXMAP); n++;
314       desktop->drawA = drawA = XmCreateDrawingArea(frame, "drawA", args, n);
315       XtManageChild (drawA);
316
317
318       if(desktop_data->popupMenu->popup == NULL)
319       {
320          CreatePopupMenu(drawA);
321          sacredDesktop = desktop;
322       }
323       else
324          XmAddToPostFromList(desktop_data->popupMenu->popup, drawA);
325
326       /* set up translations in main edit widget */
327       trans_table = XtParseTranslationTable(translations_da);
328
329       /* set up translations in main edit widget */
330       XtOverrideTranslations(drawA, trans_table);
331
332       /* Event handler for posting popup menu */
333       XtAddEventHandler(drawA, ButtonPressMask, False,
334                          DrawAInput, (XtPointer)desktop);
335
336       /* Callback for handling selection */
337       XtAddCallback(drawA, XmNinputCallback,
338                     FileWindowInputCallback, (XtPointer)desktop);
339
340       /* Event handler for detecting drag threshold surpassed */
341       XtAddEventHandler(drawA, Button1MotionMask|Button2MotionMask,
342                         False, (XtEventHandler)FileIconMotion, NULL);
343
344       n = 0;
345       XtSetArg (args[n], XmNfillMode, XmFILL_TRANSPARENT);            n++;
346       XtSetArg (args[n], XmNarmColor, white_pixel);                   n++;
347 #ifdef SHAPE
348       XtSetArg (args[n], XmNshadowThickness, 2);                      n++;
349 #else
350       XtSetArg (args[n], XmNshadowThickness, 0);                      n++;
351 #endif
352       XtSetArg (args[n], XmNfontList, user_font);                     n++;
353       XtSetArg (args[n], XmNspacing, 3);                              n++;
354       if( keybdFocusPolicy == XmEXPLICIT)
355       {
356          XtSetArg (args[n], XmNtraversalOn, True);                    n++;
357
358       }
359       else
360       {
361          XtSetArg (args[n], XmNtraversalOn, False);                   n++;
362          XtSetArg (args[n], XmNhighlightThickness, 0);                n++;
363       }
364       XtSetArg (args[n], XmNborderType, DtNON_RECTANGLE);            n++;
365       XtSetArg (args[n], "drawShadow", True);                         n++;
366       if(desktopIconType == LARGE)
367          XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_TOP);
368       else
369          XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_LEFT);
370       n++;
371       desktop->iconGadget = _DtCreateIcon (drawA, "desktop_icon", args, n);
372       XtManageChild (desktop->iconGadget);
373       XtAddCallback (desktop->iconGadget, XmNhelpCallback,
374                      (XtCallbackProc)DTHelpRequestCB, NULL);
375
376       desktop->view = UNSET_VALUE;
377       desktop->order = UNSET_VALUE;
378       desktop->direction = UNSET_VALUE;
379       desktop->positionEnabled = UNSET_VALUE;
380       desktop->restricted_directory = NULL;
381       desktop->title=  NULL;
382       desktop->helpVol = NULL;
383       desktop->toolbox = False;
384       desktop->registered = False;
385       desktop->text = NULL;
386       desktop->root_x = -1;
387       desktop->root_y = -1;
388       desktop->workspace_name = NULL;
389       desktop->workspace_num = 0;
390       desktop->file_name = NULL;
391
392       desktop_data->numCachedIcons++;
393       desktop_data->popup_name_count++;
394
395       desktop_data->desktopWindows[i] = desktop;
396    }
397
398 }
399
400
401 void
402 RegisterIconDropsDT(
403       DesktopRec *desktopWindow)
404 {
405    XSync(XtDisplay(desktopWindow->shell), 0);
406
407    SetHotRects(desktopWindow->file_view_data,
408                DropOnDesktopObject,
409                (XtPointer) desktopWindow);
410
411    XtRemoveAllCallbacks(desktopWindow->iconGadget, XmNcallback);
412    XtAddCallback (desktopWindow->iconGadget,
413                   XmNcallback,
414                   (XtCallbackProc)IconCallback,
415                   desktopWindow->file_view_data);
416 }
417
418
419 /**********************************************************************
420  *
421  *  BuildNewOrderlist - builds a new file_view for a Desktop object.
422  *          If the order_list is NULL, then stat the file and build it
423  *          from there. If order_list in not NULL then use it to build the
424  *          new file_view.
425  *
426  **********************************************************************/
427 static FileViewData *
428 BuildNewOrderlist(
429      FileViewData *order_list,
430      Widget icon,
431      char *hostName,
432      char *dirName,
433      char *file,
434      Boolean is_registered,
435      Boolean IsToolBox)
436 {
437    FileViewData *file_view_data;
438    FileData *file_data;
439    char *full_dir_name;
440
441    file_view_data = (FileViewData *)XtMalloc(sizeof(FileViewData));
442    file_view_data->directory_set =
443                       (XtPointer)XtMalloc(sizeof(DirectorySet));
444
445    ((DirectorySet *)file_view_data->directory_set)->file_count = 1;
446    ((DirectorySet *)file_view_data->directory_set)->file_view_data = NULL;
447    ((DirectorySet *)file_view_data->directory_set)->order_list = NULL;
448    ((DirectorySet *)file_view_data->directory_set)->filtered_file_count = 0;
449    ((DirectorySet *)file_view_data->directory_set)->invisible_file_count = 0;
450    ((DirectorySet *)file_view_data->directory_set)->file_mgr_data = NULL;
451
452    file_view_data->parent =
453      file_view_data->next =
454      file_view_data->desc = NULL;
455    file_view_data->filtered = False;
456    file_view_data->displayed = True;
457    file_view_data->registered = is_registered;
458    file_view_data->ts = tsNotRead;
459    file_view_data->ndir =
460      file_view_data->nfile =
461      file_view_data->nnew = 0;
462    file_view_data->widget = icon;
463    file_view_data->treebtn = NULL;
464    file_view_data->position_info = NULL;
465
466    if(order_list != NULL)
467    {
468       file_view_data->file_data = file_data =
469          (FileData *)XtMalloc(sizeof(FileData));
470
471       file_data->link = NULL;
472       file_data->next = NULL;
473       file_data->is_subdir = False;
474       file_data->is_broken = False;
475
476       file_data->file_name = XtNewString(order_list->file_data->file_name);
477       file_data->action_name = XtNewString(order_list->file_data->action_name);
478       file_data->physical_type = order_list->file_data->physical_type;
479       file_data->logical_type = order_list->file_data->logical_type;
480       file_data->errnum = order_list->file_data->errnum;
481       file_data->stat = order_list->file_data->stat;
482
483       ((DirectorySet *)file_view_data->directory_set)->name =
484          XtNewString( ((DirectorySet *)order_list->directory_set)->name );
485    }
486    else
487    {
488       Tt_status tt_status;
489
490       full_dir_name = ResolveLocalPathName(hostName, dirName, NULL,
491                                            home_host_name, &tt_status);
492       if( TT_OK == tt_status )
493       {
494         FileData2 file_data2;
495         int n;
496
497         DtEliminateDots (full_dir_name);
498
499         if (strcmp(file, ".") == 0) {
500            ReadFileData2(&file_data2, full_dir_name, NULL,IsToolBox);
501         } else {
502            ReadFileData2(&file_data2, full_dir_name, file,IsToolBox);
503         }
504         file_view_data->file_data = FileData2toFileData(&file_data2, &n);
505         XtFree(full_dir_name);
506         full_dir_name = NULL;
507       }
508
509       ((DirectorySet *)file_view_data->directory_set)->name =
510                                                          XtNewString(dirName);
511    }
512
513    return(file_view_data);
514 }
515
516
517 /************************************************************************
518  *
519  *  DesktopObjectRemoved()
520  *    Called when it is detected that an object that a desktop icon
521  *    refers to no longer exists.  Removes the icon window from the
522  *    screen and removes the object from the list of desktop objects.
523  *
524  ***********************************************************************/
525
526 void
527 DesktopObjectRemoved( DesktopRec *desktopWindow )
528 {
529   WorkspaceRec * workSpace;
530   int i, j, k, l;
531
532   /* Remove the object from the screen*/
533   XtPopdown(desktopWindow->shell);
534   XWithdrawWindow(XtDisplay(desktopWindow->shell),
535                   XtWindow(desktopWindow->shell),
536                   XDefaultScreen(XtDisplay(desktopWindow->shell)));
537
538   /*
539     File manager has 2 lists to deal with when a file is on the desktop
540     1. desktop_data->desktopWindows and
541     2. desktop_data->workspaceData[n]->selectedDTWindows
542
543     list 1 contains all files that are on desktop.
544     list 2 contains all files on desktop that are SELECTED.
545
546     At this point, for some reason, the file is no longer present
547       in the system. Remove it/them from both lists.
548
549       NOTE: This is very inefficient code but have no other
550       implementation choices.  Prefer trash to do it, but all trash
551       handlers are designed to accept ICCCM message for deleting a file.
552       Prefer the operating system to notify when a file is being deleted,
553       but..
554   */
555
556   for( j = 0; j < desktop_data->numWorkspaces; ++j )
557   {
558     workSpace = desktop_data->workspaceData[j];
559     for( k = 0; k < workSpace->files_selected; ++k )
560     {
561       if( workSpace->selectedDTWindows[k] == desktopWindow )
562       {
563         for( l = k; l < workSpace->files_selected; ++l )
564         {
565           workSpace->selectedDTWindows[l] =
566             workSpace->selectedDTWindows[l+1];
567         }
568         --(workSpace->files_selected);
569         break;
570       }
571     }
572   }
573
574   FreeDesktopWindow(desktopWindow);
575 }
576
577
578 /************************************************************************
579  *
580  *  DesktopObjectChanged()
581  *    Called when is detected that an object that a desktop icon
582  *    refers has changed its data type.  Updates the icon pixmap to
583  *    reflect the new type.
584  *
585  ***********************************************************************/
586
587 void
588 DesktopObjectChanged( DesktopRec *desktopWindow )
589 {
590   FileData *file_data;
591   Arg args[1];
592   PixmapData *pixmapData;
593
594   /* remove text widget, if any */
595   if(desktopWindow->text)
596   {
597     XtUnmanageChild(desktopWindow->text);
598     XtDestroyWidget(desktopWindow->text);
599     desktopWindow->text = NULL;
600   }
601
602   /* update icon pixmap */
603   file_data = desktopWindow->file_view_data->file_data;
604   pixmapData = _DtRetrievePixmapData(
605                                      file_data->logical_type,
606                                      file_data->file_name,
607                                      desktopWindow->dir_linked_to,
608                                      desktopWindow->shell,
609                                      desktopIconType);
610
611   if (pixmapData)
612     XtSetArg (args[0], XmNimageName, pixmapData->iconFileName);
613   else
614     XtSetArg(args[0], XmNimageName, NULL);
615   XtSetValues(desktopWindow->iconGadget, args, 1);
616
617   _DtCheckAndFreePixmapData(
618                             file_data->logical_type,
619                             desktopWindow->shell,
620                             (DtIconGadget) desktopWindow->iconGadget,
621                             pixmapData);
622 #ifdef SHAPE
623   GenerateShape(desktopWindow);
624 #endif
625 }
626
627
628 static void
629 MakeDesktopWindow(
630         DesktopRec *desktopWindow,
631         int rX,
632         int rY)
633 {
634    Colormap colormap;
635    Pixel background;
636    Pixel foreground;
637    Pixel top_shadow;
638    Pixel bottom_shadow;
639    Pixel select;
640    Arg args[10];
641    XmString icon_label;
642    XSizeHints wmSizeHints;
643    PixmapData *pixmapData;
644    Dimension  width, height;
645    Dimension  gadgetWidth, gadgetHeight;
646    Position gadgetX, gadgetY, drawAX, drawAY;
647    WMShellWidget wm;
648
649
650    /* get the colors to use for the desktop window */
651    background = desktopWindow->background;
652    XtSetArg (args[0], XmNcolormap,  &colormap);
653    XtGetValues (desktopWindow->shell, args, 1);
654
655    XmGetColors (XtScreen(desktopWindow->shell), colormap, background,
656                 &foreground, &top_shadow, &bottom_shadow, &select);
657
658    /* set the background color for both the frame and the DrawingA */
659 #ifdef SHAPE
660    XtSetArg (args[0], XmNbackground, background);
661 #else
662    XtSetArg (args[0], XmNbackground, select);
663 #endif
664    XtSetValues (desktopWindow->frame, args, 1);
665    XtSetValues (desktopWindow->drawA, args, 1);
666
667    /* set up the icon label and pixmap */
668    if(desktopWindow->file_view_data->file_data->action_name != NULL)
669       icon_label = XmStringCreateLocalized (
670                        desktopWindow->file_view_data->file_data->action_name);
671    else
672       icon_label = XmStringCreateLocalized (desktopWindow->title);
673    XtSetArg (args[0], XmNstring, icon_label);
674
675    pixmapData = _DtRetrievePixmapData(
676                    desktopWindow->file_view_data->file_data->logical_type,
677                    desktopWindow->file_view_data->file_data->file_name,
678                    desktopWindow->dir_linked_to,
679                    desktopWindow->shell,
680                    desktopIconType);
681    if (pixmapData)
682       XtSetArg (args[1], XmNimageName, pixmapData->iconFileName);
683    else
684       XtSetArg (args[1], XmNimageName, NULL);
685
686    /* set up the icon colors */
687
688    XtSetArg (args[2], XmNforeground, foreground);
689
690    if (select == white_pixel)
691    {
692       XtSetArg (args[3], XmNbackground, white_pixel);
693       XtSetArg (args[4], XmNpixmapBackground, white_pixel);
694       XtSetArg (args[5], XmNpixmapForeground, black_pixel);
695    }
696    else if (select == black_pixel)
697    {
698       XtSetArg (args[3], XmNbackground, black_pixel);
699       XtSetArg (args[4], XmNpixmapBackground, white_pixel);
700       XtSetArg (args[5], XmNpixmapForeground, black_pixel);
701    }
702    else
703    {
704 #ifdef SHAPE
705       XtSetArg (args[3], XmNbackground, background);
706 #else
707       XtSetArg (args[3], XmNbackground, select);
708 #endif
709       XtSetArg (args[4], XmNpixmapBackground, top_shadow);
710       XtSetArg (args[5], XmNpixmapForeground, bottom_shadow);
711    }
712    XtSetArg (args[6], XmNuserData,
713              (DirectorySet *)desktopWindow->file_view_data->directory_set);
714
715    XtSetValues (desktopWindow->iconGadget, args, 7);
716
717    XmStringFree(icon_label);
718
719    _DtCheckAndFreePixmapData(
720                        desktopWindow->file_view_data->file_data->logical_type,
721                        desktopWindow->shell,
722                        (DtIconGadget) desktopWindow->iconGadget,
723                        pixmapData);
724
725    /* Set userData, so that help system can obtain the desktop info */
726    XtSetArg(args[0], XmNuserData, (XtPointer)desktopWindow);
727    XtSetValues(desktopWindow->frame, args, 1);
728
729    XtSetMappedWhenManaged(desktopWindow->shell, False);
730    XtRealizeWidget (desktopWindow->shell);
731
732    /* Set the proper workspaces if needed */
733    _DtEncapSetWorkSpaceHints(desktopWindow->shell,
734                              desktopWindow->workspace_name);
735
736    /* Map the window */
737    XtSetMappedWhenManaged(desktopWindow->shell, True);
738
739    /* get the width and the heighth of the icon gadget */
740    XtSetArg (args[0], XmNwidth, &gadgetWidth);
741    XtSetArg (args[1], XmNheight, &gadgetHeight);
742    XtSetArg (args[2], XmNx, &gadgetX);
743    XtSetArg (args[3], XmNy, &gadgetY);
744    XtGetValues(desktopWindow->iconGadget, args, 4);
745
746    XtSetArg (args[0], XmNx, &drawAX);
747    XtSetArg (args[1], XmNy, &drawAY);
748    XtGetValues(desktopWindow->drawA, args, 2);
749
750    width = gadgetWidth + (Dimension)(2*gadgetX) + (Dimension)(2*drawAX);
751    height = gadgetHeight + (Dimension)(2*gadgetY) + (Dimension)(2*drawAY);
752
753    if (rX == -1)
754    {
755       CalculateRootCoordinates(desktopWindow->workspace_num, width, height,
756                                &rX, &rY);
757    }
758
759    desktopWindow->root_x = rX;
760    desktopWindow->root_y = rY;
761
762    XtSetArg (args[0], XmNx, rX);
763    XtSetArg (args[1], XmNy, rY);
764    XtSetArg (args[2], XmNwidth, width);
765    XtSetArg (args[3], XmNheight, height);
766    XtSetValues (desktopWindow->shell, args, 4);
767
768    /* force the Window Manager to map it where I want it */
769    if (XtWindow(desktopWindow->shell) != 0)
770    {
771        XGetNormalHints(XtDisplay(desktopWindow->shell),
772                        XtWindow(desktopWindow->shell), &wmSizeHints);
773        wmSizeHints.flags = USPosition | USSize;
774        XSetNormalHints(XtDisplay(desktopWindow->shell),
775                        XtWindow(desktopWindow->shell), &wmSizeHints);
776        XSync(XtDisplay(desktopWindow->shell), 0);
777    }
778
779    wm = (WMShellWidget)desktopWindow->shell;
780    wm->wm.size_hints.flags = USPosition | USSize;
781
782 #ifdef SHAPE
783    GenerateShape(desktopWindow);
784 #endif
785
786    /* map the Window on the root window */
787    XtPopup(desktopWindow->shell, XtGrabNone);
788    XSync(XtDisplay(desktopWindow->shell), False);
789
790    RegisterIconDropsDT(desktopWindow);
791
792    XtSetArg (args[0], XmNwidth, &width);
793    XtSetArg (args[1], XmNheight, &height);
794    XtGetValues(desktopWindow->shell, args, 2);
795
796    RegisterInGrid((int)width, (int)height, rX, rY,
797                                        desktopWindow->workspace_num, True);
798 }
799
800
801 void
802 SaveDesktopInfo(
803      int session)
804 {
805    static char * desktopFileName = NULL;
806    char * fileName;
807    FILE * fptr;
808    int i;
809    DesktopRec *desktopWindow;
810    char *full_path = NULL;
811    char *rDir, *title, *helpVol;
812    Tt_status tt_status;
813
814    /* Build the name which the desktop data will be saved */
815    if (desktopFileName == NULL)
816    {
817       desktopFileName = XtMalloc(strlen(DESKTOP_SAVE_NAME) + 1);
818       sprintf(desktopFileName, "%s", DESKTOP_SAVE_NAME);
819    }
820
821    switch( session )
822    {
823        case NORMAL_RESTORE:
824            /* Construct full filename */
825            fileName = ResolveLocalPathName(home_host_name,
826                                            desktop_dir, desktopFileName,
827                                            home_host_name, &tt_status);
828            break;
829        case HOME_DIR_RESTORE:
830            full_path = (char *)XtMalloc(strlen(dt_path) + strlen("/home") + 1);
831            sprintf( full_path, "%s/home", dt_path );
832            fileName = ResolveLocalPathName(home_host_name,
833                                            full_path, desktopFileName,
834                                            home_host_name, &tt_status);
835            XtFree(full_path);
836            full_path = NULL;
837            break;
838        default:
839            full_path = (char *)XtMalloc(strlen(dt_path) + strlen("/current")+1);
840            sprintf( full_path, "%s/current", dt_path );
841            fileName = ResolveLocalPathName(home_host_name,
842                                            full_path, desktopFileName,
843                                            home_host_name, &tt_status);
844            XtFree(full_path);
845            full_path = NULL;
846            break;
847    }
848
849    if(desktop_data->numIconsUsed == 0)
850    {
851       unlink(fileName);
852       XtFree(fileName);
853       fileName = NULL;
854       return;
855    }
856
857    /* Assume read-only directory, if we can't open the file */
858    if ((fptr = fopen(fileName, "w+")) == NULL)
859    {
860       XtFree(fileName);
861       fileName = NULL;
862       return;
863    }
864
865    chmod(fileName, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
866    XtFree((char *)fileName);  fileName = NULL;
867
868    fprintf(fptr, "%d\n", desktop_data->numIconsUsed);
869
870    for(i = 0;  i < desktop_data->numIconsUsed; i++)
871    {
872       desktopWindow = desktop_data->desktopWindows[i];
873
874       if(desktopWindow->restricted_directory != NULL )
875          rDir = XtNewString(desktopWindow->restricted_directory);
876       else
877          rDir = XtNewString(NULL_STRING);
878
879       if(desktopWindow->title != NULL )
880          title = XtNewString(desktopWindow->title);
881       else
882          title = XtNewString(NULL_STRING);
883
884       if(desktopWindow->helpVol != NULL )
885          helpVol = XtNewString(desktopWindow->helpVol);
886       else
887          helpVol = XtNewString(NULL_STRING);
888
889       fprintf(fptr, "%s\n%s\n%s\n%s\n%s\n%s\n%d %d %d %d %d %d %d\n",
890               desktopWindow->file_name,
891               desktopWindow->workspace_name,
892               desktopWindow->dir_linked_to,
893               rDir,
894               title,
895               helpVol,
896               desktopWindow->toolbox,
897               desktopWindow->view,
898               desktopWindow->order,
899               desktopWindow->direction,
900               desktopWindow->positionEnabled,
901               desktopWindow->root_x,
902               desktopWindow->root_y);
903
904       /* if not normal restore (ie save current or home) remove the entry */
905       if(session == CURRENT_DIR_RESTORE)
906       {
907          FileViewData *file_view_data;
908          DirectorySet *directory_set;
909
910          file_view_data = desktopWindow->file_view_data;
911          directory_set = (DirectorySet *)file_view_data->directory_set;
912
913          XtRemoveAllCallbacks(desktop_data->desktopWindows[i]->iconGadget,
914                                                             XmNcallback);
915          XtFree((char *)directory_set->file_mgr_data);
916          directory_set->file_mgr_data = NULL;
917          XtFree((char *)directory_set->name);
918          directory_set->name = NULL;
919          XtFree((char *)directory_set);
920          directory_set = NULL;
921          FreeFileData(file_view_data->file_data, True);
922          if(file_view_data->label)
923          {
924            XtFree((char *)file_view_data->label);
925            file_view_data->label = NULL;
926          }
927          XtFree((char *)file_view_data);
928          file_view_data = NULL;
929          XtFree(desktop_data->desktopWindows[i]->workspace_name);
930          desktop_data->desktopWindows[i]->workspace_name = NULL;
931          XtFree(desktop_data->desktopWindows[i]->host);
932          desktop_data->desktopWindows[i]->host = NULL;
933          XtFree(desktop_data->desktopWindows[i]->dir_linked_to);
934          desktop_data->desktopWindows[i]->dir_linked_to = NULL;
935          XtFree(desktop_data->desktopWindows[i]->title);
936          desktop_data->desktopWindows[i]->title = NULL;
937          XtFree(desktop_data->desktopWindows[i]->helpVol);
938          desktop_data->desktopWindows[i]->helpVol = NULL;
939          XtFree(desktop_data->desktopWindows[i]->restricted_directory);
940          desktop_data->desktopWindows[i]->restricted_directory = NULL;
941          desktop_data->desktopWindows[i]->restricted_directory = NULL;
942
943          desktop_data->desktopWindows[i]->root_x = -1;
944          desktop_data->desktopWindows[i]->root_y = -1;
945
946          desktop_data->desktopWindows[i]->view = UNSET_VALUE;
947          desktop_data->desktopWindows[i]->order = UNSET_VALUE;
948          desktop_data->desktopWindows[i]->direction = UNSET_VALUE;
949          desktop_data->desktopWindows[i]->positionEnabled = UNSET_VALUE;
950          desktop_data->desktopWindows[i]->toolbox = False;
951          desktop_data->desktopWindows[i]->title = NULL;
952          desktop_data->desktopWindows[i]->helpVol = NULL;
953          desktop_data->desktopWindows[i]->restricted_directory = NULL;
954
955          desktop_data->desktopWindows[i]->file_view_data = NULL;
956       }
957
958       XtFree(rDir);
959       rDir = NULL;
960       XtFree(title);
961       title = NULL;
962       XtFree(helpVol);
963       helpVol = NULL;
964    }
965
966    fclose(fptr);
967
968    if(session == CURRENT_DIR_RESTORE)
969    {
970       desktop_data->numCachedIcons += desktop_data->numIconsUsed;
971       desktop_data->numIconsUsed = 0;
972       fileName = ResolveLocalPathName(home_host_name,
973                                       desktop_dir, desktopFileName,
974                                       home_host_name, &tt_status);
975       if( TT_OK == tt_status )
976       {
977         unlink(fileName);
978         XtFree(fileName);
979         fileName = NULL;
980       }
981    }
982 }
983
984
985 void
986 LoadDesktopInfo(
987      char *session)
988 {
989    static char * desktopFileName = NULL;
990    char *fileName, *full_path, *ptr;
991    char *workSpace;
992    char *message;
993    int i, j,  numWindows, count, index, bufferSize;
994    int rX, rY;
995    FILE * fptr;
996    DesktopRec *desktopWindow;
997    Boolean status = FALSE;
998    Boolean haveOne;
999    Tt_status tt_status;
1000    struct stat stat_buf;
1001
1002    /* Build the name which the desktop data will be saved */
1003    if (desktopFileName == NULL)
1004    {
1005       desktopFileName = XtMalloc(strlen(DESKTOP_SAVE_NAME) + 1);
1006       sprintf(desktopFileName, "%s", DESKTOP_SAVE_NAME);
1007    }
1008
1009    if(session == NULL)
1010    {
1011       /* Construct full filename */
1012       fileName = ResolveLocalPathName(home_host_name,
1013                                       desktop_dir, desktopFileName,
1014                                       home_host_name, &tt_status);
1015    }
1016    else
1017    {
1018       status = DtSessionRestorePath(toplevel, &full_path, session);
1019
1020       if (!status)
1021          return;
1022
1023       if (stat(full_path, &stat_buf) != 0)
1024       {
1025          XtFree(full_path);
1026          full_path = NULL;
1027          return;
1028       }
1029
1030       ptr = strrchr(full_path, '/');
1031       *ptr = '\0';
1032
1033       /* Construct full filename */
1034       fileName = ResolveLocalPathName(home_host_name,
1035                                       full_path, desktopFileName,
1036                                       home_host_name, &tt_status);
1037
1038       XtFree(full_path);
1039       full_path = NULL;
1040    }
1041
1042    /* Assume no file if the open fails */
1043    if ((fptr = fopen(fileName, "r")) == NULL)
1044    {
1045      /* do nothing */
1046       XtFree(fileName);
1047       fileName = NULL;
1048       return;
1049    }
1050
1051    /* Load the number of entries */
1052    count = fscanf(fptr, "%d\n", &numWindows);
1053
1054    if (count <= 0)
1055    {
1056       XtFree(fileName);
1057       fileName = NULL;
1058       fclose(fptr);
1059       return;
1060    }
1061
1062    /* make sure there are enough predefined desktop windows to hold the
1063       amount restored */
1064    if(numWindows >= desktop_data->numCachedIcons)
1065       InitializeDesktopWindows(numWindows + 5 - desktop_data->numCachedIcons,
1066                                                                          NULL);
1067
1068    count = index = desktop_data->numIconsUsed;
1069
1070    bufferSize = 2*MAX_PATH + 370;
1071    message = (char *)XtMalloc(bufferSize);
1072
1073    /* read the data for each Window, then popup that window */
1074    for (i = count; i < numWindows + count; i++)
1075    {
1076       int len, toolbox, view, order, direction, positionEnabled;
1077
1078       desktopWindow = desktop_data->desktopWindows[index];
1079
1080       fgets(message, bufferSize, fptr);
1081       len = strlen(message); message[len-1] = 0x0;
1082       desktopWindow->file_name = XtNewString(message);
1083
1084       fgets(message, bufferSize, fptr);
1085       len = strlen(message); message[len-1] = 0x0;
1086       workSpace = XtNewString(message);
1087
1088       fgets(message, bufferSize, fptr);
1089       len = strlen(message); message[len-1] = 0x0;
1090       desktopWindow->dir_linked_to = XtNewString(message);
1091
1092       { /* Construct the full path and check for the file or link
1093            existence.
1094            If it's not there on the file system, don't bother
1095            to load it.
1096         */
1097         char * path;
1098         struct stat stat_buf;
1099
1100         if (strcmp(desktopWindow->dir_linked_to, "/") == 0)
1101         {
1102           path = (char *) XtMalloc(strlen(desktopWindow->dir_linked_to) +
1103                                    strlen(desktopWindow->file_name) + 1);
1104           sprintf(path, "%s%s", desktopWindow->dir_linked_to,
1105                   desktopWindow->file_name);
1106         }
1107         else
1108         {
1109           path = (char *) XtMalloc(strlen(desktopWindow->dir_linked_to) +
1110                                    strlen(desktopWindow->file_name) + 2);
1111           sprintf(path, "%s/%s", desktopWindow->dir_linked_to,
1112                   desktopWindow->file_name);
1113         }
1114
1115         if( stat(path, &stat_buf) != 0
1116             && lstat(path, &stat_buf) != 0 )
1117         {
1118           XtFree(desktopWindow->file_name);
1119           desktopWindow->file_name = NULL;
1120           XtFree(workSpace);
1121           workSpace = NULL;
1122           XtFree(desktopWindow->dir_linked_to);
1123           desktopWindow->dir_linked_to = NULL;
1124           XtFree(path);
1125           path = NULL;
1126           continue;
1127         }
1128
1129         XtFree(path);
1130         path = NULL;
1131       }
1132
1133       fgets(message, bufferSize, fptr);
1134       len = strlen(message); message[len-1] = 0x0;
1135       if( strcmp(message, NULL_STRING) == 0 )
1136         desktopWindow->restricted_directory = NULL;
1137       else
1138         desktopWindow->restricted_directory = XtNewString(message);
1139
1140       fgets(message, bufferSize, fptr);
1141       len = strlen(message); message[len-1] = 0x0;
1142       if( strcmp(message, NULL_STRING) == 0 )
1143         desktopWindow->title = NULL;
1144       else
1145         desktopWindow->title = XtNewString(message);
1146
1147       fgets(message, bufferSize, fptr);
1148       len = strlen(message); message[len-1] = 0x0;
1149       if( strcmp(message, NULL_STRING) == 0 )
1150         desktopWindow->helpVol = NULL;
1151       else
1152         desktopWindow->helpVol = XtNewString(message);
1153
1154       fgets(message, bufferSize, fptr);
1155       sscanf( message, "%d %d %d %d %d %d %d\n",
1156               &toolbox, &view, &order, &direction, &positionEnabled, &rX, &rY );
1157
1158       desktopWindow->toolbox = (char)toolbox;
1159       desktopWindow->view = (char)view;
1160       desktopWindow->order = (char)order;
1161       desktopWindow->direction = (char)direction;
1162       desktopWindow->positionEnabled = (Boolean)positionEnabled;
1163
1164       /* set up the workspace number */
1165       haveOne = False;
1166       for(j = 0; j < desktop_data->numWorkspaces; j++)
1167       {
1168          if(strcmp(workSpace, desktop_data->workspaceData[j]->name) == 0)
1169          {
1170              haveOne = True;
1171              desktopWindow->workspace_name = workSpace;
1172              desktopWindow->workspace_num =
1173                                        desktop_data->workspaceData[j]->number;
1174              break;
1175          }
1176       }
1177
1178       if(!haveOne)
1179       {
1180          desktopWindow->workspace_num = 1;
1181          desktopWindow->workspace_name =
1182            (char *)XtMalloc(strlen(desktop_data->workspaceData[0]->name) + 1);
1183          strcpy(desktopWindow->workspace_name,
1184                 desktop_data->workspaceData[0]->name);
1185          XtFree(workSpace);
1186          workSpace = NULL;
1187       }
1188
1189       desktopWindow->host = XtNewString(home_host_name);
1190
1191       desktopWindow->file_view_data =
1192              BuildNewOrderlist(NULL, desktopWindow->iconGadget,
1193                                desktopWindow->host,
1194                                desktopWindow->dir_linked_to,
1195                                desktopWindow->file_name,
1196                                desktopWindow->registered,
1197                                desktopWindow->toolbox);
1198
1199       MakeDesktopWindow(desktopWindow, rX, rY);
1200       desktopWindow->registered = desktopWindow->file_view_data->registered;
1201
1202       desktop_data->numIconsUsed++;
1203       desktop_data->numCachedIcons--;
1204       index++;
1205    }
1206    XtFree(message);
1207    message = NULL;
1208
1209    fclose(fptr);
1210
1211    XtFree(fileName);
1212    fileName = NULL;
1213    SaveDesktopInfo(NORMAL_RESTORE);
1214 }
1215
1216
1217 static void
1218 FreeDesktopWindow(
1219      DesktopRec *desktopWindow)
1220 {
1221    int i;
1222    DesktopRec *tempDesktopWindow;
1223    FileViewData *file_view_data;
1224    DirectorySet *directory_set;
1225    Dimension width, height;
1226    Arg args[2];
1227
1228    file_view_data = desktopWindow->file_view_data;
1229    directory_set = (DirectorySet *)file_view_data->directory_set;
1230    tempDesktopWindow = desktopWindow;
1231
1232    XtSetArg (args[0], XmNwidth, &width);
1233    XtSetArg (args[1], XmNheight, &height);
1234    XtGetValues(desktopWindow->shell, args, 2);
1235
1236    RegisterInGrid((int)width, (int)height, desktopWindow->root_x,
1237                    desktopWindow->root_y, desktopWindow->workspace_num, False);
1238
1239    if(desktopWindow->text != NULL)
1240    {
1241       XtUnmanageChild(desktopWindow->text);
1242       XtDestroyWidget(desktopWindow->text);
1243       desktopWindow->text = NULL;
1244    }
1245
1246    for(i = 0; i < desktop_data->numIconsUsed; i++)
1247         if(desktopWindow == desktop_data->desktopWindows[i])
1248            break;
1249
1250    /* circulate this */
1251    for(;i < desktop_data->numIconsUsed - 1; i++)
1252    {
1253       desktop_data->desktopWindows[i] =
1254                        desktop_data->desktopWindows[i + 1];
1255    }
1256
1257    /* clear all memory used by the desktop window */
1258    desktop_data->desktopWindows[i] = tempDesktopWindow;
1259    XtRemoveAllCallbacks(desktop_data->desktopWindows[i]->iconGadget,
1260                                                             XmNcallback);
1261    XtFree((char *)directory_set->file_mgr_data);
1262    directory_set->file_mgr_data = NULL;
1263    XtFree((char *)directory_set->name);
1264    directory_set->name = NULL;
1265    XtFree((char *)directory_set);
1266    directory_set = NULL;
1267    FreeFileData(file_view_data->file_data, True);
1268    if(file_view_data->label)
1269    {
1270       XtFree((char *)file_view_data->label);
1271       file_view_data->label = NULL;
1272    }
1273    XtFree((char *)file_view_data);
1274    file_view_data = NULL;
1275    XtFree(desktop_data->desktopWindows[i]->restricted_directory);
1276    desktop_data->desktopWindows[i]->restricted_directory = NULL;
1277    XtFree(desktop_data->desktopWindows[i]->title);
1278    desktop_data->desktopWindows[i]->title = NULL;
1279    XtFree(desktop_data->desktopWindows[i]->helpVol);
1280    desktop_data->desktopWindows[i]->helpVol = NULL;
1281    XtFree(desktop_data->desktopWindows[i]->workspace_name);
1282    desktop_data->desktopWindows[i]->workspace_name = NULL;
1283    XtFree(desktop_data->desktopWindows[i]->host);
1284    desktop_data->desktopWindows[i]->host = NULL;
1285    XtFree(desktop_data->desktopWindows[i]->dir_linked_to);
1286    desktop_data->desktopWindows[i]->dir_linked_to = NULL;
1287    XtFree(desktop_data->desktopWindows[i]->file_name);
1288    desktop_data->desktopWindows[i]->file_name = NULL;
1289
1290    desktop_data->desktopWindows[i]->restricted_directory = NULL;
1291    desktop_data->desktopWindows[i]->title = NULL;
1292    desktop_data->desktopWindows[i]->helpVol = NULL;
1293    desktop_data->desktopWindows[i]->workspace_name = NULL;
1294    desktop_data->desktopWindows[i]->host = NULL;
1295    desktop_data->desktopWindows[i]->dir_linked_to = NULL;
1296    desktop_data->desktopWindows[i]->file_name = NULL;
1297
1298    desktop_data->desktopWindows[i]->root_x = -1;
1299    desktop_data->desktopWindows[i]->root_y = -1;
1300
1301    desktop_data->desktopWindows[i]->file_view_data = NULL;
1302    desktop_data->numIconsUsed--;
1303    desktop_data->numCachedIcons++;
1304
1305    /* now lets check the number of cached Icons, if its too large free some
1306     * of the cache.
1307     */
1308
1309    if(desktop_data->numCachedIcons > MAX_CACHED_ICONS)
1310       FreeCachedIcons(desktop_data->numCachedIcons - MAX_CACHED_ICONS);
1311
1312    SaveDesktopInfo(NORMAL_RESTORE);
1313
1314 }
1315
1316
1317 static void
1318 DrawAInput (
1319       Widget w,
1320       XtPointer client_data,
1321       XEvent *event,
1322       Boolean *contDispatch)
1323 {
1324    XmManagerWidget action_pane;
1325    DesktopRec *desktopWindow;
1326    XButtonEvent *bevent;
1327    Arg args[2];
1328    int i, j, num_children, num_of_files;
1329    static int beventx = -1;
1330    static int beventy = -1;
1331
1332    /* if a drag is active, don't do anything. */
1333    if(dragActive)
1334       return;
1335
1336
1337    bevent = (XButtonEvent *)event;
1338    desktop_data->event = *bevent;
1339    desktopWindow = (DesktopRec *) client_data;
1340
1341    /* first decide whether more than one file is selected */
1342    for(i = 0; i < desktop_data->numWorkspaces; i++)
1343    {
1344       if(desktop_data->workspaceData[i]->number == desktopWindow->workspace_num)
1345          break;
1346    }
1347
1348    num_of_files = 0;
1349    for(j = 0; j < desktop_data->workspaceData[i]->files_selected; j++)
1350    {
1351       /* we need to check to see if the dt object this popup is on is
1352          a selected file */
1353       if(desktop_data->workspaceData[i]->selectedDTWindows[j] == desktopWindow)
1354       {
1355          /* it is in the selected list */
1356          num_of_files = desktop_data->workspaceData[i]->files_selected;
1357          break;
1358       }
1359    }
1360
1361    if(num_of_files > 1)
1362    {
1363       /* we have more than one files selected,
1364          Set userData, so that help system can obtain the desktop info */
1365       XtSetArg(args[0], XmNuserData,
1366           (XtPointer)desktop_data->workspaceData[i]->selectedDTWindows);
1367       XtSetValues(desktop_data->popupMenu->popup, args, 1);
1368
1369       XtRemoveAllCallbacks(desktop_data->popupMenu->removeDT,
1370                                                  XmNactivateCallback);
1371       XtAddCallback(desktop_data->popupMenu->removeDT, XmNactivateCallback,
1372               RemoveDT,
1373               (XtPointer) desktop_data->workspaceData[i]->selectedDTWindows[0]);
1374       XtRemoveAllCallbacks(desktop_data->popupMenu->openFolder,
1375                                                       XmNactivateCallback);
1376       XtAddCallback(desktop_data->popupMenu->openFolder, XmNactivateCallback,
1377                                          OpenFolder, (XtPointer) NULL);
1378
1379       XtRemoveAllCallbacks(desktop_data->popupMenu->rename,
1380                                                          XmNactivateCallback);
1381       XtAddCallback(desktop_data->popupMenu->rename, XmNactivateCallback,
1382                                          renameDT, (XtPointer) NULL);
1383
1384       /* unsensitise the "Open Parent Folder" and "Rename" options */
1385       XtSetSensitive(desktop_data->popupMenu->openFolder, False);
1386       XtSetSensitive(desktop_data->popupMenu->rename, False);
1387
1388       /*  Unmanage all action menu buttons. */
1389       action_pane = (XmManagerWidget) desktop_data->popupMenu->popup;
1390
1391       num_children = action_pane->composite.num_children;
1392       for (i = 7; i < num_children; i++)
1393       {
1394         XtUnmanageChild (action_pane->composite.children[i]);
1395       }
1396    }
1397    else
1398    {
1399        /* No point in continuing any further if any of these pointers
1400           is NULL */
1401       if(!desktop_data->popupMenu || !desktopWindow->file_view_data)
1402          return;
1403       /* we have zero or one files selected, so just put up the popup for
1404          the one */
1405
1406       /* Set userData, so that help system can obtain the desktop info */
1407       XtSetArg(args[0], XmNuserData, client_data);
1408       XtSetValues(desktop_data->popupMenu->popup, args, 1);
1409
1410       XtRemoveAllCallbacks(desktop_data->popupMenu->removeDT,
1411                            XmNactivateCallback);
1412       XtAddCallback(desktop_data->popupMenu->removeDT, XmNactivateCallback,
1413                     RemoveDT, (XtPointer) desktopWindow);
1414
1415       XtRemoveAllCallbacks(desktop_data->popupMenu->openFolder,
1416                            XmNactivateCallback);
1417       XtAddCallback(desktop_data->popupMenu->openFolder, XmNactivateCallback,
1418                     OpenFolder, (XtPointer) desktopWindow);
1419
1420       XtRemoveAllCallbacks(desktop_data->popupMenu->rename,
1421                            XmNactivateCallback);
1422
1423       if( desktopWindow->toolbox == False )
1424       {  /* Sensitize rename
1425           */
1426          XtSetSensitive(desktop_data->popupMenu->rename, True);
1427          XtAddCallback(desktop_data->popupMenu->rename, XmNactivateCallback,
1428                        renameDT, (XtPointer) desktopWindow);
1429       }
1430       else
1431       {  /* Don't allow user to rename the objects in the tool box.
1432             These things are action labels.
1433          */
1434          XtSetSensitive(desktop_data->popupMenu->rename, False);
1435
1436       }
1437
1438       XtSetSensitive(desktop_data->popupMenu->openFolder, True);
1439
1440       XtFree(desktop_data->popupMenu->action_pane_file_type);
1441       desktop_data->popupMenu->action_pane_file_type = NULL;
1442       desktop_data->popupMenu->action_pane_file_type = XtNewString(
1443                desktopWindow->file_view_data->file_data->logical_type);
1444
1445       UpdateActionMenuPane ((XtPointer)desktopWindow, (FileMgrRec *)NULL,
1446                             desktop_data->popupMenu->action_pane_file_type,
1447                             DESKTOP, 7, desktop_data->popupMenu->popup,
1448                             desktopWindow->file_view_data->file_data->physical_type);
1449
1450       if(desktopWindow->file_view_data->file_data->physical_type == DtDIRECTORY
1451          && desktopWindow->file_name )
1452       {
1453          char *ptr;
1454
1455          ptr = DtStrrchr(desktopWindow->title, ':');
1456          if(ptr != NULL)
1457          {
1458             ptr++;
1459             if(strcmp(root_title, ptr) == 0)
1460             { /* The desktop object is a ROOT directory */
1461                XtSetSensitive(desktop_data->popupMenu->openFolder, False);
1462                XtSetSensitive(desktop_data->popupMenu->rename, False);
1463                XtRemoveAllCallbacks(desktop_data->popupMenu->rename,
1464                                     XmNactivateCallback);
1465             }
1466          }
1467       }
1468    }
1469
1470    if(event == NULL)
1471    {
1472       Position x, y;
1473       Dimension width, height;
1474       int displayWidth, displayHeight;
1475       DtIconGadget g;
1476
1477       XtSetArg (args[0], XmNwidth, &width);
1478       XtSetArg (args[1], XmNheight, &height);
1479       XtGetValues(XtParent(desktop_data->popupMenu->popup), args, 2);
1480
1481       displayWidth = DisplayWidth(XtDisplay(w), DefaultScreen(XtDisplay(w)));
1482       displayHeight = DisplayHeight(XtDisplay(w), DefaultScreen(XtDisplay(w)));
1483
1484       g = (DtIconGadget)desktopWindow->iconGadget;
1485
1486       if(beventx == -1)
1487          beventx = desktopWindow->root_x + g->icon.pixmap_width/2;
1488
1489       if((Dimension)(beventx + width) > (Dimension)displayWidth)
1490          beventx = displayWidth - width - 4;
1491
1492       if(beventy == -1)
1493          beventy = desktopWindow->root_y +
1494                  desktopWindow->iconGadget->core.height/2;
1495
1496       if((Dimension)(beventy + height) > (Dimension)displayHeight)
1497          beventy = beventy - height - 1;
1498
1499       XtSetArg (args[0], XmNx, beventx);
1500       XtSetArg (args[1], XmNy, beventy);
1501       XtSetValues(XtParent(desktop_data->popupMenu->popup), args, 2);
1502       beventx = -1;
1503       beventy = -1;
1504    }
1505    else
1506    {
1507       beventx = bevent->x_root;
1508       beventy = bevent->y_root;
1509       XmMenuPosition(desktop_data->popupMenu->popup,
1510                                   (XButtonPressedEvent *)bevent);
1511    }
1512
1513    XtManageChild(desktop_data->popupMenu->popup);
1514
1515 }
1516
1517 /**********************************************************************
1518  *
1519  *  RemoveDT - Callback from the Desktop Popup menu to 'Remove From
1520  *      Desktop'.  Popdown's and Free the desktop window passed in
1521  *      in the client_data pointer.  Then checks to see if any other
1522  *      desktop window is pointing to the file in the File Manager the
1523  *      removed desktop object was pointing to.  If there's not, it
1524  *      removes the file from the desktop list.
1525  *
1526  ************************************************************************/
1527
1528 void
1529 RemoveDT (w, client_data, call_data)
1530       Widget w;
1531       XtPointer client_data;
1532       XtPointer call_data;
1533 {
1534    DesktopRec *desktopWindow = (DesktopRec *) client_data;
1535    int i, j, num_of_files;
1536    Boolean selected = False;
1537
1538    /* first decide whether more than one file is selected */
1539    for(i = 0; i < desktop_data->numWorkspaces; i++)
1540    {
1541       if(desktop_data->workspaceData[i]->number == desktopWindow->workspace_num)
1542          break;
1543    }
1544
1545    /* next determine if the file is really in the selected list */
1546    num_of_files = 0;
1547    for(j = 0; j < desktop_data->workspaceData[i]->files_selected; j++)
1548    {
1549       /* we need to check to see if the dt object this popup is on is
1550          a selected file */
1551       if(desktop_data->workspaceData[i]->selectedDTWindows[j] == desktopWindow)
1552       {
1553          /* it is in the selected list */
1554          num_of_files = desktop_data->workspaceData[i]->files_selected;
1555          break;
1556       }
1557    }
1558
1559    if(num_of_files == 0)
1560      num_of_files = 1;
1561    else
1562      selected = True;
1563
1564    for(j = 0; j < num_of_files; j++)
1565    {
1566       if(selected)
1567          desktopWindow = desktop_data->workspaceData[i]->selectedDTWindows[j];
1568
1569       XtPopdown(desktopWindow->shell);
1570       XWithdrawWindow(XtDisplay(desktopWindow->shell),
1571                       XtWindow(desktopWindow->shell),
1572                       XDefaultScreen(XtDisplay(desktopWindow->shell)));
1573
1574       FreeDesktopWindow(desktopWindow);
1575       if(selected)
1576          desktop_data->workspaceData[i]->files_selected--;
1577    }
1578 }
1579
1580 #ifdef SUN_PERF
1581 void
1582 RemoveMovedObjectFromDT (w, client_data, file_cnt, file_list)
1583       Widget w;
1584       XtPointer client_data;
1585       int file_cnt ;
1586       char **file_list ;
1587 {
1588    DesktopRec *desktopWindow = (DesktopRec *) client_data;
1589    int i, j, k, m, num_of_files;
1590    Boolean selected = False;
1591    char filename[MAX_PATH] ;
1592
1593    /* first decide whether more than one file is selected */
1594    for(i = 0; i < desktop_data->numWorkspaces; i++)
1595    {
1596       if(desktop_data->workspaceData[i]->number == desktopWindow->workspace_num)
1597          break;
1598    }
1599
1600    /* next determine if the file is really in the selected list */
1601    num_of_files = 0;
1602    for(j = 0; j < desktop_data->workspaceData[i]->files_selected; j++)
1603    {
1604       /* we need to check to see if the dt object this popup is on is
1605          a selected file */
1606       if(desktop_data->workspaceData[i]->selectedDTWindows[j] == desktopWindow)
1607       {
1608          /* it is in the selected list */
1609          num_of_files = desktop_data->workspaceData[i]->files_selected;
1610          break;
1611       }
1612    }
1613
1614    if(num_of_files == 0)
1615      selected = 1;
1616    else
1617      selected = True;
1618
1619    for(k = 0; k < num_of_files; k++)
1620    {
1621       if(selected)
1622          desktopWindow = desktop_data->workspaceData[i]->selectedDTWindows[k];
1623       for(j = 0; j < file_cnt; j++) {
1624          strcpy(filename, desktopWindow->dir_linked_to) ;
1625          strcat(filename, "/") ;
1626          strcat(filename, desktopWindow->file_name) ;
1627          if (!strcmp(filename, file_list[j])) {
1628              XtPopdown(desktopWindow->shell);
1629              XWithdrawWindow(XtDisplay(desktopWindow->shell),
1630                       XtWindow(desktopWindow->shell),
1631                       XDefaultScreen(XtDisplay(desktopWindow->shell)));
1632
1633              FreeDesktopWindow(desktopWindow);
1634              if(selected) {
1635                 desktop_data->workspaceData[i]->files_selected--;
1636                 for (m = k ; m < num_of_files - 1 ; m++) {
1637                   desktop_data->workspaceData[i]->selectedDTWindows[m] =
1638                     desktop_data->workspaceData[i]->selectedDTWindows[m + 1];
1639                 }
1640              }
1641          }
1642       }
1643    }
1644 }
1645 #endif /* SUN_PERF */
1646
1647 static void
1648 OpenFolder (
1649       Widget w,
1650       XtPointer client_data,
1651       XtPointer call_data)
1652 {
1653    DesktopRec   *desktopWindow;
1654    DirectorySet *directory_data;
1655    FileViewData *file_view_data;
1656    FileMgrData  *file_mgr_data;
1657    FileMgrRec   *file_mgr_rec;
1658    DialogData   *dialog_data;
1659    int j;
1660
1661    desktopWindow = (DesktopRec *) client_data;
1662    file_view_data = desktopWindow->file_view_data;
1663
1664    if (desktopWindow->toolbox)
1665    {
1666       DtActionArg  *action_args;
1667       char *pwd_dir;
1668
1669       action_args = (DtActionArg *) XtCalloc(1, sizeof(DtActionArg));
1670       if (action_args)
1671       {
1672          action_args[0].argClass = DtACTION_FILE;
1673          action_args[0].u.file.name = desktopWindow->dir_linked_to;
1674       }
1675
1676       pwd_dir = XtNewString(desktopWindow->dir_linked_to);
1677       DtActionInvoke(desktopWindow->shell, "OpenParentAppGroup", action_args, 1,
1678                      NULL, NULL, pwd_dir, True, NULL, NULL);
1679       XtFree(pwd_dir);
1680       pwd_dir = NULL;
1681    }
1682    else
1683    {
1684       initiating_view = (XtPointer) NULL;
1685
1686       if(desktopWindow->restricted_directory != NULL)
1687       {
1688          special_view = True;
1689          special_treeType = SINGLE_DIRECTORY;
1690          special_viewType = desktopWindow->view;
1691          special_orderType = desktopWindow->order;
1692          special_directionType = desktopWindow->direction;
1693          special_randomType = desktopWindow->positionEnabled;
1694          special_restricted = XtNewString(desktopWindow->restricted_directory);
1695          if(desktopWindow->title == NULL)
1696             special_title = NULL;
1697          else
1698             special_title = XtNewString(desktopWindow->title);
1699          special_helpVol = XtNewString(desktopWindow->helpVol);
1700          if(desktopWindow->toolbox)
1701             dialog_data = GetNewView(desktopWindow->host,
1702                                      desktopWindow->dir_linked_to,
1703                                      desktopWindow->restricted_directory,
1704                                      NULL, 0);
1705          else
1706             dialog_data = GetNewView(desktopWindow->host,
1707                                      desktopWindow->dir_linked_to,
1708                                      NULL, NULL, 0);
1709       }
1710       else
1711       {
1712          dialog_data = GetNewView(desktopWindow->host,
1713                                   desktopWindow->dir_linked_to,
1714                                   NULL, NULL, 0);
1715       }
1716
1717       if (openDirType == NEW && dialog_data == NULL)
1718          return;
1719
1720       if( dialog_data == NULL )
1721          return ;
1722
1723       file_mgr_data = (FileMgrData *) dialog_data->data;
1724       directory_data = file_mgr_data->directory_set[0];
1725
1726       for (j = 0; j < directory_data->file_count; j++)
1727       {
1728          file_view_data = directory_data->file_view_data[j];
1729
1730          if (file_view_data->filtered != True &&
1731              strcmp(desktopWindow->file_name,
1732              file_view_data->file_data->file_name) == 0)
1733          {
1734             SelectFile (file_mgr_data, file_view_data);
1735             break;
1736          }
1737       }
1738
1739       if(!directory_data->file_count)
1740           file_mgr_data->desktop_file = XtNewString(desktopWindow->file_name);
1741       else
1742           file_mgr_data->desktop_file = NULL;
1743
1744       file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
1745
1746       /* Initially, all menubuttons are sensitive */
1747       file_mgr_rec->menuStates = (RENAME | MOVE | DUPLICATE | LINK | TRASH |
1748                                   MODIFY | CHANGEDIR | PREFERENCES | FILTER |
1749                                   FIND | CREATE_DIR | CREATE_FILE | SETTINGS |
1750                                   CLEAN_UP | MOVE_UP |
1751                                   HOME | CHANGE_DIR | TERMINAL);
1752
1753       if (file_mgr_data->selected_file_count == 0)
1754          ActivateNoSelect(file_mgr_rec);
1755       else if (file_mgr_data->selected_file_count == 1)
1756          ActivateSingleSelect(file_mgr_rec,
1757                     file_mgr_data->selection_list[0]->file_data->logical_type);
1758       else
1759          ActivateMultipleSelect(file_mgr_rec);
1760
1761       PositionFileView(file_view_data, file_mgr_data);
1762    }
1763 }
1764
1765 static void
1766 renameDT (
1767       Widget w,
1768       XtPointer client_data,
1769       XtPointer call_data)
1770 {
1771    DesktopRec   *desktopWindow;
1772    FileViewData *file_view_data;
1773
1774    desktopWindow = (DesktopRec *) client_data;
1775    file_view_data = desktopWindow->file_view_data;
1776
1777    CreateNameChangeDialog(desktopWindow->iconGadget, file_view_data,
1778                           (XtPointer)desktopWindow, DESKTOP);
1779 }
1780
1781 void
1782 SelectDTFile (DesktopRec *desktopWindow)
1783 {
1784    int selection_count;
1785    int i,j;
1786
1787    Display *display;
1788    Window   rootWindow;
1789    Atom     pCurrent;
1790    Screen   *currentScreen;
1791    int      screen;
1792    char     *workspace_name;
1793
1794
1795    /* Get the current workspace */
1796    display = XtDisplay(desktop_data->desktopWindows[0]->shell);
1797    screen = XDefaultScreen(display);
1798    currentScreen = XScreenOfDisplay(display, screen);
1799    rootWindow = RootWindowOfScreen(currentScreen);
1800
1801    if(DtWsmGetCurrentWorkspace(display, rootWindow, &pCurrent) == Success)
1802    {
1803       workspace_name = XGetAtomName (display, pCurrent);
1804       CleanUpWSName(workspace_name);
1805    }
1806    else
1807       workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
1808
1809    for(i = 0; i < desktop_data->numWorkspaces; i++)
1810    {
1811       if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
1812       {
1813               desktop_data->workspaceData[i]->files_selected++;
1814
1815               desktop_data->workspaceData[i]->selectedDTWindows =
1816                   (DesktopRec **)
1817                   XtRealloc ((char *) desktop_data->workspaceData[i]->selectedDTWindows,
1818                      sizeof(DesktopRec *) *(desktop_data->workspaceData[i]->files_selected + 2));
1819
1820               /* Add to the front of the list */
1821               for (j = desktop_data->workspaceData[i]->files_selected; j > 0; j--)
1822               {
1823                   desktop_data->workspaceData[i]->selectedDTWindows[j] = desktop_data->workspaceData[i]->selectedDTWindows[j-1];
1824                                                                                               }
1825               desktop_data->workspaceData[i]->selectedDTWindows[0] = desktopWindow;
1826               break;
1827       }
1828    }
1829    SetToSelectColors (desktopWindow->iconGadget, desktopWindow->frame,
1830                       LINK_FILE);
1831    XSync(display, False);
1832
1833 }
1834
1835 void
1836 DeselectAllDTFiles (
1837       WorkspaceRec *workspaceData)
1838 {
1839    int selection_count;
1840    register int i;
1841
1842    selection_count = workspaceData->files_selected;
1843
1844    for (i = 0; i < selection_count; i++)
1845    {
1846          SetToNormalColors (workspaceData->selectedDTWindows[i]->iconGadget,
1847                             workspaceData->selectedDTWindows[i]->frame,
1848                             workspaceData->selectedDTWindows[i]->frame,
1849                             LINK_FILE);
1850    }
1851
1852    if (workspaceData->selectedDTWindows != NULL)
1853    {
1854       XtFree ((char *) workspaceData->selectedDTWindows);
1855       workspaceData->selectedDTWindows = NULL;
1856    }
1857
1858    workspaceData->selectedDTWindows =
1859       (DesktopRec **) XtMalloc (sizeof (DesktopRec *));
1860    workspaceData->selectedDTWindows[0] = NULL;
1861    workspaceData->files_selected = 0;
1862
1863 }
1864
1865 void
1866 DeselectDTFile (
1867       WorkspaceRec *workspaceData,
1868       DesktopRec *desktopWindow)
1869 {
1870    int selection_count;
1871    register int i;
1872    register int j;
1873
1874
1875    selection_count = workspaceData->files_selected;
1876    workspaceData->files_selected--;
1877
1878    for (i = 0; i < selection_count; i++)
1879       if (workspaceData->selectedDTWindows[i] == desktopWindow)
1880          break;
1881
1882    for (j = i; j < selection_count - 1; j++)
1883       workspaceData->selectedDTWindows[j] =
1884                                       workspaceData->selectedDTWindows[j + 1];
1885
1886    workspaceData->selectedDTWindows = (DesktopRec **)
1887                    XtRealloc ((char *) workspaceData->selectedDTWindows,
1888                                sizeof(DesktopRec *) * selection_count);
1889    workspaceData->selectedDTWindows[selection_count - 1] = NULL;
1890
1891    SetToNormalColors (desktopWindow->iconGadget, desktopWindow->frame,
1892                                         desktopWindow->frame, LINK_FILE);
1893
1894 }
1895
1896 void
1897 DTActionCallback (
1898      Widget w,
1899      XtPointer client_data,
1900      XtPointer call_data)
1901 {
1902    DesktopRec *desktopWindow;
1903    char *command;
1904    Arg args[1];
1905
1906    desktopWindow = (DesktopRec *) client_data;
1907
1908    XtSetArg (args[0], XmNuserData, (XtPointer) &command);
1909    XtGetValues (w, args, 1);
1910
1911    RunDTCommand(command, desktopWindow, NULL);
1912 }
1913
1914
1915 void
1916 RunDTCommand(
1917       char *command,
1918       DesktopRec *desktopWindow,
1919       DtDndDropCallbackStruct *drop_parameters)
1920
1921 {
1922    if ((strcmp(openNewView, command) == 0) ||
1923        (strcmp(openInPlace, command) == 0))
1924    {
1925       char *ltype = desktopWindow->file_view_data->file_data->logical_type;
1926
1927       /* If the folder is locked, don't allow user to go into it */
1928       if( strcmp( ltype, LT_FOLDER_LOCK ) == 0 )
1929       {
1930         char *tmpStr, *title, *msg;
1931
1932         tmpStr = GETMESSAGE(9, 6, "Action Error");
1933         title = XtNewString(tmpStr);
1934         msg = (char *)XtMalloc(
1935                    strlen( GETMESSAGE(30, 1, "Cannot read from %s") )
1936                  + strlen( desktopWindow->file_view_data->file_data->file_name )
1937                  + 1 );
1938         sprintf( msg, GETMESSAGE(30, 1, "Cannot read from %s"),
1939                  desktopWindow->file_view_data->file_data->file_name );
1940         _DtMessage(desktopWindow->shell,
1941                    title, msg, NULL, HelpRequestCB );
1942         XtFree(title);
1943         title = NULL;
1944         XtFree(msg);
1945         msg = NULL;
1946         return;
1947       }
1948
1949       /* this statement applies to the case where a user traverses down the *
1950        * part of the directory tree containing the application manager      *
1951        * directories or the trash directory                                 */
1952       if( (strcmp(ltype, LT_AGROUP) == 0) ||
1953           (strstr(ltype, LT_AGROUP_SUBDIR)) ||
1954           (strcmp(ltype, LT_TRASH) == 0) )
1955       {
1956          ProcessAction(command,
1957                        desktopWindow->file_view_data,
1958                        drop_parameters,
1959                        desktopWindow->host,
1960                        desktopWindow->dir_linked_to,
1961                        desktopWindow->restricted_directory,
1962                        desktopWindow->shell);
1963       }
1964       else
1965       {
1966          ProcessNewViewDT(desktopWindow);
1967       }
1968    }
1969
1970    else if ((strcmp (command, "FILESYSTEM_MOVE") == 0) ||
1971             (strcmp (command, "FILESYSTEM_COPY") == 0) ||
1972             (strcmp (command, "FILESYSTEM_LINK") == 0))
1973    {
1974       if (drop_parameters->dropData->protocol == DtDND_FILENAME_TRANSFER)
1975          ProcessMoveCopyLinkDT(command, desktopWindow, drop_parameters);
1976       else
1977          ProcessBufferDropOnFolderDT(command, desktopWindow, drop_parameters);
1978    }
1979
1980    else
1981    {
1982       ProcessAction(command,
1983                     desktopWindow->file_view_data,
1984                     drop_parameters,
1985                     desktopWindow->host,
1986                     desktopWindow->dir_linked_to,
1987                     desktopWindow->restricted_directory,
1988                     desktopWindow->shell);
1989    }
1990 }
1991
1992
1993 /************************************************************************
1994  *
1995  *  ProcessNewViewDT
1996  *
1997  ************************************************************************/
1998
1999 static void
2000 ProcessNewViewDT (
2001      DesktopRec *desktopWindow)
2002 {
2003    char directory_name[MAX_PATH];
2004
2005    sprintf(directory_name, "%s/%s", desktopWindow->dir_linked_to,
2006                                     desktopWindow->file_name);
2007    DtEliminateDots (directory_name);
2008
2009    initiating_view = (XtPointer) NULL;
2010    if(desktopWindow->restricted_directory == NULL)
2011    {
2012       GetNewView (desktopWindow->host, directory_name, NULL, NULL, 0);
2013    }
2014    else
2015    {
2016       special_view = True;
2017       special_treeType = SINGLE_DIRECTORY;
2018       special_viewType = desktopWindow->view;
2019       special_orderType = desktopWindow->order;
2020       special_directionType = desktopWindow->direction;
2021       special_randomType = desktopWindow->positionEnabled;
2022       special_restricted = XtNewString(desktopWindow->restricted_directory);
2023       if(desktopWindow->title == NULL)
2024          special_title = NULL;
2025       else
2026          special_title = XtNewString(desktopWindow->title);
2027       special_helpVol = XtNewString(desktopWindow->helpVol);
2028       if(desktopWindow->toolbox)
2029          GetNewView (desktopWindow->host, directory_name,
2030                      desktopWindow->restricted_directory, NULL, 0);
2031       else
2032          GetNewView (desktopWindow->host, directory_name, NULL, NULL, 0);
2033    }
2034 }
2035
2036
2037 /************************************************************************
2038  *
2039  *  ProcessMoveCopyLinkDT
2040  *
2041  ************************************************************************/
2042
2043 static void
2044 ProcessMoveCopyLinkDT (
2045      char *command,
2046      DesktopRec *desktopWindow,
2047      DtDndDropCallbackStruct *drop_parameters)
2048 {
2049    unsigned int modifiers = 0;
2050    int numFiles, i;
2051    char ** file_set;
2052    char ** host_set;
2053    FileViewData * file_view_data;
2054    Boolean error = FALSE;
2055
2056      /***************************************************/
2057      /* if no drop_parameters, there is nothing to move */
2058      /***************************************************/
2059    if (!drop_parameters)
2060      return;
2061
2062      /***************************************************/
2063      /* extract file and host sets from drop parameters */
2064      /***************************************************/
2065    numFiles = drop_parameters->dropData->numItems;
2066    _DtSetDroppedFileInfo(drop_parameters, &file_set, &host_set);
2067
2068
2069       /******************************/
2070       /* set movement modifier mask */
2071       /******************************/
2072    if( (initiating_view != NULL) &&
2073        (((FileMgrData *)initiating_view)->toolbox) )
2074    {
2075       /* if initiating_view is a toolbox, the transfer must be */
2076       /* a copy                                                */
2077       modifiers = ControlMask;
2078    }
2079    else
2080    {
2081       if (strcmp(command, "FILESYSTEM_COPY") == 0)
2082          modifiers = ControlMask;
2083       else if (strcmp(command, "FILESYSTEM_LINK") == 0)
2084          modifiers = ShiftMask;
2085       else
2086          modifiers = 0;
2087    }
2088
2089       /*************************************************************/
2090       /* is the desktop object linked to any of the dropped files? */
2091       /*************************************************************/
2092    file_view_data = desktopWindow->file_view_data;
2093    if (file_view_data->file_data->physical_type == DtDIRECTORY)
2094    {
2095       char dir_name[MAX_PATH];
2096
2097       sprintf(dir_name, "%s/%s", desktopWindow->dir_linked_to,
2098               desktopWindow->file_name);
2099       DtEliminateDots(dir_name);
2100
2101       for (i=0; i < numFiles; i++)
2102       {
2103          if (strcmp(dir_name, file_set[i]) == 0 &&
2104              strcmp(desktopWindow->host, host_set[i]) == 0)
2105          {
2106             char *tmpStr, *msg;
2107
2108             error = True;
2109             tmpStr =
2110                GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
2111             msg = XtNewString(tmpStr);
2112             FileOperationError(file_view_data->widget, msg, dir_name);
2113             XtFree(msg);
2114          }
2115       }
2116    }
2117
2118       /**************/
2119       /* Move files */
2120       /**************/
2121    if (!error)
2122       CheckMoveType((FileMgrData *)NULL, file_view_data,
2123                     (DirectorySet *)(file_view_data->directory_set),
2124                     desktopWindow, file_set, host_set, modifiers,
2125                     numFiles, drop_parameters->x, drop_parameters->y, DESKTOP);
2126
2127       /***************************/
2128       /* free file and host sets */
2129       /***************************/
2130    _DtFreeDroppedFileInfo(numFiles, file_set, host_set);
2131 }
2132
2133
2134 /************************************************************************
2135  *
2136  * ProcessBufferDropOnFolderDT
2137  *
2138  ************************************************************************/
2139
2140 static void
2141 ProcessBufferDropOnFolderDT (
2142      char *command,
2143      DesktopRec *desktopWindow,
2144      DtDndDropCallbackStruct *drop_parameters)
2145 {
2146    int num_of_buffers;
2147    char ** file_set = NULL;
2148    char ** host_set = NULL;
2149    BufferInfo *buffer_set = NULL;
2150    char  directory[MAX_PATH];
2151    FileViewData *file_view_data = desktopWindow->file_view_data;
2152
2153
2154    /********************************************/
2155    /* if no drop_parameters, or invalid params */
2156    /* then disallow the drop                   */
2157    /********************************************/
2158    if (!drop_parameters)
2159      return;
2160
2161    /* if dropped on a folder icon and file_view_data */
2162    /* is NULL, disallow the drop                     */
2163    if (file_view_data == NULL)
2164      return;
2165
2166
2167   /***************************************************/
2168   /* extract file and host sets from drop parameters */
2169   /***************************************************/
2170   num_of_buffers = drop_parameters->dropData->numItems;
2171
2172   /* Allocate memory for file and buffer structures */
2173   file_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers );
2174   host_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers);
2175   buffer_set = (BufferInfo * )XtMalloc (sizeof (BufferInfo) * num_of_buffers);
2176
2177   _DtSetDroppedBufferInfo(file_set, buffer_set, host_set, drop_parameters);
2178
2179
2180   /****************/
2181   /* create files */
2182   /****************/
2183   DPRINTF(("ProcessBufferDropOnFolderDT...Buffers dropped on Folder icon %s\n",
2184           file_view_data->file_data->file_name));
2185
2186    sprintf(directory,"%s/%s",
2187            ((DirectorySet *)file_view_data->directory_set)->name,
2188            file_view_data->file_data->file_name);
2189    DtEliminateDots(directory);
2190
2191    DPRINTF (("Copying buffer to %s\n", directory));
2192    MakeFilesFromBuffersDT(file_view_data, directory, file_set, host_set,
2193                           buffer_set, num_of_buffers,
2194                           desktopWindow, NULL, NULL);
2195
2196
2197   /******************************/
2198   /* free file_set + buffer_set */
2199   /******************************/
2200   _DtFreeDroppedBufferInfo (file_set, buffer_set, host_set, num_of_buffers);
2201 }
2202
2203 char *
2204 IsAFileOnDesktop2(
2205         char **file_set,
2206         int  file_count,
2207         int  *number,
2208         Boolean  *IsToolBox)
2209 {
2210    int i,j;
2211    DesktopRec *desktopWindow;
2212    char tmp_filename[MAX_PATH];
2213    Boolean onDesktop = False;
2214    Boolean Link = False;
2215    char *filesOnDesktop;
2216    char *filename1,*filename2;
2217    int newLen, stat_result;
2218    Tt_status tt_status;
2219    static Tt_message dummy_msg = NULL;
2220    struct stat stat_buf;
2221
2222    *IsToolBox = False;
2223
2224    if(dummy_msg == NULL)
2225       dummy_msg = tt_message_create();
2226
2227    *number = 0;
2228    for(i = 0; i < file_count; i++)
2229    {
2230       /* Let's check to see if file coming in is a link, if it is let's
2231        * test it instead of where it is linked to.
2232        */
2233       stat_result = lstat (file_set[i], &stat_buf);
2234       if (stat_result == 0 && (stat_buf.st_mode & S_IFMT) == S_IFLNK)
2235       {
2236          filename1 = XtNewString(file_set[i]);
2237          Link = True;
2238       }
2239       else
2240       {
2241          tt_status = tt_message_file_set(dummy_msg, file_set[i]);
2242          filename1 = tt_message_file(dummy_msg);
2243          Link = False;
2244       }
2245       for(j = 0; j < desktop_data->numIconsUsed; j++)
2246       {
2247         desktopWindow = desktop_data->desktopWindows[j];
2248
2249 /*
2250         if( strcmp( desktopWindow->dir_linked_to, "/" ) != 0 )
2251           sprintf(tmp_filename, "%s/%s", desktopWindow->dir_linked_to,
2252                     desktopWindow->file_view_data->file_data->file_name);
2253         else
2254           sprintf(tmp_filename, "%s%s", desktopWindow->dir_linked_to,
2255                     desktopWindow->file_view_data->file_data->file_name);
2256 */
2257         strcpy( tmp_filename, desktopWindow->dir_linked_to );
2258         if(Link)
2259            filename2 = XtNewString(tmp_filename);
2260         else
2261         {
2262            tt_status = tt_message_file_set (dummy_msg, tmp_filename);
2263            filename2 = tt_message_file(dummy_msg);
2264         }
2265         filename2 = (char *)XtRealloc(filename2, strlen(filename2)
2266                     + strlen(desktopWindow->file_view_data->file_data->file_name)
2267                     + 2 );
2268         strcat(filename2, "/");
2269         strcat(filename2, desktopWindow->file_view_data->file_data->file_name);
2270
2271         if( strcmp( filename1, filename2 ) == 0 )
2272         {
2273           *IsToolBox = desktopWindow->toolbox;
2274           if(onDesktop == False)
2275           {
2276             filesOnDesktop = (char *)XtMalloc(strlen(filename1) + 10);
2277             sprintf( filesOnDesktop, "\n   %s\n", filename1);
2278             onDesktop = True;
2279           }
2280           else
2281           {
2282             newLen = strlen(filesOnDesktop) + strlen(filename1) + 6;
2283             filesOnDesktop = (char *)XtRealloc(filesOnDesktop, newLen);
2284             sprintf(filesOnDesktop, "%s   %s\n", filesOnDesktop, filename1);
2285           }
2286           *number += 1;
2287           break;
2288         }
2289         if(Link)
2290            XtFree(filename2);
2291         else
2292            tt_free(filename2);
2293       }
2294       if(Link)
2295          XtFree(filename1);
2296       else
2297          tt_free(filename1);
2298    }
2299
2300    if(onDesktop)
2301      return(filesOnDesktop);
2302
2303    return(NULL);
2304 }
2305
2306
2307 /*
2308  * This function handles button 1 selection in a desktop icon.
2309  */
2310
2311 void
2312 ProcessDTSelection (
2313    DesktopRec * desktopRec,
2314    XButtonEvent * event)
2315 {
2316     Window   rootWindow;
2317     Atom     pCurrent;
2318     Screen   *currentScreen;
2319     int      screen;
2320     char     *workspace_name;
2321     Boolean  toggle_select = False;
2322     int i, j;
2323
2324     if (event->state & ControlMask)
2325        toggle_select = True;
2326
2327     screen = XDefaultScreen(XtDisplay(desktopRec->shell));
2328     currentScreen = XScreenOfDisplay(XtDisplay(desktopRec->shell), screen);
2329     rootWindow = RootWindowOfScreen(currentScreen);
2330
2331     if(DtWsmGetCurrentWorkspace(XtDisplay(desktopRec->shell), rootWindow,
2332                                                       &pCurrent) == Success)
2333     {
2334        workspace_name = XGetAtomName (XtDisplay(desktopRec->shell), pCurrent);
2335        CleanUpWSName(workspace_name);
2336     }
2337     else
2338        workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
2339
2340     for(i = 0; i < desktop_data->numWorkspaces; i++)
2341     {
2342        if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
2343        {
2344           if(toggle_select == False)
2345              DeselectAllDTFiles(desktop_data->workspaceData[i]);
2346           else
2347           {
2348              for(j = 0;j < desktop_data->workspaceData[i]->files_selected; j++)
2349              {
2350                 if(desktop_data->workspaceData[i]->selectedDTWindows[j] ==
2351                                                                  desktopRec)
2352                 {
2353                    DeselectDTFile(desktop_data->workspaceData[i], desktopRec);
2354                    return;
2355                 }
2356              }
2357           }
2358
2359           desktop_data->workspaceData[i]->files_selected++;
2360
2361           desktop_data->workspaceData[i]->selectedDTWindows =
2362                (DesktopRec **) XtRealloc ((char *)
2363                          desktop_data->workspaceData[i]->selectedDTWindows,
2364                          sizeof(DesktopRec *) *
2365                          (desktop_data->workspaceData[i]->files_selected + 2));
2366
2367           /* Add to the front of the list */
2368           for (j = desktop_data->workspaceData[i]->files_selected; j > 0; j--)
2369           {
2370              desktop_data->workspaceData[i]->selectedDTWindows[j] =
2371                      desktop_data->workspaceData[i]->selectedDTWindows[j-1];
2372           }
2373
2374           desktop_data->workspaceData[i]->selectedDTWindows[0] = desktopRec;
2375           break;
2376        }
2377     }
2378     XtFree(workspace_name);
2379
2380     SetToSelectColors (desktopRec->iconGadget, desktopRec->frame, LINK_FILE);
2381 }
2382
2383
2384 void
2385 UnpostDTTextField ()
2386
2387 {
2388    DesktopRec *desktopWindow;
2389    int i;
2390
2391    for(i = 0; i < desktop_data->numIconsUsed; i++)
2392    {
2393       desktopWindow = desktop_data->desktopWindows[i];
2394       if(desktopWindow->text)
2395       {
2396          XtUnmanageChild(desktopWindow->text);
2397 #ifdef SHAPE
2398          GenerateShape(desktopWindow);
2399 #endif
2400          XtDestroyWidget(desktopWindow->text);
2401          desktopWindow->text = NULL;
2402          return;
2403       }
2404    }
2405 }
2406
2407
2408 Boolean
2409 DTFileIsSelected (
2410    DesktopRec * desktopRec,
2411    FileViewData * fileViewData)
2412 {
2413    Window   rootWindow;
2414    Atom     pCurrent;
2415    Screen   *currentScreen;
2416    int      screen;
2417    char     *workspace_name;
2418    int i, j;
2419
2420    screen = XDefaultScreen(XtDisplay(desktopRec->shell));
2421    currentScreen = XScreenOfDisplay(XtDisplay(desktopRec->shell), screen);
2422    rootWindow = RootWindowOfScreen(currentScreen);
2423
2424    if(DtWsmGetCurrentWorkspace(XtDisplay(desktopRec->shell), rootWindow,
2425                                                       &pCurrent) == Success)
2426    {
2427        workspace_name = XGetAtomName (XtDisplay(desktopRec->shell), pCurrent);
2428        CleanUpWSName(workspace_name);
2429    }
2430    else
2431        workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
2432
2433
2434    for(i = 0; i < desktop_data->numWorkspaces; i++)
2435    {
2436       if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
2437       {
2438          for(j = 0;j < desktop_data->workspaceData[i]->files_selected; j++)
2439          {
2440             if(desktop_data->workspaceData[i]->selectedDTWindows[j] ==
2441                                  desktopRec)
2442             {
2443                XtFree(workspace_name);
2444                return(True);
2445             }
2446          }
2447          XtFree(workspace_name);
2448          return(False);
2449       }
2450    }
2451    XtFree(workspace_name);
2452    return(False);
2453 }
2454
2455 /***********************************************************************
2456  *
2457  *  RegisterPanelInGrid - Registers the Dtwm planel in grid
2458  *
2459  *  Arguments: workspace - workspace number
2460  *             displayWidth - width of worspace screen
2461  *             displayHaight - height of workspace screen
2462  *
2463  ************************************************************************/
2464
2465 void RegisterPanelInGrid(int workspace,  int displayWidth, int displayHeight )
2466 {
2467    /* want to take out space where the FP lays ... Note this only for the
2468       default size of the FP.  Right now there is no dynamic way of registering
2469       the FP no matter what size it is */
2470 #define EXPECTED_PANEL_WIDTH 1105
2471 #define EXPECTED_PANEL_HEIGHT 83
2472    RegisterInGrid(EXPECTED_PANEL_WIDTH, EXPECTED_PANEL_HEIGHT,
2473                  /* the panel is expected to be horizontally centered */
2474                  (displayWidth > EXPECTED_PANEL_WIDTH) ?
2475                   (displayWidth - EXPECTED_PANEL_WIDTH) / 2 : 0,
2476                  /* the panel is expected to be at the bottom of the screen */
2477                  (displayHeight > EXPECTED_PANEL_HEIGHT) ?
2478                    (displayHeight - EXPECTED_PANEL_HEIGHT) : displayHeight,
2479                  workspace, True);
2480 }
2481
2482 /***********************************************************************
2483  *
2484  *  InitializeDesktopGrid
2485  *
2486  ************************************************************************/
2487
2488 void
2489 InitializeDesktopGrid( int displayWidth, int displayHeight)
2490 {
2491    int i,j,k;
2492
2493    desktop_grid_size = desktop_data->numWorkspaces * numColumns * numRows;
2494    desktop_grid = (Boolean *)XtCalloc(1, desktop_grid_size);
2495
2496    for(i = 1; i <= desktop_data->numWorkspaces; i++)
2497    {
2498       RegisterPanelInGrid(i, displayWidth, displayHeight);
2499    }
2500 }
2501
2502 void
2503 RegisterInGrid(
2504        int width,
2505        int height,
2506        int rX,
2507        int rY,
2508        int workspace,
2509        Boolean type)
2510 {
2511    int row, column;
2512    int rowHeight, columnWidth;
2513    int desktop_grid_index;
2514    int i,j;
2515
2516    if(desktopIconType == LARGE)
2517    {
2518       row = rY / PIXELS_PER_ROW_LARGE;
2519       column = rX / PIXELS_PER_COLUMN_LARGE;
2520       rowHeight = (rY + height) / PIXELS_PER_ROW_LARGE;
2521       columnWidth = (rX + width) / PIXELS_PER_COLUMN_LARGE;
2522    }
2523    else
2524    {
2525       row = rY / PIXELS_PER_ROW_SMALL;
2526       column = rX / PIXELS_PER_COLUMN_SMALL;
2527       rowHeight = (rY + height) / PIXELS_PER_ROW_SMALL;
2528       columnWidth = (rX + width) / PIXELS_PER_COLUMN_SMALL;
2529    }
2530
2531    if (columnWidth >= numColumns)
2532    {
2533       columnWidth = numColumns - 1;
2534    }
2535    if (rowHeight >= numRows)
2536    {
2537       rowHeight = numRows - 1;
2538    }
2539
2540    desktop_grid_index = (workspace - 1) * numColumns * numRows;
2541
2542    for (i = (column > 0) ? column : 0; i <= columnWidth ; i++)
2543    {
2544       for (j = (row > 0) ? row : 0; j <= rowHeight ; j++)
2545       {
2546          if (type)
2547          {
2548            /* increase count of objects at given cell */
2549             desktop_grid[ desktop_grid_index + (i * numRows) + j] ++;
2550          }
2551          else
2552          {
2553            /* decrease count of objects at given cell  */
2554            if (desktop_grid[ desktop_grid_index + (i * numRows) + j] > 0)
2555            {
2556               desktop_grid[ desktop_grid_index + (i * numRows) + j] --;
2557            }
2558          }
2559       }
2560    }
2561 }
2562
2563
2564
2565 void
2566 PutOnDTCB (
2567      Widget w,
2568      XtPointer client_data,
2569      XtPointer call_data)
2570 {
2571    Arg args[1];
2572    FileMgrRec *file_mgr_rec;
2573    DialogData  * dialog_data;
2574    FileMgrData * file_mgr_data;
2575    FileViewData * file_view_data;
2576    Widget mbar;
2577    char *directory;
2578    char *file_name;
2579    int i,EndIndex;
2580
2581    XmUpdateDisplay (w);
2582
2583    if(client_data != 0)
2584       mbar = XtParent(w);
2585    else
2586       mbar = XmGetPostedFromWidget(XtParent(w));
2587
2588    XtSetArg(args[0], XmNuserData, &file_mgr_rec);
2589    XtGetValues(mbar, args, 1);
2590
2591    /* Ignore accelerators when we're insensitive */
2592    if(client_data == NULL)
2593       if ((file_mgr_rec->menuStates & PUT_ON_DESKTOP) == 0)
2594          return;
2595
2596    /* Ignore accelerators received after we're unposted */
2597    if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
2598       return;
2599    file_mgr_data = (FileMgrData *) dialog_data->data;
2600
2601    /* get the file_view_data object from which the menu was invoked */
2602    if (client_data == NULL)
2603      file_view_data = NULL;
2604    else
2605    {
2606      file_view_data = file_mgr_data->popup_menu_icon;
2607      if (!file_mgr_data->selected_file_count && file_view_data == NULL)
2608        /* the object has gone away (probably deleted) */
2609        return;
2610
2611      file_mgr_data->popup_menu_icon = NULL; /* Reset it, we don't need it */
2612
2613        /* No need to see the selection_list if file_view_data is NULL */
2614
2615
2616      if(file_view_data)
2617      {
2618        for(i = 0; i < file_mgr_data->selected_file_count; i++)
2619        {
2620           if(file_mgr_data->selection_list[i] == file_view_data)
2621           {
2622              file_view_data = NULL;
2623              break;
2624           }
2625        }
2626      }
2627    }
2628
2629    EndIndex = desktop_data->numIconsUsed;
2630    if(file_view_data == NULL)
2631    {
2632       for (i = 0; i < file_mgr_data->selected_file_count; i++)
2633       {
2634          if (file_mgr_data->toolbox)
2635          {
2636             char *path, *ptr;
2637
2638             path = _DtGetSelectedFilePath(file_mgr_data->selection_list[i]);
2639             path = _DtResolveAppManPath(path,
2640                                         file_mgr_data->restricted_directory);
2641             ptr = strrchr(path, '/');
2642             *ptr = '\0';
2643             directory = path;
2644             file_name = ptr + 1;
2645
2646             SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2647                                 file_name, file_mgr_data->host,
2648                                 directory,
2649                                 -1, -1, NULL,EndIndex);
2650
2651             *ptr = '/';
2652             XtFree(path);
2653             path = NULL;
2654          }
2655          else
2656          {
2657             directory = ((DirectorySet *)
2658                    (file_mgr_data->selection_list[i]->directory_set))->name;
2659             file_name = file_mgr_data->selection_list[i]->file_data->file_name;
2660
2661             SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2662                                 file_name, file_mgr_data->host,
2663                                 directory,
2664                                 -1, -1, NULL,EndIndex);
2665          }
2666       }
2667    }
2668    else
2669    {
2670       if (file_mgr_data->toolbox)
2671       {
2672          char *path, *ptr;
2673
2674          path = _DtGetSelectedFilePath(file_view_data);
2675          path = _DtResolveAppManPath(path, file_mgr_data->restricted_directory);
2676          ptr = strrchr(path, '/');
2677          *ptr = '\0';
2678          directory = path;
2679          file_name = ptr + 1;
2680
2681          SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2682                              file_name, file_mgr_data->host,
2683                              directory,
2684                              -1, -1, NULL,EndIndex);
2685
2686          *ptr = '/';
2687          XtFree(path);
2688          path = NULL;
2689       }
2690       else
2691       {
2692          directory = ((DirectorySet *)(file_view_data->directory_set))->name;
2693          file_name = file_view_data->file_data->file_name;
2694          SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2695                              file_name, file_mgr_data->host,
2696                              file_mgr_data->current_directory, -1, -1, NULL,EndIndex);
2697       }
2698    }
2699 }
2700
2701
2702 static void
2703 CalculateRootCoordinates (
2704      int ws_num,
2705      int width,
2706      int height,
2707      int *root_x,
2708      int *root_y)
2709 {
2710    int      row, column;
2711    Boolean  rDirection, cDirection, whichFirst;
2712    Boolean  error = False;
2713    int      numGridsR, numGridsC, i, j;
2714
2715    if(desktopIconType == LARGE)
2716    {
2717       numGridsC = (width / PIXELS_PER_COLUMN_LARGE) + 1;
2718       numGridsR = (height / PIXELS_PER_ROW_LARGE) + 1;
2719    }
2720    else /* small */
2721    {
2722       numGridsC = (width / PIXELS_PER_COLUMN_SMALL) + 1;
2723       numGridsR = (height / PIXELS_PER_ROW_SMALL) + 1;
2724    }
2725
2726    /*
2727     * set up where to get the first grid spot and which directions to
2728     * search for one until one is found.  For directions True means in the
2729     * positive direction.  If whichFirst is True then row is moved first.
2730     */
2731    switch( desktopPlacement )
2732    {
2733        case (OBJ_PLACE_LEFT_PRIMARY | OBJ_PLACE_TOP_SECONDARY):
2734        case (OBJ_PLACE_TOP_PRIMARY | OBJ_PLACE_LEFT_SECONDARY):
2735            row = 0;
2736            column = 0;
2737            rDirection = True;
2738            cDirection = True;
2739            if(desktopPlacement & OBJ_PLACE_LEFT_PRIMARY)
2740              whichFirst = False;
2741            else
2742              whichFirst = True;
2743            break;
2744
2745        case (OBJ_PLACE_LEFT_PRIMARY | OBJ_PLACE_BOTTOM_SECONDARY):
2746        case (OBJ_PLACE_BOTTOM_PRIMARY | OBJ_PLACE_LEFT_SECONDARY):
2747            row = numRows - numGridsR;
2748            column = 0;
2749            rDirection = False;
2750            cDirection = True;
2751            if(desktopPlacement & OBJ_PLACE_LEFT_PRIMARY)
2752              whichFirst = False;
2753            else
2754              whichFirst = True;
2755            break;
2756
2757        case (OBJ_PLACE_RIGHT_PRIMARY | OBJ_PLACE_TOP_SECONDARY):
2758        case (OBJ_PLACE_TOP_PRIMARY | OBJ_PLACE_RIGHT_SECONDARY):
2759            row = 0;
2760            column = numColumns - numGridsC;
2761            rDirection = True;
2762            cDirection = False;
2763            if(desktopPlacement & OBJ_PLACE_RIGHT_PRIMARY)
2764              whichFirst = False;
2765            else
2766              whichFirst = True;
2767            break;
2768
2769        case (OBJ_PLACE_RIGHT_PRIMARY | OBJ_PLACE_BOTTOM_SECONDARY):
2770        case (OBJ_PLACE_BOTTOM_PRIMARY | OBJ_PLACE_RIGHT_SECONDARY):
2771            row = numRows - numGridsR;
2772            column = numColumns - numGridsC;
2773            rDirection = False;
2774            cDirection = False;
2775            if(desktopPlacement & OBJ_PLACE_RIGHT_PRIMARY)
2776              whichFirst = False;
2777            else
2778              whichFirst = True;
2779            break;
2780    }
2781
2782
2783    /*
2784     * Given the information which is set up above, find the first availible
2785     * spot in the grid where the Desktop Icon can be placed.  NOTE: if the
2786     * Icon turns out to be bigger then the size of the grid, this may have
2787     * to be recalculated.  But we won't know the size until we do a realize
2788     */
2789    ws_num = ((ws_num - 1) * numColumns * numRows);
2790    while(1)
2791    {
2792       if(desktop_grid[ws_num + (column * numRows) + row] == 0)
2793       {
2794          if(numGridsR == 1 && numGridsC == 1)
2795          {
2796             if(desktopIconType == LARGE)
2797             {
2798                *root_x = column * PIXELS_PER_COLUMN_LARGE;
2799                *root_y = row * PIXELS_PER_ROW_LARGE;
2800             }
2801             else
2802             {
2803                *root_x = column * PIXELS_PER_COLUMN_SMALL;
2804                *root_y = row * PIXELS_PER_ROW_SMALL;
2805             }
2806             return;
2807          }
2808
2809          for(i = 0; i < numGridsR; i++)
2810          {
2811             for(j = 0; j < numGridsC; j++)
2812             {
2813                if(desktop_grid[ws_num + ((column + j) * numRows) + (row + i)] > 0)
2814               {
2815                  error = True;
2816                  break;
2817               }
2818             }
2819             if(error)
2820                break;
2821          }
2822          if(!error)
2823          {
2824             if(desktopIconType == LARGE)
2825             {
2826                *root_x = column * PIXELS_PER_COLUMN_LARGE;
2827                *root_y = row * PIXELS_PER_ROW_LARGE;
2828             }
2829             else
2830             {
2831                *root_x = column * PIXELS_PER_COLUMN_SMALL;
2832                *root_y = row * PIXELS_PER_ROW_SMALL;
2833             }
2834             return;
2835          }
2836          else
2837             error = False;
2838       }
2839
2840       /*
2841        * area taken so let get the next grid depending on rDirection,
2842        * cDirection and whchis is first
2843        */
2844       if(whichFirst)
2845       {
2846          if(rDirection)
2847          {
2848             row += 1;
2849             if(row >= numRows)
2850             {
2851                row = 0;
2852                if(cDirection)
2853                {
2854                   column += 1;
2855                   if(column + numGridsC - 1 >= numColumns)
2856                   {
2857                      error = True;
2858                      break;
2859                   }
2860                }
2861                else
2862                {
2863                   column -= 1;
2864                   if(column < 0)
2865                   {
2866                      error = True;
2867                      break;
2868                   }
2869                }
2870             }
2871          }
2872          else
2873          {
2874             row -= 1;
2875             if(row <  0)
2876             {
2877                row = numRows - 1;
2878                if(cDirection)
2879                {
2880                   column += 1;
2881                   if(column + numGridsC - 1 >= numColumns)
2882                   {
2883                      error = True;
2884                      break;
2885                   }
2886                }
2887                else
2888                {
2889                   column -= 1;
2890                   if(column < 0)
2891                   {
2892                      error = True;
2893                      break;
2894                   }
2895                }
2896             }
2897          }
2898       }
2899       else
2900       {
2901          if(cDirection)
2902          {
2903             column += 1;
2904             if(column >= numColumns)
2905             {
2906                column = 0;
2907                if(rDirection)
2908                {
2909                   row += 1;
2910                   if( row + numGridsR - 1 >= numRows)
2911                   {
2912                      error = True;
2913                      break;
2914                   }
2915                }
2916                else
2917                {
2918                   row -= 1;
2919                   if( row < 0)
2920                   {
2921                      error = True;
2922                      break;
2923                   }
2924                }
2925             }
2926          }
2927          else
2928          {
2929             column -= 1;
2930             if(column < 0)
2931             {
2932                column = numColumns - 1;
2933                if(rDirection)
2934                {
2935                   row += 1;
2936                   if( row + numGridsR - 1>= numRows)
2937                   {
2938                      error = True;
2939                      break;
2940                   }
2941                }
2942                else
2943                {
2944                   row -= 1;
2945                   if( row < 0)
2946                   {
2947                      error = True;
2948                      break;
2949                   }
2950                }
2951             }
2952          }
2953       }
2954    }
2955 }
2956
2957
2958 void
2959 SetupDesktopWindow (
2960      Display *display,
2961      FileMgrData *file_mgr_data,
2962      FileMgrRec *file_mgr_rec,
2963      char *file_name,
2964      char *hst_name,
2965      char *dir_name,
2966      int root_x,
2967      int root_y,
2968      char *type,
2969      int EndIndex)
2970 {
2971    char *title;
2972    char title_buf[256];
2973    Boolean restricted_top;
2974    DesktopRec *desktopWindow;
2975    int i, j;
2976    int ws_num;
2977    Window   rootWindow;
2978    Atom     pCurrent;
2979    Screen   *currentScreen;
2980    int      screen;
2981    char   * workspace_name;
2982    char *ptr, * directory_name;
2983    Tt_status tt_status;
2984
2985
2986    DPRINTF(("SetupDesktopWindow: %s\n", file_name));
2987
2988    /*
2989     * Get the host, directory, and file name for the real file
2990     */
2991
2992    /* get the full path and eliminate dots */
2993    directory_name = ResolveLocalPathName(hst_name,
2994                                          dir_name,
2995                                          file_name,
2996                                          home_host_name,
2997                                          &tt_status);
2998    if( TT_OK != tt_status )
2999    { /* Should pop up an error dialog.
3000      */
3001      return;
3002    }
3003
3004    DtEliminateDots(directory_name);
3005
3006    /* check if this is a restricted directory */
3007    restricted_top = file_mgr_data &&
3008                     file_mgr_data->restricted_directory &&
3009                     strcmp(directory_name,
3010                            file_mgr_data->restricted_directory) == 0;
3011
3012    /* separate the rest of the path into directory and file name */
3013    ptr = strrchr(directory_name, '/');
3014    if (*(ptr + 1) != '\0')
3015    {
3016       *ptr++ = '\0';
3017       file_name = ptr;
3018    }
3019    else
3020       file_name = ".";
3021
3022    /*
3023     * Get the window title
3024     */
3025    if (restricted_top && file_mgr_data->title)
3026       title = file_mgr_data->title;
3027    else if (strcmp(file_name, ".") != 0)
3028       title = file_name;
3029    else
3030    {
3031       sprintf(title_buf, "%s:%s", home_host_name, root_title);
3032       title = title_buf;
3033    }
3034
3035
3036    screen = XDefaultScreen(display);
3037    currentScreen = XScreenOfDisplay(display, screen);
3038    rootWindow = RootWindowOfScreen(currentScreen);
3039
3040    /* want to get the current workspace so that the window maps
3041       to the right workspace */
3042    if (DtWsmGetCurrentWorkspace(display, rootWindow, &pCurrent) == Success)
3043    {
3044       workspace_name = XGetAtomName (display, pCurrent);
3045       CleanUpWSName(workspace_name);
3046    }
3047    else
3048       workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
3049
3050    desktop_data->event.type = INVALID_TYPE;
3051
3052    ws_num = -1;
3053    /* determine the workspace number */
3054    for(j = 0; j < desktop_data->numWorkspaces; j++)
3055    {
3056       if(strcmp(workspace_name, desktop_data->workspaceData[j]->name) == 0)
3057       {
3058           ws_num = desktop_data->workspaceData[j]->number;
3059           break;
3060       }
3061    }
3062
3063    /* if the workspace number is still -1, it means there are new
3064       workspaces, so lets go initialize them */
3065    if(ws_num == -1)
3066      ws_num = InitializeNewWorkspaces(display, workspace_name);
3067
3068
3069    /* loop through the current objects on the desktop and see if one
3070       with the same name is already in this workspace.  If it is,
3071       don't map the window and put out a warning message telling
3072       the user this */
3073    for(i = 0; i < EndIndex; i++)
3074    {
3075       if (strcmp(desktop_data->desktopWindows[i]->title, title) == 0 &&
3076           strcmp(desktop_data->desktopWindows[i]->workspace_name,
3077                  workspace_name) == 0)
3078       {
3079          char * msg;
3080          char * tmpStr;
3081
3082          tmpStr = (GETMESSAGE(28,11, "An object named:\n\n   %s\n\nalready exists on the backdrop in this Workspace.\nYou cannot put another object with the same name on the Workspace.\nTo have both objects on the Workspace, rename one of them."));
3083          msg = XtNewString(tmpStr);
3084          FileOperationError(file_mgr_rec->main, msg, title);
3085          XtFree(msg);
3086          msg = NULL;
3087          XtFree(workspace_name);
3088          workspace_name = NULL;
3089          XtFree(directory_name);
3090          directory_name = NULL;
3091          return;
3092       }
3093    }
3094
3095    /* get the next available cached iconWindow and use it to map
3096       this topLevelWindow */
3097    desktopWindow = desktop_data->desktopWindows[desktop_data->numIconsUsed];
3098    desktop_data->numIconsUsed++;
3099    desktop_data->numCachedIcons--;
3100
3101    /* store some of the data needed for the Desktop object */
3102    desktopWindow->host = XtNewString(home_host_name);
3103    if( *directory_name == 0x0 )
3104      desktopWindow->dir_linked_to = XtNewString("/");
3105    else
3106      desktopWindow->dir_linked_to = XtNewString(directory_name);
3107    desktopWindow->file_name = XtNewString(file_name);
3108    desktopWindow->title = XtNewString(title);
3109
3110    desktopWindow->workspace_name = workspace_name;
3111    desktopWindow->workspace_num = ws_num;
3112
3113    if (file_mgr_data != NULL)
3114    {
3115        if (file_mgr_data->restricted_directory == NULL)
3116            desktopWindow->restricted_directory = NULL;
3117        else
3118          desktopWindow->restricted_directory =
3119                 XtNewString(file_mgr_data->restricted_directory);
3120
3121       if (file_mgr_data->helpVol == NULL)
3122          desktopWindow->helpVol = NULL;
3123       else
3124          desktopWindow->helpVol = XtNewString(file_mgr_data->helpVol);
3125
3126       desktopWindow->view = file_mgr_data->view;
3127       desktopWindow->order = file_mgr_data->order;
3128       desktopWindow->direction = file_mgr_data->direction;
3129       desktopWindow->positionEnabled = file_mgr_data->positionEnabled;
3130       desktopWindow->toolbox = file_mgr_data->toolbox;
3131    }
3132    else  /* there is no file_mgr_data associated with this file, so it
3133             must be "Put On Desktop" but not from a File Manager View
3134             (i.e. Find File) */
3135    {
3136        /* store the directory the file is linked to */
3137        /* need to determine the toolbox dir !!!*/
3138        if (type == NULL)
3139          desktopWindow->restricted_directory = NULL;
3140        else
3141          desktopWindow->restricted_directory = XtNewString(type);
3142        desktopWindow->helpVol = NULL;
3143        desktopWindow->toolbox = False;
3144        desktopWindow->view = UNSET_VALUE;
3145        desktopWindow->order = UNSET_VALUE;
3146        desktopWindow->direction = UNSET_VALUE;
3147        desktopWindow->positionEnabled = UNSET_VALUE;
3148    }
3149
3150    desktopWindow->file_view_data = BuildNewOrderlist(
3151                           NULL /* @@@ use cached info if possible! */,
3152                           desktopWindow->iconGadget,
3153                           home_host_name,
3154                           desktopWindow->dir_linked_to,
3155                           file_name,
3156                           desktopWindow->registered,
3157                           desktopWindow->toolbox);
3158
3159    MakeDesktopWindow(desktopWindow, root_x, root_y);
3160    desktopWindow->registered = desktopWindow->file_view_data->registered;
3161
3162    /* go cache some more windows if there isn't enough cached */
3163    if (desktop_data->numCachedIcons < 5)
3164       InitializeDesktopWindows(5, display);
3165
3166    /* go save the current state of the desktop */
3167    SaveDesktopInfo(NORMAL_RESTORE);
3168
3169    XtFree(directory_name);
3170    directory_name = NULL;
3171
3172    if(openDirType == NEW)
3173       ForceMyIconOpen(desktopWindow->host, NULL);
3174
3175    if( checkBrokenLink != 0 && checkBrokenLinkTimerId == 0 )
3176    {
3177      checkBrokenLinkTimerId = XtAppAddTimeOut(
3178                    XtWidgetToApplicationContext( toplevel ),
3179                    checkBrokenLink * 1000,
3180                    TimerEventBrokenLinks,
3181                    NULL );
3182    }
3183
3184 }
3185
3186
3187 static void
3188 FreeCachedIcons (
3189      int iconsToBeFreed)
3190 {
3191    int i, new_size;
3192    DesktopRec *desktop;
3193    DesktopRec *tmpDesktop;
3194
3195    new_size = (desktop_data->numCachedIcons + desktop_data->numIconsUsed) -
3196                                                               iconsToBeFreed;
3197    for(i = desktop_data->numCachedIcons + desktop_data->numIconsUsed;
3198                                                          i > new_size; i--)
3199    {
3200       desktop = desktop_data->desktopWindows[i - 1];
3201       if(desktop == sacredDesktop)
3202       {
3203          desktop = desktop_data->desktopWindows[desktop_data->numIconsUsed];
3204          desktop_data->desktopWindows[desktop_data->numIconsUsed] =
3205                                                                  sacredDesktop;
3206       }
3207       XtDestroyWidget(desktop->shell);
3208       XtFree((char *)desktop);
3209       desktop = NULL;
3210
3211       desktop_data->numCachedIcons--;
3212    }
3213    desktop_data->desktopWindows =
3214                (DesktopRec ** )XtRealloc((char *)desktop_data->desktopWindows,
3215                                             sizeof(DesktopRec *) * new_size);
3216 }
3217
3218 static void
3219 CreatePopupMenu (
3220      Widget drawA )
3221 {
3222    Widget popupBtns[15];
3223    XmString label_string;
3224    char * mnemonic;
3225    Arg args[6];
3226    int n;
3227
3228
3229    /*
3230     * WARNING!!!
3231     *
3232     * IF YOU ADD ANY NEW MENU ITEMS TO THE DESKTOP POPUP MENU, THEN YOU
3233     * MUST ALSO ADD A CHECK FOR IT IN DTHelpRequestCB() [in HelpCB.c],
3234     * SINCE THAT FUNCTION HAS A SPECIAL CHECK FOR EACH MENU BUTTON!
3235     */
3236
3237    n = 0;
3238    XtSetArg(args[n], XmNwhichButton, bMenuButton); n++;
3239    desktop_data->popupMenu->popup =
3240                            XmCreatePopupMenu(drawA, "DTPopup", args, n);
3241
3242    XtAddCallback (desktop_data->popupMenu->popup, XmNmapCallback,
3243                                         popupMenu, (XtPointer) NULL);
3244    XtAddCallback (desktop_data->popupMenu->popup, XmNhelpCallback,
3245                   (XtCallbackProc)DTHelpRequestCB,
3246                   HELP_DESKTOP_POPUP_MENU_STR);
3247
3248    label_string = XmStringCreateLocalized((GETMESSAGE(28,4, "Workspace Object")));
3249    XtSetArg (args[0], XmNlabelString, label_string);
3250    popupBtns[0] = (Widget) XmCreateLabelGadget(desktop_data->popupMenu->popup,
3251                                                           "title", args, 1);
3252    popupBtns[1] = XmCreateSeparatorGadget(desktop_data->popupMenu->popup,
3253                                                            "sep1", NULL, 0);
3254    popupBtns[2] = XmCreateSeparatorGadget(desktop_data->popupMenu->popup,
3255                                                            "sep2", NULL, 0);
3256    XmStringFree (label_string);
3257
3258    label_string = XmStringCreateLocalized((GETMESSAGE(28,5, "Remove From Workspace")));
3259    XtSetArg (args[0], XmNlabelString, label_string);
3260    mnemonic = ((char *)GETMESSAGE(28, 6, "R"));
3261    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
3262    desktop_data->popupMenu->removeDT = popupBtns[3] =
3263            XmCreatePushButtonGadget (desktop_data->popupMenu->popup,
3264                                                              "rmDT", args, 2);
3265    XmStringFree (label_string);
3266    XtAddCallback (desktop_data->popupMenu->removeDT, XmNhelpCallback,
3267                   (XtCallbackProc)DTHelpRequestCB,
3268                   HELP_DESKTOP_POPUP_MENU_STR);
3269
3270
3271    label_string = XmStringCreateLocalized ((GETMESSAGE(28,7, "Open Parent Folder")));
3272    XtSetArg (args[0], XmNlabelString, label_string);
3273    mnemonic = ((char *)GETMESSAGE(28, 8, "O"));
3274    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
3275    desktop_data->popupMenu->openFolder = popupBtns[4] =
3276             XmCreatePushButtonGadget (desktop_data->popupMenu->popup,
3277                                                              "info", args, 2);
3278    XmStringFree (label_string);
3279    XtAddCallback (desktop_data->popupMenu->openFolder, XmNhelpCallback,
3280                   (XtCallbackProc)DTHelpRequestCB,
3281                   HELP_DESKTOP_POPUP_MENU_STR);
3282
3283    label_string = XmStringCreateLocalized ((GETMESSAGE(20,128, "Rename")));
3284    XtSetArg (args[0], XmNlabelString, label_string);
3285    mnemonic = ((char *)GETMESSAGE(20, 129, "n"));
3286    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
3287    desktop_data->popupMenu->rename = popupBtns[5] =
3288             XmCreatePushButtonGadget (desktop_data->popupMenu->popup,
3289                                                             "rename", args, 2);
3290    XmStringFree (label_string);
3291    XtAddCallback (desktop_data->popupMenu->rename, XmNhelpCallback,
3292                   (XtCallbackProc)DTHelpRequestCB,
3293                   HELP_DESKTOP_POPUP_MENU_STR);
3294
3295    popupBtns[6] = XmCreateSeparatorGadget(desktop_data->popupMenu->popup,
3296                                                           "sep1", NULL, 0);
3297
3298    XtManageChildren(popupBtns, 7);
3299 }
3300
3301 static void
3302 popupMenu (
3303      Widget w,
3304      XtPointer client_data,
3305      XtPointer call_data)
3306 {
3307    Widget shell;
3308    Boolean found = False;
3309    int i;
3310    XmAnyCallbackStruct * callback;
3311    XEvent * event;
3312
3313    callback = (XmAnyCallbackStruct *) call_data;
3314    event = (XEvent *) callback->event;
3315
3316    shell = XmGetPostedFromWidget(w);
3317    for(i = 0; i < desktop_data->numIconsUsed; i++)
3318    {
3319       if(desktop_data->desktopWindows[i]->shell == shell ||
3320                       desktop_data->desktopWindows[i]->drawA == shell)
3321       {
3322          found = True;
3323          break;
3324       }
3325    }
3326    if(found)
3327    {
3328       DrawAInput(desktop_data->popupMenu->popup,
3329                  (XtPointer)desktop_data->desktopWindows[i],
3330                  event, (Boolean *)NULL);
3331    }
3332 }
3333
3334
3335 #ifdef SHAPE
3336 void
3337 GenerateShape(
3338       DesktopRec *desktopWindow)
3339 {
3340    Dimension shadowThickness, highlightThickness;
3341    Dimension pixmapWidth, pixmapHeight;
3342    Dimension stringWidth, stringHeight;
3343    XRectangle rect[2];
3344    unsigned char flags;
3345    unsigned char pixmapPosition;
3346    unsigned char alignment;
3347    Arg args[4];
3348    DtIconGadget g;
3349
3350    if(!shapeExtension)
3351       return;
3352
3353    XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
3354    XtSetArg (args[1], XmNhighlightThickness, &highlightThickness);
3355    XtSetArg (args[2], XmNpixmapPosition, &pixmapPosition);
3356    XtSetArg (args[3], XmNalignment, &alignment);
3357    XtGetValues (desktopWindow->iconGadget, args, 4);
3358
3359    g = (DtIconGadget)desktopWindow->iconGadget;
3360    pixmapWidth = g->icon.pixmap_width;
3361    pixmapHeight = g->icon.pixmap_height;
3362    stringWidth = g->icon.string_width;
3363    stringHeight = g->icon.cache->string_height;
3364
3365    _DtIconGetIconRects((DtIconGadget)desktopWindow->iconGadget,
3366                                                 &flags, &rect[0], &rect[1]);
3367
3368    switch ((int) pixmapPosition)
3369    {
3370       case XmPIXMAP_TOP:
3371         if(alignment != XmALIGNMENT_CENTER)
3372         {
3373            /* 1 */
3374             rect[0].x += 1;
3375             rect[0].y += 1;
3376             rect[0].width += 2*shadowThickness;
3377             rect[0].height += 2*shadowThickness;
3378
3379            /* 2 */
3380             rect[1].x += 1;
3381             rect[1].y += 1;
3382             rect[1].width += 2*shadowThickness;
3383             rect[1].height += 2*shadowThickness;
3384
3385             if(rect[0].width > rect[1].width)
3386                rect[1].width = rect[0].width;
3387          }
3388          else /* is XmALIGNMENT_CENTER */
3389          {
3390             if(stringWidth > pixmapWidth)
3391             {
3392               /* 1 */
3393                rect[0].x += 1;
3394                rect[0].y += 1;
3395                rect[0].width += 2*shadowThickness;
3396                rect[0].height += 2*shadowThickness;
3397
3398               /* 2 */
3399                rect[1].x += 1;
3400                rect[1].y += 1;
3401                rect[1].width += 2*shadowThickness;
3402                rect[1].height += 2*shadowThickness;
3403
3404                if(rect[0].width > rect[1].width)
3405                   rect[1].width = rect[0].width;
3406             }
3407             else
3408             {
3409              /* 1 */
3410                rect[0].x += 1;
3411                rect[0].y += 1;
3412                rect[0].width += 2*shadowThickness;
3413                rect[0].height += 2*shadowThickness;
3414
3415               /* 2 */
3416                rect[1].x = rect[0].x;
3417                rect[1].y += 1;
3418                rect[1].width = rect[0].width;
3419                rect[1].height += 2*shadowThickness;
3420             }
3421          }
3422
3423          break;
3424       case XmPIXMAP_LEFT:
3425          if((Dimension)(stringHeight+5) >= pixmapHeight)
3426          {
3427             if(pixmapHeight == 0)
3428             {
3429               /* 1 */
3430                rect[0].x = 0;
3431                rect[0].y = 0;
3432                rect[0].width = 0;
3433                rect[0].height = 0;
3434
3435                rect[1].x += 1;
3436                rect[1].y += 1;
3437                rect[1].width += 2*shadowThickness;
3438                rect[1].height += 2*shadowThickness;
3439             }
3440             else
3441             {
3442               /* 2 */
3443                rect[1].y = rect[0].y + 1;
3444                rect[1].x += 1;
3445                rect[1].width += 2*shadowThickness;
3446                if(pixmapHeight > stringHeight)
3447                   rect[1].height += 2*shadowThickness +
3448                                        (pixmapHeight - stringHeight);
3449                else
3450                   rect[1].height += 2*shadowThickness;
3451
3452               /* 1 */
3453                rect[0].x += 1;
3454                rect[0].y = rect[1].y;
3455                rect[0].width += shadowThickness;
3456                rect[0].height = rect[1].height;
3457             }
3458          }
3459          else
3460          {
3461            /* 1 */
3462             rect[0].x += 1;
3463             rect[0].y += 1;
3464             rect[0].width += 2*shadowThickness;
3465             rect[0].height += 2*shadowThickness;
3466
3467            /* 2 */
3468             rect[1].x += 1;
3469             rect[1].y += 1;
3470             rect[1].width += 2*shadowThickness;
3471             rect[1].height += 2*shadowThickness;
3472          }
3473          break;
3474    }
3475
3476    XShapeCombineRectangles(XtDisplay(desktopWindow->shell),
3477                            XtWindow(desktopWindow->shell),
3478                            ShapeBounding, 0, 0, &rect[0], 2,
3479                            ShapeSet, Unsorted);
3480 }
3481 #endif
3482
3483 static void
3484 BuildDesktopLinks (
3485        Display *display)
3486 {
3487    struct stat statBuf;
3488    Atom     *paWS;
3489    int       numInfo;
3490    Window   rootWindow;
3491    Screen   *currentScreen;
3492    int      i, screen, result;
3493    int      retry;
3494
3495    /* Build the 'Desktop' directory */
3496    desktop_dir = XtMalloc(strlen(users_home_dir) + strlen(DESKTOP_DIR) + 2);
3497    sprintf(desktop_dir, "%s%s", users_home_dir, DESKTOP_DIR);
3498    if (stat(desktop_dir, &statBuf) < 0)
3499       mkdir(desktop_dir, S_IRUSR|S_IWUSR|S_IXUSR);
3500
3501    /* Now build the list of workspaces */
3502    screen = XDefaultScreen(display);
3503    currentScreen = XScreenOfDisplay(display, screen);
3504    rootWindow = RootWindowOfScreen(currentScreen);
3505
3506    retry = retryLoadDesktopInfo;
3507    if (retry <= 0)
3508      retry = 1;
3509
3510    while (retry > 0)
3511    {
3512       result = DtWsmGetWorkspaceList (display, rootWindow, &paWS, &numInfo);
3513       if (result == Success)
3514       {
3515          desktop_data->numWorkspaces = (int)numInfo;
3516          break;
3517       }
3518       else
3519       {
3520          desktop_data->numWorkspaces = 1;
3521          sleep(2);
3522          retry--;
3523       }
3524    }
3525
3526    desktop_data->workspaceData = (WorkspaceRec **)
3527                XtMalloc(sizeof(WorkspaceRec *) * desktop_data->numWorkspaces);
3528    for (i=0; i < desktop_data->numWorkspaces; i++)
3529    {
3530       WorkspaceRec *workspaceData;
3531
3532       workspaceData = (WorkspaceRec *)XtMalloc(sizeof(WorkspaceRec));
3533
3534       if(result == Success)
3535       {
3536          workspaceData->name = XGetAtomName (display, paWS[i]);
3537          CleanUpWSName(workspaceData->name);
3538       }
3539       else
3540          workspaceData->name = XtNewString("One");
3541       workspaceData->number = i + 1;
3542       workspaceData->files_selected = 0;
3543       workspaceData->selectedDTWindows =
3544                          (DesktopRec **) XtMalloc (sizeof (DesktopRec *));
3545       workspaceData->selectedDTWindows[0] = NULL;
3546       workspaceData->primaryHelpDialog = NULL;
3547       workspaceData->secondaryHelpDialogCount = 0;
3548       workspaceData->secondaryHelpDialogList = NULL;
3549
3550       desktop_data->workspaceData[i] = workspaceData;
3551    }
3552
3553    if (result == Success)
3554    {
3555       XFree ((char *) paWS);
3556       paWS = NULL;
3557    }
3558 }
3559
3560 static int
3561 InitializeNewWorkspaces (
3562        Display *display,
3563        char *workspaceName)
3564 {
3565    struct stat statBuf;
3566    Atom     *paWS;
3567    int       numInfo;
3568    Window   rootWindow;
3569    Screen   *currentScreen;
3570    int      i, j, k, screen;
3571    Boolean  haveIt;
3572
3573    /* Now build the directories for each desktop (i.e. workspace) */
3574    screen = XDefaultScreen(display);
3575    currentScreen = XScreenOfDisplay(display, screen);
3576    rootWindow = RootWindowOfScreen(currentScreen);
3577
3578    if (DtWsmGetWorkspaceList (display, rootWindow, &paWS, &numInfo) == Success)
3579    {
3580       if(numInfo <= desktop_data->numWorkspaces)
3581       {
3582          /* should never get here, just put the new object in ws 0 */
3583          return(0);
3584       }
3585
3586       /* go realloc room for the workspace Data */
3587       desktop_data->workspaceData = (WorkspaceRec **) XtRealloc(
3588                                (char *)desktop_data->workspaceData,
3589                                sizeof(WorkspaceRec *) * numInfo);
3590
3591       /* now initialize the new workspaces */
3592       for(i=0; i < numInfo - desktop_data->numWorkspaces; i++)
3593       {
3594          WorkspaceRec *workspaceData;
3595
3596          workspaceData = (WorkspaceRec *)XtMalloc(sizeof(WorkspaceRec));
3597
3598          for(j=0; j < numInfo; j++)
3599          {
3600             workspaceData->name = XGetAtomName (display, paWS[j]);
3601             CleanUpWSName(workspaceData->name);
3602             haveIt = False;
3603             for(k=0; k<desktop_data->numWorkspaces; k++)
3604             {
3605                if(strcmp(workspaceData->name,
3606                             desktop_data->workspaceData[k]->name) == 0)
3607                {
3608                   haveIt = True;
3609                   break;
3610                }
3611             }
3612             if(!haveIt)
3613                break;
3614          }
3615
3616          workspaceData->number = desktop_data->numWorkspaces + i + 1;
3617          workspaceData->files_selected = 0;
3618          workspaceData->selectedDTWindows =
3619                             (DesktopRec **) XtMalloc (sizeof (DesktopRec *));
3620          workspaceData->selectedDTWindows[0] = NULL;
3621          workspaceData->primaryHelpDialog = NULL;
3622          workspaceData->secondaryHelpDialogCount = 0;
3623          workspaceData->secondaryHelpDialogList = NULL;
3624
3625          desktop_data->workspaceData[desktop_data->numWorkspaces + i] =
3626                                                                workspaceData;
3627       }
3628       XFree ((char *) paWS);
3629       paWS = NULL;
3630    }
3631
3632    /* now lets add more desktop grids for the new workspaces */
3633
3634    desktop_grid_size = numInfo * numColumns * numRows;
3635    desktop_grid = (Boolean *)XtRealloc((char *)desktop_grid,desktop_grid_size);
3636    for(i = desktop_data->numWorkspaces; i < numInfo; i++)
3637    {
3638       for(j = 0; j < numColumns; j++)
3639          for(k = 0; k < numRows; k++)
3640             desktop_grid[(i * numRows * numColumns) +
3641                                            (j * numRows) + k] = 0;
3642
3643       RegisterPanelInGrid( i + 1,
3644                            DisplayWidth(display,screen),
3645                            DisplayHeight(display, screen));
3646
3647    }
3648    desktop_data->numWorkspaces = numInfo;
3649
3650    /* now determine which workspace the new object is in */
3651    for(j = 0; j < desktop_data->numWorkspaces; j++)
3652    {
3653       if(strcmp(workspaceName, desktop_data->workspaceData[j]->name) == 0)
3654           return(desktop_data->workspaceData[j]->number);
3655    }
3656
3657    /* should never get here */
3658    return(0);
3659 }
3660
3661 /************************************************************************
3662  *
3663  *  TimerEvent
3664  *      This function is called when dtfile does an _DtActionInvoke. All
3665  *      it does is turn off the Hourglass cursor.
3666  *
3667  ************************************************************************/
3668
3669 static void
3670 TimerEvent(
3671         Widget widget,
3672         XtIntervalId *id )
3673 {
3674   _DtTurnOffHourGlass (widget);
3675 }
3676
3677
3678 /**********************************************************************
3679  *
3680  * CleanUpWSName - routine which makes sure there are no spaces, "/",
3681  *     "'", and ":" in a workspace name. If there are it changes them to
3682  *     "_".
3683  *
3684  *********************************************************************/
3685 void
3686 CleanUpWSName(
3687        char *workspace_name)
3688 {
3689    char *ptr;
3690
3691    /* the workspace name could be something other than "One" "Two" etc.
3692        if the user has change his/her xrdb.  Need to check for characters
3693        in the name which will break us.
3694       First check " "
3695    */
3696    ptr = DtStrchr(workspace_name, ' ');
3697    while(ptr != NULL)
3698    {
3699       *ptr = '_';
3700       ptr = DtStrchr(ptr, ' ');
3701    }
3702
3703    /*
3704      Next check "/"
3705    */
3706    ptr = DtStrchr(workspace_name, '/');
3707    while(ptr != NULL)
3708    {
3709       *ptr = '_';
3710       ptr = DtStrchr(ptr, '/');
3711    }
3712
3713    /*
3714      Next check ":"
3715    */
3716    ptr = DtStrchr(workspace_name, ':');
3717    while(ptr != NULL)
3718    {
3719       *ptr = '_';
3720       ptr = DtStrchr(ptr, ':');
3721    }
3722
3723    /*
3724      Next check "'"
3725    */
3726    ptr = DtStrchr(workspace_name, '\'');
3727    while(ptr != NULL)
3728    {
3729       *ptr = '_';
3730       ptr = DtStrchr(ptr, '\'');
3731    }
3732 }
3733
3734
3735 /**********************************************************************
3736  *
3737  *  CheckDesktoMarquee - given a x, y, width, and height determine
3738  *        whether a desktop objects pixmap falls within the bounded
3739  *        region.  If it does select it. If it is selected and no
3740  *        longer is in the bounded region, deslect it.
3741  *
3742  ***********************************************************************/
3743 void
3744 CheckDesktopMarquee(
3745    int x,
3746    int y,
3747    int width,
3748    int height)
3749 {
3750    int i, j;
3751    Window   rootWindow;
3752    Atom     pCurrent;
3753    Screen   *currentScreen;
3754    int      screen;
3755    char     *workspace_name;
3756    Dimension shadowThickness;
3757    XRectangle pixmapRect;
3758    XRectangle labelRect;
3759    XRectangle incoming_rect;
3760    unsigned char pixmapPosition;
3761    DtIconGadget g;
3762    WorkspaceRec *workspaceData;
3763    unsigned char flags;
3764    Region region;
3765    Display *display;
3766    Boolean match;
3767    Boolean pointInRegion;
3768
3769    if(desktop_data->numIconsUsed <= 0)
3770       return;
3771
3772    /* Create a region with the incoming x, y, width, and height */
3773    incoming_rect.x = (short)x;
3774    incoming_rect.y = (short)y;
3775    incoming_rect.width = (unsigned short)width;
3776    incoming_rect.height = (unsigned short)height;
3777    region = XCreateRegion();
3778    XUnionRectWithRegion (&incoming_rect, region, region);
3779
3780    /* Get the current workspace */
3781    display = XtDisplay(desktop_data->desktopWindows[0]->shell);
3782    screen = XDefaultScreen(display);
3783    currentScreen = XScreenOfDisplay(display, screen);
3784    rootWindow = RootWindowOfScreen(currentScreen);
3785
3786    if(DtWsmGetCurrentWorkspace(display, rootWindow, &pCurrent) == Success)
3787    {
3788       workspace_name = XGetAtomName (display, pCurrent);
3789       CleanUpWSName(workspace_name);
3790    }
3791    else
3792       workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
3793
3794    for(i = 0; i < desktop_data->numWorkspaces; i++)
3795    {
3796       if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
3797       {
3798          workspaceData = desktop_data->workspaceData[i];
3799          break;
3800       }
3801    }
3802
3803    /* now lets loop through the icons used, first check to see if they are
3804     * in the same workspace. If not continue else we need to check to see
3805     * if they are in the region passed in.
3806     */
3807    for(i = 0; i < desktop_data->numIconsUsed; i++)
3808    {
3809       if(strcmp(desktop_data->desktopWindows[i]->workspace_name,
3810                                                   workspace_name) != 0)
3811          continue;
3812
3813       /* first we need to get the pixmap region for the desktop object */
3814       g = (DtIconGadget)desktop_data->desktopWindows[i]->iconGadget;
3815       shadowThickness = g->gadget.shadow_thickness;
3816       pixmapPosition = g->icon.cache->pixmap_position;
3817
3818       _DtIconGetIconRects((DtIconGadget)g, &flags, &pixmapRect, &labelRect);
3819
3820       switch ((int) pixmapPosition)
3821       {
3822          case XmPIXMAP_TOP:  /* 0 */
3823          case XmPIXMAP_LEFT: /* 2 */
3824             if( flags & XmPIXMAP_RECT )
3825             {
3826               pixmapRect.x = pixmapRect.x + desktop_data->desktopWindows[i]->root_x + 1;
3827               pixmapRect.y = pixmapRect.y + desktop_data->desktopWindows[i]->root_y + 1;
3828               pixmapRect.width += 2*shadowThickness;
3829               pixmapRect.height += 2*shadowThickness;
3830
3831               /* now lets check to see if the upper left and lower right corners
3832                * of the pixmap falls within the passed in region
3833                */
3834               pointInRegion = (XPointInRegion(region, pixmapRect.x, pixmapRect.y) &&
3835                                XPointInRegion(region, pixmapRect.x + pixmapRect.width,
3836                                               pixmapRect.y + pixmapRect.height));
3837             }
3838             else if( flags & XmLABEL_RECT )
3839             { /* For the ones that don't have pixmap */
3840               labelRect.x = labelRect.x + desktop_data->desktopWindows[i]->root_x + 1;
3841               labelRect.y = labelRect.y + desktop_data->desktopWindows[i]->root_y + 1;
3842               labelRect.width += 2*shadowThickness;
3843               labelRect.height += 2*shadowThickness;
3844
3845               /* now lets check to see if the upper left and lower right corners
3846                * of the pixmap falls within the passed in region
3847                */
3848               pointInRegion = (XPointInRegion(region, labelRect.x, labelRect.y) &&
3849                                XPointInRegion(region, labelRect.x + labelRect.width,
3850                                               labelRect.y + labelRect.height));
3851             }
3852             else
3853               pointInRegion = False;
3854
3855             if( pointInRegion )
3856             {
3857                /* it falls within the region, lets see if its already
3858                 * selected.
3859                 */
3860                match = False;
3861                for(j = 0; j < workspaceData->files_selected; j++)
3862                {
3863                   if(workspaceData->selectedDTWindows[j] ==
3864                                             desktop_data->desktopWindows[i])
3865                   {
3866                      match = True;
3867                      break;
3868                   }
3869                }
3870
3871                if(match)
3872                   continue;
3873
3874                /* its not already selected, so lets select it ... */
3875                workspaceData->files_selected++;
3876
3877                workspaceData->selectedDTWindows =
3878                      (DesktopRec **) XtRealloc ((char *)
3879                                   workspaceData->selectedDTWindows,
3880                                   sizeof(DesktopRec *) *
3881                                   (workspaceData->files_selected + 2));
3882
3883                /* Add to the front of the list */
3884                for (j = workspaceData->files_selected; j > 0; j--)
3885                {
3886                   workspaceData->selectedDTWindows[j] =
3887                                    workspaceData->selectedDTWindows[j-1];
3888                }
3889
3890                workspaceData->selectedDTWindows[0] =
3891                                        desktop_data->desktopWindows[i];
3892                SetToSelectColors ((Widget)g,
3893                                  desktop_data->desktopWindows[i]->frame,
3894                                  LINK_FILE);
3895                XSync(display, False);
3896             }
3897             else
3898             {
3899                /* its pixmap is not it the region so lets see if it is
3900                 * selected.  If it is lets deslect it.
3901                 */
3902                for(j = 0; j < workspaceData->files_selected; j++)
3903                {
3904                   if(workspaceData->selectedDTWindows[j] ==
3905                                               desktop_data->desktopWindows[i])
3906                   {
3907                      DeselectDTFile (workspaceData,
3908                                           desktop_data->desktopWindows[i]);
3909                      XSync(display, False);
3910                      break;
3911                   }
3912                }
3913             }
3914             break;
3915       }
3916    }
3917    XDestroyRegion (region);
3918    XtFree(workspace_name);
3919 }
3920
3921
3922 static void
3923 ProcessDropOnDesktopObject (
3924      Widget w,
3925      DtDndDropCallbackStruct *dropInfo,
3926      DesktopRec *desktopWindow)
3927 {
3928    char *command = NULL;
3929
3930    /******************/
3931    /* transfer phase */
3932    /******************/
3933    if (dropInfo->reason != DtCR_DND_DROP_ANIMATE)
3934    {
3935       DPRINTF(("DropOnObject: Transfer Callback\n"));
3936
3937       /* In case when the drag is from non File Manager client */
3938       if(!dragActive)
3939         initiating_view = NULL;
3940
3941       /* check for invalid trash drop */
3942       if (FileFromTrash(dropInfo->dropData->data.files[0]))
3943       {
3944          if (InvalidTrashDragDrop(dropInfo->operation,
3945                FROM_TRASH,
3946                desktopWindow->shell))
3947          {
3948             dropInfo->status = DtDND_FAILURE;
3949             return;
3950          }
3951       }
3952
3953       command = TypeToAction(dropInfo->operation,
3954                              desktopWindow->file_view_data->file_data->logical_type);
3955       if(command &&
3956          (strncmp("FILESYSTEM_", command, strlen("FILESYSTEM_")) != 0) &&
3957          dropInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
3958           dropInfo->completeMove = True;
3959       else
3960           /* set the complete move flag to False since we will be handling */
3961           /* the deletion of the original file                             */
3962           dropInfo->completeMove = False;
3963    }
3964
3965    /******************************************/
3966    /* animate phase, retrieve action and run */
3967    /******************************************/
3968    else
3969    {
3970       command =
3971         TypeToAction(dropInfo->operation,
3972                      desktopWindow->file_view_data->file_data->logical_type);
3973       if (command)
3974       {
3975          RunDTCommand (command,
3976                        desktopWindow,
3977                        dropInfo);
3978          DtDtsFreeAttributeValue(command);
3979       }
3980    }
3981 }
3982
3983
3984 static void
3985 DropOnDesktopObject (
3986      Widget w,
3987      XtPointer client_data,
3988      XtPointer call_data)
3989 {
3990    DtDndDropCallbackStruct *dropInfo = (DtDndDropCallbackStruct *)call_data;
3991
3992    switch (dropInfo -> dropData->protocol)
3993      {
3994        case DtDND_FILENAME_TRANSFER:
3995        case DtDND_BUFFER_TRANSFER:
3996          ProcessDropOnDesktopObject (w, dropInfo, (DesktopRec *) client_data);
3997          break;
3998        default :
3999          dropInfo->status = DtDND_FAILURE;
4000      } /* endswitch */
4001 }
4002
4003 void
4004 WorkSpaceRemoved (
4005      Widget w,
4006      Atom deleted_ws_atom,
4007      int type,
4008      XtPointer client_data)
4009 {
4010   Display  *display;
4011   Window   rootWindow;
4012   Atom     pCurrent;
4013   Screen   *currentScreen;
4014   int      screen;
4015   char     *workspace_name,*old_workspace_name;
4016   Atom     *paWS;
4017   int      numInfo,oldNumWorkspaces,old_ws_num,ws_num;
4018   int      i,j,k,retry,result,old_index,new_index;
4019
4020   display = XtDisplay(w);
4021   screen = XDefaultScreen(display);
4022   currentScreen = XScreenOfDisplay(display, screen);
4023   rootWindow = RootWindowOfScreen(currentScreen);
4024   oldNumWorkspaces = desktop_data->numWorkspaces;
4025
4026   old_workspace_name = XGetAtomName (display, deleted_ws_atom);
4027
4028   if( type == DtWSM_MODIFY_WORKSPACE_TYPE_DELETE )
4029   {
4030     retry = retryLoadDesktopInfo;
4031     if (retry <= 0)
4032       retry = 1;
4033     /* Get total new number of workspaces */
4034     while (retry > 0)
4035     {
4036        result = DtWsmGetWorkspaceList (display, rootWindow, &paWS, &numInfo);
4037        if (result == Success)
4038        {
4039           desktop_data->numWorkspaces = (int)numInfo;
4040           break;
4041        }
4042        else
4043        {
4044           desktop_data->numWorkspaces = 1;
4045           sleep(2);
4046           retry--;
4047        }
4048     }
4049     /* Get the current workspace */
4050     if(DtWsmGetCurrentWorkspace(display,rootWindow,&pCurrent) == Success)
4051     {
4052        workspace_name = XGetAtomName (display, pCurrent);
4053        CleanUpWSName(workspace_name);
4054     }
4055     else
4056        workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
4057
4058     /* determine the workspaces number of deleted and current*/
4059     old_ws_num = GetWorkspaceNum(old_workspace_name,oldNumWorkspaces,&old_index);
4060     ws_num = GetWorkspaceNum(workspace_name,oldNumWorkspaces,&new_index);
4061
4062     /* Free up or reassign any workspace data in the deleted workspace */
4063     FreeUpOldWorkspace(oldNumWorkspaces,old_ws_num,ws_num,old_index,new_index);
4064
4065     /* Look up for the duplication of workspace objects in the new workspace */
4066     for(i=0;i<desktop_data->numIconsUsed;i++)
4067     {    /* Those objects whose workspace number matches the deleted workspace number */
4068        if (desktop_data->desktopWindows[i]->workspace_num == old_ws_num)
4069        {  /* Look up in all of the workspace objects */
4070          for(j=0;j<desktop_data->numIconsUsed;j++)
4071          {  /* Those objects in the current workspace */
4072            if (j!= i && desktop_data->desktopWindows[j]->workspace_num == ws_num)
4073            {
4074              /* If there is an object matching the old workspace object delete the old */
4075              if(strcmp(desktop_data->desktopWindows[j]->file_name,desktop_data
4076                ->desktopWindows[i]->file_name) == 0)
4077              {
4078                ws_num = GetWorkspaceNum(workspace_name,desktop_data->
4079                              numWorkspaces, &new_index);
4080                for(k=0;
4081                  k<desktop_data->workspaceData[new_index]->files_selected;k++)
4082                {
4083                 /* Adjust the selectedDTWindows of current to accommadate the old list */
4084                   if(desktop_data->workspaceData[new_index]->
4085                        selectedDTWindows[k] == desktop_data->desktopWindows[i])
4086                   {
4087                     desktop_data->workspaceData[new_index]->
4088                                         selectedDTWindows[k] = NULL;
4089                     for(;k<desktop_data->workspaceData[new_index]->files_selected;k++)
4090                       desktop_data->workspaceData[new_index]->
4091                        selectedDTWindows[k] = desktop_data->
4092                           workspaceData[new_index]-> selectedDTWindows[k+1];
4093                       desktop_data->workspaceData[new_index]->files_selected--;
4094                     break;
4095                   }
4096                }
4097                XtPopdown(desktop_data->desktopWindows[i]->shell);
4098                XWithdrawWindow(XtDisplay(desktop_data->desktopWindows[i]->shell),
4099                       XtWindow(desktop_data->desktopWindows[i]->shell),
4100                       XDefaultScreen(XtDisplay(desktop_data->desktopWindows[i]->shell)));
4101                FreeDesktopWindow(desktop_data->desktopWindows[i]);
4102                i--;  /* To make sure that other icons are also covered */
4103                break;
4104              }
4105            }
4106          }
4107          if(j == desktop_data->numIconsUsed)
4108          {
4109            desktop_data->desktopWindows[i]->workspace_num  = ws_num;
4110            XtFree(desktop_data->desktopWindows[i]->workspace_name);
4111            desktop_data->desktopWindows[i]->workspace_name = NULL;
4112            desktop_data->desktopWindows[i]->workspace_name =
4113                                       XtNewString(workspace_name);
4114          }
4115        }
4116     }
4117   }
4118   else if( type == DtWSM_MODIFY_WORKSPACE_TYPE_ADD )
4119   {
4120      InitializeNewWorkspaces(display, old_workspace_name);
4121   }
4122   XFree(old_workspace_name);
4123 }
4124
4125 static int
4126 GetWorkspaceNum(char *workspace_name,
4127                 int NumWorkspaces,
4128                 int  *workspace_index)
4129 {
4130   int j;
4131   int ws_num = -1;
4132   for(j = 0; j < NumWorkspaces; j++)
4133   {
4134     if(strcmp(workspace_name, desktop_data->workspaceData[j]->name) == 0)
4135     {
4136         ws_num = desktop_data->workspaceData[j]->number;
4137         break;
4138     }
4139   }
4140   *workspace_index = (j == NumWorkspaces)?-1:j;
4141   return ws_num;
4142 }
4143 static void
4144 FreeUpOldWorkspace(
4145    int oldNumWorkspaces,
4146    int old_ws_num,
4147    int ws_num,
4148    int  old_index,
4149    int  new_index)
4150 {
4151    int j,numnewfiles,numoldfiles;
4152
4153    if(old_ws_num==-1 || old_index==-1 ||
4154       desktop_data->workspaceData[old_index]==NULL) /* Something  is wrong */
4155      return;
4156    numnewfiles = desktop_data->workspaceData[new_index]->files_selected;
4157    numoldfiles = desktop_data->workspaceData[old_index]->files_selected;
4158    if(numoldfiles)
4159    {
4160      desktop_data->workspaceData[new_index]->selectedDTWindows=(DesktopRec **)
4161       XtRealloc((XtPointer) desktop_data->workspaceData[new_index]->selectedDTWindows,
4162           sizeof(DesktopRec *) * ( numnewfiles+numoldfiles));
4163      for(j=numnewfiles;j< numnewfiles+numoldfiles;j++)
4164      {
4165        desktop_data->workspaceData[new_index]->selectedDTWindows[j] =
4166       desktop_data->workspaceData[old_index]->selectedDTWindows[j-numnewfiles];
4167      }
4168      XtFree((XtPointer) desktop_data->workspaceData[old_index]->selectedDTWindows);
4169       desktop_data->workspaceData[old_index]->selectedDTWindows = NULL;
4170      desktop_data->workspaceData[new_index]->files_selected = numnewfiles+numoldfiles;
4171    }
4172
4173    numnewfiles=desktop_data->workspaceData[new_index]->secondaryHelpDialogCount;
4174    numoldfiles=desktop_data->workspaceData[old_index]->secondaryHelpDialogCount;
4175    if(numoldfiles)
4176    {
4177      desktop_data->workspaceData[new_index]->secondaryHelpDialogList=
4178       (DialogData **) XtRealloc((XtPointer) desktop_data->workspaceData[old_index]->
4179     secondaryHelpDialogList,sizeof(DialogData *) * ( numnewfiles+numoldfiles));
4180      for(j=numnewfiles;j< numnewfiles+numoldfiles;j++)
4181      {
4182       desktop_data->workspaceData[new_index]->secondaryHelpDialogList[j] =
4183       desktop_data->workspaceData[old_index]->secondaryHelpDialogList[j-ws_num];
4184      }
4185      desktop_data->workspaceData[new_index]->secondaryHelpDialogCount = numnewfiles+numoldfiles;
4186    }
4187    /* Move up the workspaceData */
4188    XtFree((XtPointer) desktop_data->workspaceData[old_index]);
4189     desktop_data->workspaceData[old_index] = NULL;
4190    for(j=old_index; j<desktop_data->numWorkspaces;j++)
4191       desktop_data->workspaceData[j] = desktop_data->workspaceData[j+1];
4192    desktop_data->workspaceData[j] = NULL;
4193 }
4194 /************************************************************************
4195  *
4196  ************************************************************************/
4197
4198 void
4199 PutOnWorkspaceHandler(
4200    Tt_message ttMsg)
4201 {
4202   DesktopRec * desktopWindow;
4203   struct stat fileInfo;
4204   char title[256], invalidWorkspace = 0x0;
4205   int numArgs, i, screen, ws;
4206   char * fullName, * fileName = NULL, * dirName = NULL, * workspace = NULL;
4207   char * requestWorkspace = NULL;
4208
4209   fullName = tt_message_file( ttMsg );
4210
4211   if( tt_is_err( tt_ptr_error( fullName ) ) )
4212   { /* No file name */
4213     tt_message_reply( ttMsg );
4214     tttk_message_destroy( ttMsg );
4215     return;
4216   }
4217
4218   if (NULL != fullName) DtEliminateDots( fullName );
4219
4220   if(NULL==fullName ||
4221      (stat(fullName, &fileInfo) != 0 && lstat(fullName, &fileInfo) != 0))
4222   {
4223     char *template, *errorMsg, *dialogTitle, *errorName;
4224
4225     /* File does not exist */
4226     tt_message_reply(ttMsg);
4227     tttk_message_destroy(ttMsg);
4228
4229     dialogTitle = XtNewString(GETMESSAGE(20, 84, "Put in Workspace"));
4230
4231     template = XtNewString(
4232                 GETMESSAGE(
4233                   28, 13,
4234                   "Object:\n\n   %s\n\ndoes not exist in the file system."));
4235     if (NULL == fullName)
4236       errorName = "";
4237     else
4238       errorName = fullName;
4239     errorMsg = (char *) XtMalloc(strlen(template) + strlen(errorName) + 1);
4240     sprintf(errorMsg, template, errorName);
4241     _DtMessage(toplevel, dialogTitle, errorMsg, NULL, HelpRequestCB);
4242
4243     XtFree(template);
4244     XtFree(errorMsg);
4245     if (NULL != fullName) tt_free(fullName);
4246     return;
4247   }
4248
4249   numArgs = tt_message_args_count( ttMsg );
4250   if( tt_is_err( tt_int_error( numArgs ) ) )
4251     numArgs = 0;
4252
4253   if( numArgs == 0 )
4254   { /* No argument */
4255     tt_message_reply( ttMsg );
4256     tttk_message_destroy( ttMsg );
4257     return;
4258   }
4259
4260   for( i = 0; i < numArgs; ++i )
4261   {
4262     char * vtype;
4263
4264     vtype = tt_message_arg_type( ttMsg, i );
4265
4266     if( (vtype == 0)
4267         || (tt_is_err( tt_ptr_error( vtype ))) )
4268       continue;
4269
4270     if( strcmp( vtype, "-workspace" ) == 0 )
4271     {
4272       requestWorkspace = tt_message_arg_val( ttMsg, i );
4273     }
4274     tt_free( vtype );
4275   }
4276
4277   /* separate the rest of the path into directory and file name */
4278   if( strcmp( fullName, "/" ) == 0 )
4279   {
4280     sprintf( title, "%s:%s", home_host_name, root_title );
4281     fileName = XtNewString( "." );
4282     dirName = XtNewString( "/" );
4283   }
4284   else
4285   {
4286     char * ptr;
4287     ptr = strrchr( fullName, '/' );
4288     if( ptr == fullName )
4289     {
4290       strcpy( title, ptr + 1 );
4291       dirName = XtNewString( "/" );
4292       fileName = XtNewString( ptr + 1 );
4293     }
4294     else if( *(ptr + 1) != '\0' )
4295     {
4296       char savedChar = *ptr;
4297       *ptr = '\0';
4298       dirName = XtNewString( fullName );
4299       *ptr = savedChar;
4300       strcpy( title, ptr + 1 );
4301       fileName = XtNewString( ptr + 1 );
4302     }
4303     else
4304     {
4305       tt_message_reply( ttMsg );
4306       tttk_message_destroy( ttMsg );
4307
4308       tt_free( fullName );
4309       return;
4310     }
4311   }
4312
4313   tt_free( fullName );
4314   workspace = XtNewString( requestWorkspace );
4315   tt_free( requestWorkspace );
4316
4317   if( strcmp( workspace, "current" ) == 0 )
4318   {
4319     Display  * display;
4320     Window   rootWindow;
4321     Atom     pCurrent;
4322     Screen   * currentScreen;
4323     int      screen;
4324
4325     XtFree( workspace );
4326
4327     /* Get the current workspace */
4328     display = XtDisplay( toplevel );
4329     screen = XDefaultScreen( display );
4330     currentScreen = XScreenOfDisplay( display, screen );
4331     rootWindow = RootWindowOfScreen( currentScreen );
4332
4333     if( DtWsmGetCurrentWorkspace( display, rootWindow, &pCurrent ) == Success )
4334       workspace = XGetAtomName( display, pCurrent );
4335     else
4336       workspace = XtNewString( desktop_data->workspaceData[0]->name );
4337   }
4338
4339   ws = -1;
4340   /* determine the workspace number
4341   */
4342   for( i = 0; i < desktop_data->numWorkspaces; ++i )
4343   {
4344     if( strcmp( workspace, desktop_data->workspaceData[i]->name ) == 0 )
4345     {
4346       ws = desktop_data->workspaceData[i]->number - 1;
4347       break;
4348     }
4349   }
4350
4351   if( ws == -1 )
4352   { /* Invalid workspace
4353        choose workspace one
4354     */
4355     ws = 0;
4356     XtFree( workspace );
4357     workspace = XtNewString( "ws0" );
4358     invalidWorkspace = 0x1;
4359   }
4360
4361   for( i = 0; i < desktop_data->numIconsUsed; ++i )
4362   {
4363     if( strcmp( desktop_data->desktopWindows[i]->title, title ) == 0
4364         && strcmp( desktop_data->desktopWindows[i]->workspace_name,
4365                    workspace ) == 0 )
4366     {
4367       char * template, * errorMsg, * dialogTitle;
4368
4369       dialogTitle = XtNewString(GETMESSAGE(20,84,"Put in Workspace"));
4370       if( invalidWorkspace )
4371         template = XtNewString( GETMESSAGE(28,12, "An invalid workspace was passed. The default workspace will be\nworkspace one and an object named:\n\n   %s\n\nalready exists on the backdrop in this Workspace.\nYou cannot put another object with the same name on the Workspace.\nTo have both objects on the Workspace, rename one of them."));
4372       else
4373         template = XtNewString( GETMESSAGE(28,11, "An object named:\n\n   %s\n\nalready exists on the backdrop in this Workspace.\nYou cannot put another object with the same name on the Workspace.\nTo have both objects on the Workspace, rename one of them."));
4374       errorMsg = (char *) XtMalloc( strlen( template )
4375                                     + strlen( title ) + 1 );
4376       sprintf( errorMsg, template, title );
4377       _DtMessage( toplevel, dialogTitle, errorMsg, NULL, HelpRequestCB );
4378
4379       XtFree( errorMsg );
4380       XtFree( workspace );
4381       XtFree( dirName );
4382       XtFree( fileName );
4383       XtFree( dialogTitle );
4384       XtFree( template );
4385
4386       tt_message_reply( ttMsg );
4387       tttk_message_destroy( ttMsg );
4388
4389       return;
4390     }
4391   }
4392
4393   /* get the next available cached iconWindow and use it to map
4394      this topLevelWindow */
4395   desktopWindow = desktop_data->desktopWindows[desktop_data->numIconsUsed];
4396   desktop_data->numIconsUsed++;
4397   desktop_data->numCachedIcons--;
4398
4399   /* store some of the data needed for the Desktop object */
4400   desktopWindow->host = XtNewString( home_host_name );
4401   desktopWindow->dir_linked_to = dirName;
4402   desktopWindow->file_name = fileName;
4403   desktopWindow->title = XtNewString( title );
4404
4405   desktopWindow->workspace_name = XtNewString( desktop_data->workspaceData[ws]->name );
4406   desktopWindow->workspace_num = desktop_data->workspaceData[ws]->number;
4407   desktopWindow->restricted_directory = NULL;
4408   desktopWindow->helpVol = NULL;
4409   desktopWindow->toolbox = False;
4410   desktopWindow->view = UNSET_VALUE;
4411   desktopWindow->order = UNSET_VALUE;
4412   desktopWindow->direction = UNSET_VALUE;
4413   desktopWindow->positionEnabled = UNSET_VALUE;
4414
4415   desktopWindow->file_view_data = BuildNewOrderlist(
4416                               NULL /* @@@ use cached info if possible! */,
4417                               desktopWindow->iconGadget,
4418                               home_host_name,
4419                               desktopWindow->dir_linked_to,
4420                               fileName,
4421                               desktopWindow->registered,
4422                               desktopWindow->toolbox );
4423
4424   MakeDesktopWindow( desktopWindow, -1, -1 );
4425   desktopWindow->registered = desktopWindow->file_view_data->registered;
4426
4427   /* go cache some more windows if there isn't enough cached */
4428   if( desktop_data->numCachedIcons < 5 )
4429     InitializeDesktopWindows( 5, XtDisplay( toplevel ) );
4430
4431   /* go save the current state of the desktop */
4432   SaveDesktopInfo( NORMAL_RESTORE );
4433
4434   tt_message_reply( ttMsg );
4435   tttk_message_destroy( ttMsg );
4436
4437   XtFree( workspace );
4438
4439   if( checkBrokenLink != 0 && checkBrokenLinkTimerId == 0 )
4440   {
4441     checkBrokenLinkTimerId = XtAppAddTimeOut(
4442                                  XtWidgetToApplicationContext( toplevel ),
4443                                  checkBrokenLink * 1000,
4444                                  TimerEventBrokenLinks,
4445                                  NULL );
4446   }
4447
4448 }
4449