dthelp: Change to ANSI function definitions
[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 libraries 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 = NULL, *full_path = NULL, *ptr = NULL;
991    char *workSpace = NULL;
992    char *message = NULL;
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 = 0, toolbox = False, view = UNSET_VALUE,
1077           order = UNSET_VALUE, direction = UNSET_VALUE,
1078           positionEnabled = UNSET_VALUE;
1079
1080       desktopWindow = desktop_data->desktopWindows[index];
1081
1082       if (fgets(message, bufferSize, fptr))
1083       {
1084           len = strlen(message); message[len-1] = 0x0;
1085           desktopWindow->file_name = XtNewString(message);
1086       }
1087       else
1088           desktopWindow->file_name = NULL;
1089
1090       if (fgets(message, bufferSize, fptr))
1091       {
1092           len = strlen(message); message[len-1] = 0x0;
1093           workSpace = XtNewString(message);
1094       }
1095       else
1096           workSpace = NULL;
1097
1098       if (fgets(message, bufferSize, fptr))
1099       {
1100           len = strlen(message); message[len-1] = 0x0;
1101           desktopWindow->dir_linked_to = XtNewString(message);
1102       }
1103       else
1104           desktopWindow->dir_linked_to = NULL;
1105
1106       { /* Construct the full path and check for the file or link
1107            existence.
1108            If it's not there on the file system, don't bother
1109            to load it.
1110         */
1111         char * path;
1112         struct stat stat_buf;
1113
1114         if (strcmp(desktopWindow->dir_linked_to, "/") == 0)
1115         {
1116           path = (char *) XtMalloc(strlen(desktopWindow->dir_linked_to) +
1117                                    strlen(desktopWindow->file_name) + 1);
1118           sprintf(path, "%s%s", desktopWindow->dir_linked_to,
1119                   desktopWindow->file_name);
1120         }
1121         else
1122         {
1123           path = (char *) XtMalloc(strlen(desktopWindow->dir_linked_to) +
1124                                    strlen(desktopWindow->file_name) + 2);
1125           sprintf(path, "%s/%s", desktopWindow->dir_linked_to,
1126                   desktopWindow->file_name);
1127         }
1128
1129         if( stat(path, &stat_buf) != 0
1130             && lstat(path, &stat_buf) != 0 )
1131         {
1132           XtFree(desktopWindow->file_name);
1133           desktopWindow->file_name = NULL;
1134           XtFree(workSpace);
1135           workSpace = NULL;
1136           XtFree(desktopWindow->dir_linked_to);
1137           desktopWindow->dir_linked_to = NULL;
1138           XtFree(path);
1139           path = NULL;
1140           continue;
1141         }
1142
1143         XtFree(path);
1144         path = NULL;
1145       }
1146
1147       if (fgets(message, bufferSize, fptr))
1148       {
1149           len = strlen(message); message[len-1] = 0x0;
1150           if( strcmp(message, NULL_STRING) == 0 )
1151               desktopWindow->restricted_directory = NULL;
1152           else
1153               desktopWindow->restricted_directory = XtNewString(message);
1154       }
1155       else
1156           desktopWindow->restricted_directory = NULL;
1157
1158       if (fgets(message, bufferSize, fptr))
1159       {
1160           len = strlen(message); message[len-1] = 0x0;
1161           if( strcmp(message, NULL_STRING) == 0 )
1162               desktopWindow->title = NULL;
1163           else
1164               desktopWindow->title = XtNewString(message);
1165       }
1166       else
1167           desktopWindow->title = NULL;
1168
1169       if (fgets(message, bufferSize, fptr))
1170       {
1171           len = strlen(message); message[len-1] = 0x0;
1172           if( strcmp(message, NULL_STRING) == 0 )
1173               desktopWindow->helpVol = NULL;
1174           else
1175               desktopWindow->helpVol = XtNewString(message);
1176       }
1177       else
1178           desktopWindow->helpVol = NULL;
1179
1180       if (fgets(message, bufferSize, fptr))
1181       {
1182           sscanf( message, "%d %d %d %d %d %d %d\n",
1183                   &toolbox, &view, &order, &direction, &positionEnabled, &rX, &rY );
1184       }
1185       else
1186           message = NULL;
1187
1188       desktopWindow->toolbox = (char)toolbox;
1189       desktopWindow->view = (char)view;
1190       desktopWindow->order = (char)order;
1191       desktopWindow->direction = (char)direction;
1192       desktopWindow->positionEnabled = (Boolean)positionEnabled;
1193
1194       /* set up the workspace number */
1195       haveOne = False;
1196       for(j = 0; j < desktop_data->numWorkspaces; j++)
1197       {
1198          if(strcmp(workSpace, desktop_data->workspaceData[j]->name) == 0)
1199          {
1200              haveOne = True;
1201              desktopWindow->workspace_name = workSpace;
1202              desktopWindow->workspace_num =
1203                                        desktop_data->workspaceData[j]->number;
1204              break;
1205          }
1206       }
1207
1208       if(!haveOne)
1209       {
1210          desktopWindow->workspace_num = 1;
1211          desktopWindow->workspace_name =
1212            (char *)XtMalloc(strlen(desktop_data->workspaceData[0]->name) + 1);
1213          strcpy(desktopWindow->workspace_name,
1214                 desktop_data->workspaceData[0]->name);
1215          XtFree(workSpace);
1216          workSpace = NULL;
1217       }
1218
1219       desktopWindow->host = XtNewString(home_host_name);
1220
1221       desktopWindow->file_view_data =
1222              BuildNewOrderlist(NULL, desktopWindow->iconGadget,
1223                                desktopWindow->host,
1224                                desktopWindow->dir_linked_to,
1225                                desktopWindow->file_name,
1226                                desktopWindow->registered,
1227                                desktopWindow->toolbox);
1228
1229       MakeDesktopWindow(desktopWindow, rX, rY);
1230       desktopWindow->registered = desktopWindow->file_view_data->registered;
1231
1232       desktop_data->numIconsUsed++;
1233       desktop_data->numCachedIcons--;
1234       index++;
1235    }
1236    XtFree(message);
1237    message = NULL;
1238
1239    fclose(fptr);
1240
1241    XtFree(fileName);
1242    fileName = NULL;
1243    SaveDesktopInfo(NORMAL_RESTORE);
1244 }
1245
1246
1247 static void
1248 FreeDesktopWindow(
1249      DesktopRec *desktopWindow)
1250 {
1251    int i;
1252    DesktopRec *tempDesktopWindow;
1253    FileViewData *file_view_data;
1254    DirectorySet *directory_set;
1255    Dimension width, height;
1256    Arg args[2];
1257
1258    file_view_data = desktopWindow->file_view_data;
1259    directory_set = (DirectorySet *)file_view_data->directory_set;
1260    tempDesktopWindow = desktopWindow;
1261
1262    XtSetArg (args[0], XmNwidth, &width);
1263    XtSetArg (args[1], XmNheight, &height);
1264    XtGetValues(desktopWindow->shell, args, 2);
1265
1266    RegisterInGrid((int)width, (int)height, desktopWindow->root_x,
1267                    desktopWindow->root_y, desktopWindow->workspace_num, False);
1268
1269    if(desktopWindow->text != NULL)
1270    {
1271       XtUnmanageChild(desktopWindow->text);
1272       XtDestroyWidget(desktopWindow->text);
1273       desktopWindow->text = NULL;
1274    }
1275
1276    for(i = 0; i < desktop_data->numIconsUsed; i++)
1277         if(desktopWindow == desktop_data->desktopWindows[i])
1278            break;
1279
1280    /* circulate this */
1281    for(;i < desktop_data->numIconsUsed - 1; i++)
1282    {
1283       desktop_data->desktopWindows[i] =
1284                        desktop_data->desktopWindows[i + 1];
1285    }
1286
1287    /* clear all memory used by the desktop window */
1288    desktop_data->desktopWindows[i] = tempDesktopWindow;
1289    XtRemoveAllCallbacks(desktop_data->desktopWindows[i]->iconGadget,
1290                                                             XmNcallback);
1291    XtFree((char *)directory_set->file_mgr_data);
1292    directory_set->file_mgr_data = NULL;
1293    XtFree((char *)directory_set->name);
1294    directory_set->name = NULL;
1295    XtFree((char *)directory_set);
1296    directory_set = NULL;
1297    FreeFileData(file_view_data->file_data, True);
1298    if(file_view_data->label)
1299    {
1300       XtFree((char *)file_view_data->label);
1301       file_view_data->label = NULL;
1302    }
1303    XtFree((char *)file_view_data);
1304    file_view_data = NULL;
1305    XtFree(desktop_data->desktopWindows[i]->restricted_directory);
1306    desktop_data->desktopWindows[i]->restricted_directory = NULL;
1307    XtFree(desktop_data->desktopWindows[i]->title);
1308    desktop_data->desktopWindows[i]->title = NULL;
1309    XtFree(desktop_data->desktopWindows[i]->helpVol);
1310    desktop_data->desktopWindows[i]->helpVol = NULL;
1311    XtFree(desktop_data->desktopWindows[i]->workspace_name);
1312    desktop_data->desktopWindows[i]->workspace_name = NULL;
1313    XtFree(desktop_data->desktopWindows[i]->host);
1314    desktop_data->desktopWindows[i]->host = NULL;
1315    XtFree(desktop_data->desktopWindows[i]->dir_linked_to);
1316    desktop_data->desktopWindows[i]->dir_linked_to = NULL;
1317    XtFree(desktop_data->desktopWindows[i]->file_name);
1318    desktop_data->desktopWindows[i]->file_name = NULL;
1319
1320    desktop_data->desktopWindows[i]->restricted_directory = NULL;
1321    desktop_data->desktopWindows[i]->title = NULL;
1322    desktop_data->desktopWindows[i]->helpVol = NULL;
1323    desktop_data->desktopWindows[i]->workspace_name = NULL;
1324    desktop_data->desktopWindows[i]->host = NULL;
1325    desktop_data->desktopWindows[i]->dir_linked_to = NULL;
1326    desktop_data->desktopWindows[i]->file_name = NULL;
1327
1328    desktop_data->desktopWindows[i]->root_x = -1;
1329    desktop_data->desktopWindows[i]->root_y = -1;
1330
1331    desktop_data->desktopWindows[i]->file_view_data = NULL;
1332    desktop_data->numIconsUsed--;
1333    desktop_data->numCachedIcons++;
1334
1335    /* now lets check the number of cached Icons, if its too large free some
1336     * of the cache.
1337     */
1338
1339    if(desktop_data->numCachedIcons > MAX_CACHED_ICONS)
1340       FreeCachedIcons(desktop_data->numCachedIcons - MAX_CACHED_ICONS);
1341
1342    SaveDesktopInfo(NORMAL_RESTORE);
1343
1344 }
1345
1346
1347 static void
1348 DrawAInput (
1349       Widget w,
1350       XtPointer client_data,
1351       XEvent *event,
1352       Boolean *contDispatch)
1353 {
1354    XmManagerWidget action_pane;
1355    DesktopRec *desktopWindow;
1356    XButtonEvent *bevent;
1357    Arg args[2];
1358    int i, j, num_children, num_of_files;
1359    static int beventx = -1;
1360    static int beventy = -1;
1361
1362    /* if a drag is active, don't do anything. */
1363    if(dragActive)
1364       return;
1365
1366
1367    bevent = (XButtonEvent *)event;
1368    desktop_data->event = *bevent;
1369    desktopWindow = (DesktopRec *) client_data;
1370
1371    /* first decide whether more than one file is selected */
1372    for(i = 0; i < desktop_data->numWorkspaces; i++)
1373    {
1374       if(desktop_data->workspaceData[i]->number == desktopWindow->workspace_num)
1375          break;
1376    }
1377
1378    num_of_files = 0;
1379    for(j = 0; j < desktop_data->workspaceData[i]->files_selected; j++)
1380    {
1381       /* we need to check to see if the dt object this popup is on is
1382          a selected file */
1383       if(desktop_data->workspaceData[i]->selectedDTWindows[j] == desktopWindow)
1384       {
1385          /* it is in the selected list */
1386          num_of_files = desktop_data->workspaceData[i]->files_selected;
1387          break;
1388       }
1389    }
1390
1391    if(num_of_files > 1)
1392    {
1393       /* we have more than one files selected,
1394          Set userData, so that help system can obtain the desktop info */
1395       XtSetArg(args[0], XmNuserData,
1396           (XtPointer)desktop_data->workspaceData[i]->selectedDTWindows);
1397       XtSetValues(desktop_data->popupMenu->popup, args, 1);
1398
1399       XtRemoveAllCallbacks(desktop_data->popupMenu->removeDT,
1400                                                  XmNactivateCallback);
1401       XtAddCallback(desktop_data->popupMenu->removeDT, XmNactivateCallback,
1402               RemoveDT,
1403               (XtPointer) desktop_data->workspaceData[i]->selectedDTWindows[0]);
1404       XtRemoveAllCallbacks(desktop_data->popupMenu->openFolder,
1405                                                       XmNactivateCallback);
1406       XtAddCallback(desktop_data->popupMenu->openFolder, XmNactivateCallback,
1407                                          OpenFolder, (XtPointer) NULL);
1408
1409       XtRemoveAllCallbacks(desktop_data->popupMenu->rename,
1410                                                          XmNactivateCallback);
1411       XtAddCallback(desktop_data->popupMenu->rename, XmNactivateCallback,
1412                                          renameDT, (XtPointer) NULL);
1413
1414       /* unsensitise the "Open Parent Folder" and "Rename" options */
1415       XtSetSensitive(desktop_data->popupMenu->openFolder, False);
1416       XtSetSensitive(desktop_data->popupMenu->rename, False);
1417
1418       /*  Unmanage all action menu buttons. */
1419       action_pane = (XmManagerWidget) desktop_data->popupMenu->popup;
1420
1421       num_children = action_pane->composite.num_children;
1422       for (i = 7; i < num_children; i++)
1423       {
1424         XtUnmanageChild (action_pane->composite.children[i]);
1425       }
1426    }
1427    else
1428    {
1429        /* No point in continuing any further if any of these pointers
1430           is NULL */
1431       if(!desktop_data->popupMenu || !desktopWindow->file_view_data)
1432          return;
1433       /* we have zero or one files selected, so just put up the popup for
1434          the one */
1435
1436       /* Set userData, so that help system can obtain the desktop info */
1437       XtSetArg(args[0], XmNuserData, client_data);
1438       XtSetValues(desktop_data->popupMenu->popup, args, 1);
1439
1440       XtRemoveAllCallbacks(desktop_data->popupMenu->removeDT,
1441                            XmNactivateCallback);
1442       XtAddCallback(desktop_data->popupMenu->removeDT, XmNactivateCallback,
1443                     RemoveDT, (XtPointer) desktopWindow);
1444
1445       XtRemoveAllCallbacks(desktop_data->popupMenu->openFolder,
1446                            XmNactivateCallback);
1447       XtAddCallback(desktop_data->popupMenu->openFolder, XmNactivateCallback,
1448                     OpenFolder, (XtPointer) desktopWindow);
1449
1450       XtRemoveAllCallbacks(desktop_data->popupMenu->rename,
1451                            XmNactivateCallback);
1452
1453       if( desktopWindow->toolbox == False )
1454       {  /* Sensitize rename
1455           */
1456          XtSetSensitive(desktop_data->popupMenu->rename, True);
1457          XtAddCallback(desktop_data->popupMenu->rename, XmNactivateCallback,
1458                        renameDT, (XtPointer) desktopWindow);
1459       }
1460       else
1461       {  /* Don't allow user to rename the objects in the tool box.
1462             These things are action labels.
1463          */
1464          XtSetSensitive(desktop_data->popupMenu->rename, False);
1465
1466       }
1467
1468       XtSetSensitive(desktop_data->popupMenu->openFolder, True);
1469
1470       XtFree(desktop_data->popupMenu->action_pane_file_type);
1471       desktop_data->popupMenu->action_pane_file_type = NULL;
1472       desktop_data->popupMenu->action_pane_file_type = XtNewString(
1473                desktopWindow->file_view_data->file_data->logical_type);
1474
1475       UpdateActionMenuPane ((XtPointer)desktopWindow, (FileMgrRec *)NULL,
1476                             desktop_data->popupMenu->action_pane_file_type,
1477                             DESKTOP, 7, desktop_data->popupMenu->popup,
1478                             desktopWindow->file_view_data->file_data->physical_type);
1479
1480       if(desktopWindow->file_view_data->file_data->physical_type == DtDIRECTORY
1481          && desktopWindow->file_name )
1482       {
1483          char *ptr;
1484
1485          ptr = DtStrrchr(desktopWindow->title, ':');
1486          if(ptr != NULL)
1487          {
1488             ptr++;
1489             if(strcmp(root_title, ptr) == 0)
1490             { /* The desktop object is a ROOT directory */
1491                XtSetSensitive(desktop_data->popupMenu->openFolder, False);
1492                XtSetSensitive(desktop_data->popupMenu->rename, False);
1493                XtRemoveAllCallbacks(desktop_data->popupMenu->rename,
1494                                     XmNactivateCallback);
1495             }
1496          }
1497       }
1498    }
1499
1500    if(event == NULL)
1501    {
1502       Position x, y;
1503       Dimension width, height;
1504       int displayWidth, displayHeight;
1505       DtIconGadget g;
1506
1507       XtSetArg (args[0], XmNwidth, &width);
1508       XtSetArg (args[1], XmNheight, &height);
1509       XtGetValues(XtParent(desktop_data->popupMenu->popup), args, 2);
1510
1511       displayWidth = DisplayWidth(XtDisplay(w), DefaultScreen(XtDisplay(w)));
1512       displayHeight = DisplayHeight(XtDisplay(w), DefaultScreen(XtDisplay(w)));
1513
1514       g = (DtIconGadget)desktopWindow->iconGadget;
1515
1516       if(beventx == -1)
1517          beventx = desktopWindow->root_x + g->icon.pixmap_width/2;
1518
1519       if((Dimension)(beventx + width) > (Dimension)displayWidth)
1520          beventx = displayWidth - width - 4;
1521
1522       if(beventy == -1)
1523          beventy = desktopWindow->root_y +
1524                  desktopWindow->iconGadget->core.height/2;
1525
1526       if((Dimension)(beventy + height) > (Dimension)displayHeight)
1527          beventy = beventy - height - 1;
1528
1529       XtSetArg (args[0], XmNx, beventx);
1530       XtSetArg (args[1], XmNy, beventy);
1531       XtSetValues(XtParent(desktop_data->popupMenu->popup), args, 2);
1532       beventx = -1;
1533       beventy = -1;
1534    }
1535    else
1536    {
1537       beventx = bevent->x_root;
1538       beventy = bevent->y_root;
1539       XmMenuPosition(desktop_data->popupMenu->popup,
1540                                   (XButtonPressedEvent *)bevent);
1541    }
1542
1543    XtManageChild(desktop_data->popupMenu->popup);
1544
1545 }
1546
1547 /**********************************************************************
1548  *
1549  *  RemoveDT - Callback from the Desktop Popup menu to 'Remove From
1550  *      Desktop'.  Popdown's and Free the desktop window passed in
1551  *      in the client_data pointer.  Then checks to see if any other
1552  *      desktop window is pointing to the file in the File Manager the
1553  *      removed desktop object was pointing to.  If there's not, it
1554  *      removes the file from the desktop list.
1555  *
1556  ************************************************************************/
1557
1558 void
1559 RemoveDT (Widget w, XtPointer client_data, XtPointer call_data)
1560 {
1561    DesktopRec *desktopWindow = (DesktopRec *) client_data;
1562    int i, j, num_of_files;
1563    Boolean selected = False;
1564
1565    /* first decide whether more than one file is selected */
1566    for(i = 0; i < desktop_data->numWorkspaces; i++)
1567    {
1568       if(desktop_data->workspaceData[i]->number == desktopWindow->workspace_num)
1569          break;
1570    }
1571
1572    /* next determine if the file is really in the selected list */
1573    num_of_files = 0;
1574    for(j = 0; j < desktop_data->workspaceData[i]->files_selected; j++)
1575    {
1576       /* we need to check to see if the dt object this popup is on is
1577          a selected file */
1578       if(desktop_data->workspaceData[i]->selectedDTWindows[j] == desktopWindow)
1579       {
1580          /* it is in the selected list */
1581          num_of_files = desktop_data->workspaceData[i]->files_selected;
1582          break;
1583       }
1584    }
1585
1586    if(num_of_files == 0)
1587      num_of_files = 1;
1588    else
1589      selected = True;
1590
1591    for(j = 0; j < num_of_files; j++)
1592    {
1593       if(selected)
1594          desktopWindow = desktop_data->workspaceData[i]->selectedDTWindows[j];
1595
1596       XtPopdown(desktopWindow->shell);
1597       XWithdrawWindow(XtDisplay(desktopWindow->shell),
1598                       XtWindow(desktopWindow->shell),
1599                       XDefaultScreen(XtDisplay(desktopWindow->shell)));
1600
1601       FreeDesktopWindow(desktopWindow);
1602       if(selected)
1603          desktop_data->workspaceData[i]->files_selected--;
1604    }
1605 }
1606
1607 #ifdef SUN_PERF
1608 void
1609 RemoveMovedObjectFromDT (Widget w, XtPointer client_data, int file_cnt,
1610                          char **file_list)
1611 {
1612    DesktopRec *desktopWindow = (DesktopRec *) client_data;
1613    int i, j, k, m, num_of_files;
1614    Boolean selected = False;
1615    char filename[MAX_PATH] ;
1616
1617    /* first decide whether more than one file is selected */
1618    for(i = 0; i < desktop_data->numWorkspaces; i++)
1619    {
1620       if(desktop_data->workspaceData[i]->number == desktopWindow->workspace_num)
1621          break;
1622    }
1623
1624    /* next determine if the file is really in the selected list */
1625    num_of_files = 0;
1626    for(j = 0; j < desktop_data->workspaceData[i]->files_selected; j++)
1627    {
1628       /* we need to check to see if the dt object this popup is on is
1629          a selected file */
1630       if(desktop_data->workspaceData[i]->selectedDTWindows[j] == desktopWindow)
1631       {
1632          /* it is in the selected list */
1633          num_of_files = desktop_data->workspaceData[i]->files_selected;
1634          break;
1635       }
1636    }
1637
1638    if(num_of_files == 0)
1639      selected = 1;
1640    else
1641      selected = True;
1642
1643    for(k = 0; k < num_of_files; k++)
1644    {
1645       if(selected)
1646          desktopWindow = desktop_data->workspaceData[i]->selectedDTWindows[k];
1647       for(j = 0; j < file_cnt; j++) {
1648          strcpy(filename, desktopWindow->dir_linked_to) ;
1649          strcat(filename, "/") ;
1650          strcat(filename, desktopWindow->file_name) ;
1651          if (!strcmp(filename, file_list[j])) {
1652              XtPopdown(desktopWindow->shell);
1653              XWithdrawWindow(XtDisplay(desktopWindow->shell),
1654                       XtWindow(desktopWindow->shell),
1655                       XDefaultScreen(XtDisplay(desktopWindow->shell)));
1656
1657              FreeDesktopWindow(desktopWindow);
1658              if(selected) {
1659                 desktop_data->workspaceData[i]->files_selected--;
1660                 for (m = k ; m < num_of_files - 1 ; m++) {
1661                   desktop_data->workspaceData[i]->selectedDTWindows[m] =
1662                     desktop_data->workspaceData[i]->selectedDTWindows[m + 1];
1663                 }
1664              }
1665          }
1666       }
1667    }
1668 }
1669 #endif /* SUN_PERF */
1670
1671 static void
1672 OpenFolder (
1673       Widget w,
1674       XtPointer client_data,
1675       XtPointer call_data)
1676 {
1677    DesktopRec   *desktopWindow;
1678    DirectorySet *directory_data;
1679    FileViewData *file_view_data;
1680    FileMgrData  *file_mgr_data;
1681    FileMgrRec   *file_mgr_rec;
1682    DialogData   *dialog_data;
1683    int j;
1684
1685    desktopWindow = (DesktopRec *) client_data;
1686    file_view_data = desktopWindow->file_view_data;
1687
1688    if (desktopWindow->toolbox)
1689    {
1690       DtActionArg  *action_args;
1691       char *pwd_dir;
1692
1693       action_args = (DtActionArg *) XtCalloc(1, sizeof(DtActionArg));
1694       if (action_args)
1695       {
1696          action_args[0].argClass = DtACTION_FILE;
1697          action_args[0].u.file.name = desktopWindow->dir_linked_to;
1698       }
1699
1700       pwd_dir = XtNewString(desktopWindow->dir_linked_to);
1701       DtActionInvoke(desktopWindow->shell, "OpenParentAppGroup", action_args, 1,
1702                      NULL, NULL, pwd_dir, True, NULL, NULL);
1703       XtFree(pwd_dir);
1704       pwd_dir = NULL;
1705    }
1706    else
1707    {
1708       initiating_view = (XtPointer) NULL;
1709
1710       if(desktopWindow->restricted_directory != NULL)
1711       {
1712          special_view = True;
1713          special_treeType = SINGLE_DIRECTORY;
1714          special_viewType = desktopWindow->view;
1715          special_orderType = desktopWindow->order;
1716          special_directionType = desktopWindow->direction;
1717          special_randomType = desktopWindow->positionEnabled;
1718          special_restricted = XtNewString(desktopWindow->restricted_directory);
1719          if(desktopWindow->title == NULL)
1720             special_title = NULL;
1721          else
1722             special_title = XtNewString(desktopWindow->title);
1723          special_helpVol = XtNewString(desktopWindow->helpVol);
1724          if(desktopWindow->toolbox)
1725             dialog_data = GetNewView(desktopWindow->host,
1726                                      desktopWindow->dir_linked_to,
1727                                      desktopWindow->restricted_directory,
1728                                      NULL, 0);
1729          else
1730             dialog_data = GetNewView(desktopWindow->host,
1731                                      desktopWindow->dir_linked_to,
1732                                      NULL, NULL, 0);
1733       }
1734       else
1735       {
1736          dialog_data = GetNewView(desktopWindow->host,
1737                                   desktopWindow->dir_linked_to,
1738                                   NULL, NULL, 0);
1739       }
1740
1741       if (openDirType == NEW && dialog_data == NULL)
1742          return;
1743
1744       if( dialog_data == NULL )
1745          return ;
1746
1747       file_mgr_data = (FileMgrData *) dialog_data->data;
1748       directory_data = file_mgr_data->directory_set[0];
1749
1750       for (j = 0; j < directory_data->file_count; j++)
1751       {
1752          file_view_data = directory_data->file_view_data[j];
1753
1754          if (file_view_data->filtered != True &&
1755              strcmp(desktopWindow->file_name,
1756              file_view_data->file_data->file_name) == 0)
1757          {
1758             SelectFile (file_mgr_data, file_view_data);
1759             break;
1760          }
1761       }
1762
1763       if(!directory_data->file_count)
1764           file_mgr_data->desktop_file = XtNewString(desktopWindow->file_name);
1765       else
1766           file_mgr_data->desktop_file = NULL;
1767
1768       file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
1769
1770       /* Initially, all menubuttons are sensitive */
1771       file_mgr_rec->menuStates = (RENAME | MOVE | DUPLICATE | LINK | TRASH |
1772                                   MODIFY | CHANGEDIR | PREFERENCES | FILTER |
1773                                   FIND | CREATE_DIR | CREATE_FILE | SETTINGS |
1774                                   CLEAN_UP | MOVE_UP |
1775                                   HOME | CHANGE_DIR | TERMINAL);
1776
1777       if (file_mgr_data->selected_file_count == 0)
1778          ActivateNoSelect(file_mgr_rec);
1779       else if (file_mgr_data->selected_file_count == 1)
1780          ActivateSingleSelect(file_mgr_rec,
1781                     file_mgr_data->selection_list[0]->file_data->logical_type);
1782       else
1783          ActivateMultipleSelect(file_mgr_rec);
1784
1785       PositionFileView(file_view_data, file_mgr_data);
1786    }
1787 }
1788
1789 static void
1790 renameDT (
1791       Widget w,
1792       XtPointer client_data,
1793       XtPointer call_data)
1794 {
1795    DesktopRec   *desktopWindow;
1796    FileViewData *file_view_data;
1797
1798    desktopWindow = (DesktopRec *) client_data;
1799    file_view_data = desktopWindow->file_view_data;
1800
1801    CreateNameChangeDialog(desktopWindow->iconGadget, file_view_data,
1802                           (XtPointer)desktopWindow, DESKTOP);
1803 }
1804
1805 void
1806 SelectDTFile (DesktopRec *desktopWindow)
1807 {
1808    int selection_count;
1809    int i,j;
1810
1811    Display *display;
1812    Window   rootWindow;
1813    Atom     pCurrent;
1814    Screen   *currentScreen;
1815    int      screen;
1816    char     *workspace_name;
1817
1818
1819    /* Get the current workspace */
1820    display = XtDisplay(desktop_data->desktopWindows[0]->shell);
1821    screen = XDefaultScreen(display);
1822    currentScreen = XScreenOfDisplay(display, screen);
1823    rootWindow = RootWindowOfScreen(currentScreen);
1824
1825    if(DtWsmGetCurrentWorkspace(display, rootWindow, &pCurrent) == Success)
1826    {
1827       workspace_name = XGetAtomName (display, pCurrent);
1828       CleanUpWSName(workspace_name);
1829    }
1830    else
1831       workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
1832
1833    for(i = 0; i < desktop_data->numWorkspaces; i++)
1834    {
1835       if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
1836       {
1837               desktop_data->workspaceData[i]->files_selected++;
1838
1839               desktop_data->workspaceData[i]->selectedDTWindows =
1840                   (DesktopRec **)
1841                   XtRealloc ((char *) desktop_data->workspaceData[i]->selectedDTWindows,
1842                      sizeof(DesktopRec *) *(desktop_data->workspaceData[i]->files_selected + 2));
1843
1844               /* Add to the front of the list */
1845               for (j = desktop_data->workspaceData[i]->files_selected; j > 0; j--)
1846               {
1847                   desktop_data->workspaceData[i]->selectedDTWindows[j] = desktop_data->workspaceData[i]->selectedDTWindows[j-1];
1848                                                                                               }
1849               desktop_data->workspaceData[i]->selectedDTWindows[0] = desktopWindow;
1850               break;
1851       }
1852    }
1853    SetToSelectColors (desktopWindow->iconGadget, desktopWindow->frame,
1854                       LINK_FILE);
1855    XSync(display, False);
1856
1857 }
1858
1859 void
1860 DeselectAllDTFiles (
1861       WorkspaceRec *workspaceData)
1862 {
1863    int selection_count;
1864    register int i;
1865
1866    selection_count = workspaceData->files_selected;
1867
1868    for (i = 0; i < selection_count; i++)
1869    {
1870          SetToNormalColors (workspaceData->selectedDTWindows[i]->iconGadget,
1871                             workspaceData->selectedDTWindows[i]->frame,
1872                             workspaceData->selectedDTWindows[i]->frame,
1873                             LINK_FILE);
1874    }
1875
1876    if (workspaceData->selectedDTWindows != NULL)
1877    {
1878       XtFree ((char *) workspaceData->selectedDTWindows);
1879       workspaceData->selectedDTWindows = NULL;
1880    }
1881
1882    workspaceData->selectedDTWindows =
1883       (DesktopRec **) XtMalloc (sizeof (DesktopRec *));
1884    workspaceData->selectedDTWindows[0] = NULL;
1885    workspaceData->files_selected = 0;
1886
1887 }
1888
1889 void
1890 DeselectDTFile (
1891       WorkspaceRec *workspaceData,
1892       DesktopRec *desktopWindow)
1893 {
1894    int selection_count;
1895    register int i;
1896    register int j;
1897
1898
1899    selection_count = workspaceData->files_selected;
1900    workspaceData->files_selected--;
1901
1902    for (i = 0; i < selection_count; i++)
1903       if (workspaceData->selectedDTWindows[i] == desktopWindow)
1904          break;
1905
1906    for (j = i; j < selection_count - 1; j++)
1907       workspaceData->selectedDTWindows[j] =
1908                                       workspaceData->selectedDTWindows[j + 1];
1909
1910    workspaceData->selectedDTWindows = (DesktopRec **)
1911                    XtRealloc ((char *) workspaceData->selectedDTWindows,
1912                                sizeof(DesktopRec *) * selection_count);
1913    workspaceData->selectedDTWindows[selection_count - 1] = NULL;
1914
1915    SetToNormalColors (desktopWindow->iconGadget, desktopWindow->frame,
1916                                         desktopWindow->frame, LINK_FILE);
1917
1918 }
1919
1920 void
1921 DTActionCallback (
1922      Widget w,
1923      XtPointer client_data,
1924      XtPointer call_data)
1925 {
1926    DesktopRec *desktopWindow;
1927    char *command;
1928    Arg args[1];
1929
1930    desktopWindow = (DesktopRec *) client_data;
1931
1932    XtSetArg (args[0], XmNuserData, (XtPointer) &command);
1933    XtGetValues (w, args, 1);
1934
1935    RunDTCommand(command, desktopWindow, NULL);
1936 }
1937
1938
1939 void
1940 RunDTCommand(
1941       char *command,
1942       DesktopRec *desktopWindow,
1943       DtDndDropCallbackStruct *drop_parameters)
1944
1945 {
1946    if ((strcmp(openNewView, command) == 0) ||
1947        (strcmp(openInPlace, command) == 0))
1948    {
1949       char *ltype = desktopWindow->file_view_data->file_data->logical_type;
1950
1951       /* If the folder is locked, don't allow user to go into it */
1952       if( strcmp( ltype, LT_FOLDER_LOCK ) == 0 )
1953       {
1954         char *tmpStr, *title, *msg;
1955
1956         tmpStr = GETMESSAGE(9, 6, "Action Error");
1957         title = XtNewString(tmpStr);
1958         msg = (char *)XtMalloc(
1959                    strlen( GETMESSAGE(30, 1, "Cannot read from %s") )
1960                  + strlen( desktopWindow->file_view_data->file_data->file_name )
1961                  + 1 );
1962         sprintf( msg, GETMESSAGE(30, 1, "Cannot read from %s"),
1963                  desktopWindow->file_view_data->file_data->file_name );
1964         _DtMessage(desktopWindow->shell,
1965                    title, msg, NULL, HelpRequestCB );
1966         XtFree(title);
1967         title = NULL;
1968         XtFree(msg);
1969         msg = NULL;
1970         return;
1971       }
1972
1973       /* this statement applies to the case where a user traverses down the *
1974        * part of the directory tree containing the application manager      *
1975        * directories or the trash directory                                 */
1976       if( (strcmp(ltype, LT_AGROUP) == 0) ||
1977           (strstr(ltype, LT_AGROUP_SUBDIR)) ||
1978           (strcmp(ltype, LT_TRASH) == 0) )
1979       {
1980          ProcessAction(command,
1981                        desktopWindow->file_view_data,
1982                        drop_parameters,
1983                        desktopWindow->host,
1984                        desktopWindow->dir_linked_to,
1985                        desktopWindow->restricted_directory,
1986                        desktopWindow->shell);
1987       }
1988       else
1989       {
1990          ProcessNewViewDT(desktopWindow);
1991       }
1992    }
1993
1994    else if ((strcmp (command, "FILESYSTEM_MOVE") == 0) ||
1995             (strcmp (command, "FILESYSTEM_COPY") == 0) ||
1996             (strcmp (command, "FILESYSTEM_LINK") == 0))
1997    {
1998       if (drop_parameters->dropData->protocol == DtDND_FILENAME_TRANSFER)
1999          ProcessMoveCopyLinkDT(command, desktopWindow, drop_parameters);
2000       else
2001          ProcessBufferDropOnFolderDT(command, desktopWindow, drop_parameters);
2002    }
2003
2004    else
2005    {
2006       ProcessAction(command,
2007                     desktopWindow->file_view_data,
2008                     drop_parameters,
2009                     desktopWindow->host,
2010                     desktopWindow->dir_linked_to,
2011                     desktopWindow->restricted_directory,
2012                     desktopWindow->shell);
2013    }
2014 }
2015
2016
2017 /************************************************************************
2018  *
2019  *  ProcessNewViewDT
2020  *
2021  ************************************************************************/
2022
2023 static void
2024 ProcessNewViewDT (
2025      DesktopRec *desktopWindow)
2026 {
2027    char directory_name[MAX_PATH];
2028
2029    sprintf(directory_name, "%s/%s", desktopWindow->dir_linked_to,
2030                                     desktopWindow->file_name);
2031    DtEliminateDots (directory_name);
2032
2033    initiating_view = (XtPointer) NULL;
2034    if(desktopWindow->restricted_directory == NULL)
2035    {
2036       GetNewView (desktopWindow->host, directory_name, NULL, NULL, 0);
2037    }
2038    else
2039    {
2040       special_view = True;
2041       special_treeType = SINGLE_DIRECTORY;
2042       special_viewType = desktopWindow->view;
2043       special_orderType = desktopWindow->order;
2044       special_directionType = desktopWindow->direction;
2045       special_randomType = desktopWindow->positionEnabled;
2046       special_restricted = XtNewString(desktopWindow->restricted_directory);
2047       if(desktopWindow->title == NULL)
2048          special_title = NULL;
2049       else
2050          special_title = XtNewString(desktopWindow->title);
2051       special_helpVol = XtNewString(desktopWindow->helpVol);
2052       if(desktopWindow->toolbox)
2053          GetNewView (desktopWindow->host, directory_name,
2054                      desktopWindow->restricted_directory, NULL, 0);
2055       else
2056          GetNewView (desktopWindow->host, directory_name, NULL, NULL, 0);
2057    }
2058 }
2059
2060
2061 /************************************************************************
2062  *
2063  *  ProcessMoveCopyLinkDT
2064  *
2065  ************************************************************************/
2066
2067 static void
2068 ProcessMoveCopyLinkDT (
2069      char *command,
2070      DesktopRec *desktopWindow,
2071      DtDndDropCallbackStruct *drop_parameters)
2072 {
2073    unsigned int modifiers = 0;
2074    int numFiles, i;
2075    char ** file_set;
2076    char ** host_set;
2077    FileViewData * file_view_data;
2078    Boolean error = FALSE;
2079
2080      /***************************************************/
2081      /* if no drop_parameters, there is nothing to move */
2082      /***************************************************/
2083    if (!drop_parameters)
2084      return;
2085
2086      /***************************************************/
2087      /* extract file and host sets from drop parameters */
2088      /***************************************************/
2089    numFiles = drop_parameters->dropData->numItems;
2090    _DtSetDroppedFileInfo(drop_parameters, &file_set, &host_set);
2091
2092
2093       /******************************/
2094       /* set movement modifier mask */
2095       /******************************/
2096    if( (initiating_view != NULL) &&
2097        (((FileMgrData *)initiating_view)->toolbox) )
2098    {
2099       /* if initiating_view is a toolbox, the transfer must be */
2100       /* a copy                                                */
2101       modifiers = ControlMask;
2102    }
2103    else
2104    {
2105       if (strcmp(command, "FILESYSTEM_COPY") == 0)
2106          modifiers = ControlMask;
2107       else if (strcmp(command, "FILESYSTEM_LINK") == 0)
2108          modifiers = ShiftMask;
2109       else
2110          modifiers = 0;
2111    }
2112
2113       /*************************************************************/
2114       /* is the desktop object linked to any of the dropped files? */
2115       /*************************************************************/
2116    file_view_data = desktopWindow->file_view_data;
2117    if (file_view_data->file_data->physical_type == DtDIRECTORY)
2118    {
2119       char dir_name[MAX_PATH];
2120
2121       sprintf(dir_name, "%s/%s", desktopWindow->dir_linked_to,
2122               desktopWindow->file_name);
2123       DtEliminateDots(dir_name);
2124
2125       for (i=0; i < numFiles; i++)
2126       {
2127          if (strcmp(dir_name, file_set[i]) == 0 &&
2128              strcmp(desktopWindow->host, host_set[i]) == 0)
2129          {
2130             char *tmpStr, *msg;
2131
2132             error = True;
2133             tmpStr =
2134                GETMESSAGE(11,16, "A folder cannot be moved into itself.\n%s");
2135             msg = XtNewString(tmpStr);
2136             FileOperationError(file_view_data->widget, msg, dir_name);
2137             XtFree(msg);
2138          }
2139       }
2140    }
2141
2142       /**************/
2143       /* Move files */
2144       /**************/
2145    if (!error)
2146       CheckMoveType((FileMgrData *)NULL, file_view_data,
2147                     (DirectorySet *)(file_view_data->directory_set),
2148                     desktopWindow, file_set, host_set, modifiers,
2149                     numFiles, drop_parameters->x, drop_parameters->y, DESKTOP);
2150
2151       /***************************/
2152       /* free file and host sets */
2153       /***************************/
2154    _DtFreeDroppedFileInfo(numFiles, file_set, host_set);
2155 }
2156
2157
2158 /************************************************************************
2159  *
2160  * ProcessBufferDropOnFolderDT
2161  *
2162  ************************************************************************/
2163
2164 static void
2165 ProcessBufferDropOnFolderDT (
2166      char *command,
2167      DesktopRec *desktopWindow,
2168      DtDndDropCallbackStruct *drop_parameters)
2169 {
2170    int num_of_buffers;
2171    char ** file_set = NULL;
2172    char ** host_set = NULL;
2173    BufferInfo *buffer_set = NULL;
2174    char  directory[MAX_PATH];
2175    FileViewData *file_view_data = desktopWindow->file_view_data;
2176
2177
2178    /********************************************/
2179    /* if no drop_parameters, or invalid params */
2180    /* then disallow the drop                   */
2181    /********************************************/
2182    if (!drop_parameters)
2183      return;
2184
2185    /* if dropped on a folder icon and file_view_data */
2186    /* is NULL, disallow the drop                     */
2187    if (file_view_data == NULL)
2188      return;
2189
2190
2191   /***************************************************/
2192   /* extract file and host sets from drop parameters */
2193   /***************************************************/
2194   num_of_buffers = drop_parameters->dropData->numItems;
2195
2196   /* Allocate memory for file and buffer structures */
2197   file_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers );
2198   host_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers);
2199   buffer_set = (BufferInfo * )XtMalloc (sizeof (BufferInfo) * num_of_buffers);
2200
2201   _DtSetDroppedBufferInfo(file_set, buffer_set, host_set, drop_parameters);
2202
2203
2204   /****************/
2205   /* create files */
2206   /****************/
2207   DPRINTF(("ProcessBufferDropOnFolderDT...Buffers dropped on Folder icon %s\n",
2208           file_view_data->file_data->file_name));
2209
2210    sprintf(directory,"%s/%s",
2211            ((DirectorySet *)file_view_data->directory_set)->name,
2212            file_view_data->file_data->file_name);
2213    DtEliminateDots(directory);
2214
2215    DPRINTF (("Copying buffer to %s\n", directory));
2216    MakeFilesFromBuffersDT(file_view_data, directory, file_set, host_set,
2217                           buffer_set, num_of_buffers,
2218                           desktopWindow, NULL, NULL);
2219
2220
2221   /******************************/
2222   /* free file_set + buffer_set */
2223   /******************************/
2224   _DtFreeDroppedBufferInfo (file_set, buffer_set, host_set, num_of_buffers);
2225 }
2226
2227 char *
2228 IsAFileOnDesktop2(
2229         char **file_set,
2230         int  file_count,
2231         int  *number,
2232         Boolean  *IsToolBox)
2233 {
2234    int i,j;
2235    DesktopRec *desktopWindow;
2236    char tmp_filename[MAX_PATH];
2237    Boolean onDesktop = False;
2238    Boolean Link = False;
2239    char *filesOnDesktop;
2240    char *filename1,*filename2;
2241    int newLen, stat_result;
2242    Tt_status tt_status;
2243    static Tt_message dummy_msg = NULL;
2244    struct stat stat_buf;
2245
2246    *IsToolBox = False;
2247
2248    if(dummy_msg == NULL)
2249       dummy_msg = tt_message_create();
2250
2251    *number = 0;
2252    for(i = 0; i < file_count; i++)
2253    {
2254       /* Let's check to see if file coming in is a link, if it is let's
2255        * test it instead of where it is linked to.
2256        */
2257       stat_result = lstat (file_set[i], &stat_buf);
2258       if (stat_result == 0 && (stat_buf.st_mode & S_IFMT) == S_IFLNK)
2259       {
2260          filename1 = XtNewString(file_set[i]);
2261          Link = True;
2262       }
2263       else
2264       {
2265          tt_status = tt_message_file_set(dummy_msg, file_set[i]);
2266          filename1 = tt_message_file(dummy_msg);
2267          Link = False;
2268       }
2269       for(j = 0; j < desktop_data->numIconsUsed; j++)
2270       {
2271         desktopWindow = desktop_data->desktopWindows[j];
2272
2273 /*
2274         if( strcmp( desktopWindow->dir_linked_to, "/" ) != 0 )
2275           sprintf(tmp_filename, "%s/%s", desktopWindow->dir_linked_to,
2276                     desktopWindow->file_view_data->file_data->file_name);
2277         else
2278           sprintf(tmp_filename, "%s%s", desktopWindow->dir_linked_to,
2279                     desktopWindow->file_view_data->file_data->file_name);
2280 */
2281         strcpy( tmp_filename, desktopWindow->dir_linked_to );
2282         if(Link)
2283            filename2 = XtNewString(tmp_filename);
2284         else
2285         {
2286            tt_status = tt_message_file_set (dummy_msg, tmp_filename);
2287            filename2 = tt_message_file(dummy_msg);
2288         }
2289         filename2 = (char *)XtRealloc(filename2, strlen(filename2)
2290                     + strlen(desktopWindow->file_view_data->file_data->file_name)
2291                     + 2 );
2292         strcat(filename2, "/");
2293         strcat(filename2, desktopWindow->file_view_data->file_data->file_name);
2294
2295         if( strcmp( filename1, filename2 ) == 0 )
2296         {
2297           *IsToolBox = desktopWindow->toolbox;
2298           if(onDesktop == False)
2299           {
2300             filesOnDesktop = (char *)XtMalloc(strlen(filename1) + 10);
2301             sprintf( filesOnDesktop, "\n   %s\n", filename1);
2302             onDesktop = True;
2303           }
2304           else
2305           {
2306             newLen = strlen(filesOnDesktop) + strlen(filename1) + 6;
2307             filesOnDesktop = (char *)XtRealloc(filesOnDesktop, newLen);
2308             sprintf(filesOnDesktop, "%s   %s\n", filesOnDesktop, filename1);
2309           }
2310           *number += 1;
2311           break;
2312         }
2313         if(Link)
2314            XtFree(filename2);
2315         else
2316            tt_free(filename2);
2317       }
2318       if(Link)
2319          XtFree(filename1);
2320       else
2321          tt_free(filename1);
2322    }
2323
2324    if(onDesktop)
2325      return(filesOnDesktop);
2326
2327    return(NULL);
2328 }
2329
2330
2331 /*
2332  * This function handles button 1 selection in a desktop icon.
2333  */
2334
2335 void
2336 ProcessDTSelection (
2337    DesktopRec * desktopRec,
2338    XButtonEvent * event)
2339 {
2340     Window   rootWindow;
2341     Atom     pCurrent;
2342     Screen   *currentScreen;
2343     int      screen;
2344     char     *workspace_name;
2345     Boolean  toggle_select = False;
2346     int i, j;
2347
2348     if (event->state & ControlMask)
2349        toggle_select = True;
2350
2351     screen = XDefaultScreen(XtDisplay(desktopRec->shell));
2352     currentScreen = XScreenOfDisplay(XtDisplay(desktopRec->shell), screen);
2353     rootWindow = RootWindowOfScreen(currentScreen);
2354
2355     if(DtWsmGetCurrentWorkspace(XtDisplay(desktopRec->shell), rootWindow,
2356                                                       &pCurrent) == Success)
2357     {
2358        workspace_name = XGetAtomName (XtDisplay(desktopRec->shell), pCurrent);
2359        CleanUpWSName(workspace_name);
2360     }
2361     else
2362        workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
2363
2364     for(i = 0; i < desktop_data->numWorkspaces; i++)
2365     {
2366        if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
2367        {
2368           if(toggle_select == False)
2369              DeselectAllDTFiles(desktop_data->workspaceData[i]);
2370           else
2371           {
2372              for(j = 0;j < desktop_data->workspaceData[i]->files_selected; j++)
2373              {
2374                 if(desktop_data->workspaceData[i]->selectedDTWindows[j] ==
2375                                                                  desktopRec)
2376                 {
2377                    DeselectDTFile(desktop_data->workspaceData[i], desktopRec);
2378                    return;
2379                 }
2380              }
2381           }
2382
2383           desktop_data->workspaceData[i]->files_selected++;
2384
2385           desktop_data->workspaceData[i]->selectedDTWindows =
2386                (DesktopRec **) XtRealloc ((char *)
2387                          desktop_data->workspaceData[i]->selectedDTWindows,
2388                          sizeof(DesktopRec *) *
2389                          (desktop_data->workspaceData[i]->files_selected + 2));
2390
2391           /* Add to the front of the list */
2392           for (j = desktop_data->workspaceData[i]->files_selected; j > 0; j--)
2393           {
2394              desktop_data->workspaceData[i]->selectedDTWindows[j] =
2395                      desktop_data->workspaceData[i]->selectedDTWindows[j-1];
2396           }
2397
2398           desktop_data->workspaceData[i]->selectedDTWindows[0] = desktopRec;
2399           break;
2400        }
2401     }
2402     XtFree(workspace_name);
2403
2404     SetToSelectColors (desktopRec->iconGadget, desktopRec->frame, LINK_FILE);
2405 }
2406
2407
2408 void
2409 UnpostDTTextField (void)
2410
2411 {
2412    DesktopRec *desktopWindow;
2413    int i;
2414
2415    for(i = 0; i < desktop_data->numIconsUsed; i++)
2416    {
2417       desktopWindow = desktop_data->desktopWindows[i];
2418       if(desktopWindow->text)
2419       {
2420          XtUnmanageChild(desktopWindow->text);
2421 #ifdef SHAPE
2422          GenerateShape(desktopWindow);
2423 #endif
2424          XtDestroyWidget(desktopWindow->text);
2425          desktopWindow->text = NULL;
2426          return;
2427       }
2428    }
2429 }
2430
2431
2432 Boolean
2433 DTFileIsSelected (
2434    DesktopRec * desktopRec,
2435    FileViewData * fileViewData)
2436 {
2437    Window   rootWindow;
2438    Atom     pCurrent;
2439    Screen   *currentScreen;
2440    int      screen;
2441    char     *workspace_name;
2442    int i, j;
2443
2444    screen = XDefaultScreen(XtDisplay(desktopRec->shell));
2445    currentScreen = XScreenOfDisplay(XtDisplay(desktopRec->shell), screen);
2446    rootWindow = RootWindowOfScreen(currentScreen);
2447
2448    if(DtWsmGetCurrentWorkspace(XtDisplay(desktopRec->shell), rootWindow,
2449                                                       &pCurrent) == Success)
2450    {
2451        workspace_name = XGetAtomName (XtDisplay(desktopRec->shell), pCurrent);
2452        CleanUpWSName(workspace_name);
2453    }
2454    else
2455        workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
2456
2457
2458    for(i = 0; i < desktop_data->numWorkspaces; i++)
2459    {
2460       if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
2461       {
2462          for(j = 0;j < desktop_data->workspaceData[i]->files_selected; j++)
2463          {
2464             if(desktop_data->workspaceData[i]->selectedDTWindows[j] ==
2465                                  desktopRec)
2466             {
2467                XtFree(workspace_name);
2468                return(True);
2469             }
2470          }
2471          XtFree(workspace_name);
2472          return(False);
2473       }
2474    }
2475    XtFree(workspace_name);
2476    return(False);
2477 }
2478
2479 /***********************************************************************
2480  *
2481  *  RegisterPanelInGrid - Registers the Dtwm planel in grid
2482  *
2483  *  Arguments: workspace - workspace number
2484  *             displayWidth - width of worspace screen
2485  *             displayHaight - height of workspace screen
2486  *
2487  ************************************************************************/
2488
2489 void RegisterPanelInGrid(int workspace,  int displayWidth, int displayHeight )
2490 {
2491    /* want to take out space where the FP lays ... Note this only for the
2492       default size of the FP.  Right now there is no dynamic way of registering
2493       the FP no matter what size it is */
2494 #define EXPECTED_PANEL_WIDTH 1105
2495 #define EXPECTED_PANEL_HEIGHT 83
2496    RegisterInGrid(EXPECTED_PANEL_WIDTH, EXPECTED_PANEL_HEIGHT,
2497                  /* the panel is expected to be horizontally centered */
2498                  (displayWidth > EXPECTED_PANEL_WIDTH) ?
2499                   (displayWidth - EXPECTED_PANEL_WIDTH) / 2 : 0,
2500                  /* the panel is expected to be at the bottom of the screen */
2501                  (displayHeight > EXPECTED_PANEL_HEIGHT) ?
2502                    (displayHeight - EXPECTED_PANEL_HEIGHT) : displayHeight,
2503                  workspace, True);
2504 }
2505
2506 /***********************************************************************
2507  *
2508  *  InitializeDesktopGrid
2509  *
2510  ************************************************************************/
2511
2512 void
2513 InitializeDesktopGrid( int displayWidth, int displayHeight)
2514 {
2515    int i,j,k;
2516
2517    desktop_grid_size = desktop_data->numWorkspaces * numColumns * numRows;
2518    desktop_grid = (Boolean *)XtCalloc(1, desktop_grid_size);
2519
2520    for(i = 1; i <= desktop_data->numWorkspaces; i++)
2521    {
2522       RegisterPanelInGrid(i, displayWidth, displayHeight);
2523    }
2524 }
2525
2526 void
2527 RegisterInGrid(
2528        int width,
2529        int height,
2530        int rX,
2531        int rY,
2532        int workspace,
2533        Boolean type)
2534 {
2535    int row, column;
2536    int rowHeight, columnWidth;
2537    int desktop_grid_index;
2538    int i,j;
2539
2540    if(desktopIconType == LARGE)
2541    {
2542       row = rY / PIXELS_PER_ROW_LARGE;
2543       column = rX / PIXELS_PER_COLUMN_LARGE;
2544       rowHeight = (rY + height) / PIXELS_PER_ROW_LARGE;
2545       columnWidth = (rX + width) / PIXELS_PER_COLUMN_LARGE;
2546    }
2547    else
2548    {
2549       row = rY / PIXELS_PER_ROW_SMALL;
2550       column = rX / PIXELS_PER_COLUMN_SMALL;
2551       rowHeight = (rY + height) / PIXELS_PER_ROW_SMALL;
2552       columnWidth = (rX + width) / PIXELS_PER_COLUMN_SMALL;
2553    }
2554
2555    if (columnWidth >= numColumns)
2556    {
2557       columnWidth = numColumns - 1;
2558    }
2559    if (rowHeight >= numRows)
2560    {
2561       rowHeight = numRows - 1;
2562    }
2563
2564    desktop_grid_index = (workspace - 1) * numColumns * numRows;
2565
2566    for (i = (column > 0) ? column : 0; i <= columnWidth ; i++)
2567    {
2568       for (j = (row > 0) ? row : 0; j <= rowHeight ; j++)
2569       {
2570          if (type)
2571          {
2572            /* increase count of objects at given cell */
2573             desktop_grid[ desktop_grid_index + (i * numRows) + j] ++;
2574          }
2575          else
2576          {
2577            /* decrease count of objects at given cell  */
2578            if (desktop_grid[ desktop_grid_index + (i * numRows) + j] > 0)
2579            {
2580               desktop_grid[ desktop_grid_index + (i * numRows) + j] --;
2581            }
2582          }
2583       }
2584    }
2585 }
2586
2587
2588
2589 void
2590 PutOnDTCB (
2591      Widget w,
2592      XtPointer client_data,
2593      XtPointer call_data)
2594 {
2595    Arg args[1];
2596    FileMgrRec *file_mgr_rec;
2597    DialogData  * dialog_data;
2598    FileMgrData * file_mgr_data;
2599    FileViewData * file_view_data;
2600    Widget mbar;
2601    char *directory;
2602    char *file_name;
2603    int i,EndIndex;
2604
2605    XmUpdateDisplay (w);
2606
2607    if(client_data != 0)
2608       mbar = XtParent(w);
2609    else
2610       mbar = XmGetPostedFromWidget(XtParent(w));
2611
2612    XtSetArg(args[0], XmNuserData, &file_mgr_rec);
2613    XtGetValues(mbar, args, 1);
2614
2615    /* Ignore accelerators when we're insensitive */
2616    if(client_data == NULL)
2617       if ((file_mgr_rec->menuStates & PUT_ON_DESKTOP) == 0)
2618          return;
2619
2620    /* Ignore accelerators received after we're unposted */
2621    if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
2622       return;
2623    file_mgr_data = (FileMgrData *) dialog_data->data;
2624
2625    /* get the file_view_data object from which the menu was invoked */
2626    if (client_data == NULL)
2627      file_view_data = NULL;
2628    else
2629    {
2630      file_view_data = file_mgr_data->popup_menu_icon;
2631      if (!file_mgr_data->selected_file_count && file_view_data == NULL)
2632        /* the object has gone away (probably deleted) */
2633        return;
2634
2635      file_mgr_data->popup_menu_icon = NULL; /* Reset it, we don't need it */
2636
2637        /* No need to see the selection_list if file_view_data is NULL */
2638
2639
2640      if(file_view_data)
2641      {
2642        for(i = 0; i < file_mgr_data->selected_file_count; i++)
2643        {
2644           if(file_mgr_data->selection_list[i] == file_view_data)
2645           {
2646              file_view_data = NULL;
2647              break;
2648           }
2649        }
2650      }
2651    }
2652
2653    EndIndex = desktop_data->numIconsUsed;
2654    if(file_view_data == NULL)
2655    {
2656       for (i = 0; i < file_mgr_data->selected_file_count; i++)
2657       {
2658          if (file_mgr_data->toolbox)
2659          {
2660             char *path, *ptr;
2661
2662             path = _DtGetSelectedFilePath(file_mgr_data->selection_list[i]);
2663             path = _DtResolveAppManPath(path,
2664                                         file_mgr_data->restricted_directory);
2665             ptr = strrchr(path, '/');
2666             *ptr = '\0';
2667             directory = path;
2668             file_name = ptr + 1;
2669
2670             SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2671                                 file_name, file_mgr_data->host,
2672                                 directory,
2673                                 -1, -1, NULL,EndIndex);
2674
2675             *ptr = '/';
2676             XtFree(path);
2677             path = NULL;
2678          }
2679          else
2680          {
2681             directory = ((DirectorySet *)
2682                    (file_mgr_data->selection_list[i]->directory_set))->name;
2683             file_name = file_mgr_data->selection_list[i]->file_data->file_name;
2684
2685             SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2686                                 file_name, file_mgr_data->host,
2687                                 directory,
2688                                 -1, -1, NULL,EndIndex);
2689          }
2690       }
2691    }
2692    else
2693    {
2694       if (file_mgr_data->toolbox)
2695       {
2696          char *path, *ptr;
2697
2698          path = _DtGetSelectedFilePath(file_view_data);
2699          path = _DtResolveAppManPath(path, file_mgr_data->restricted_directory);
2700          ptr = strrchr(path, '/');
2701          *ptr = '\0';
2702          directory = path;
2703          file_name = ptr + 1;
2704
2705          SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2706                              file_name, file_mgr_data->host,
2707                              directory,
2708                              -1, -1, NULL,EndIndex);
2709
2710          *ptr = '/';
2711          XtFree(path);
2712          path = NULL;
2713       }
2714       else
2715       {
2716          directory = ((DirectorySet *)(file_view_data->directory_set))->name;
2717          file_name = file_view_data->file_data->file_name;
2718          SetupDesktopWindow (XtDisplay(w), file_mgr_data, file_mgr_rec,
2719                              file_name, file_mgr_data->host,
2720                              file_mgr_data->current_directory, -1, -1, NULL,EndIndex);
2721       }
2722    }
2723 }
2724
2725
2726 static void
2727 CalculateRootCoordinates (
2728      int ws_num,
2729      int width,
2730      int height,
2731      int *root_x,
2732      int *root_y)
2733 {
2734    int      row = 0, column = 0;
2735    Boolean  rDirection = False, cDirection = False, whichFirst = False;
2736    Boolean  error = False;
2737    int      numGridsR, numGridsC, i, j;
2738
2739    if(desktopIconType == LARGE)
2740    {
2741       numGridsC = (width / PIXELS_PER_COLUMN_LARGE) + 1;
2742       numGridsR = (height / PIXELS_PER_ROW_LARGE) + 1;
2743    }
2744    else /* small */
2745    {
2746       numGridsC = (width / PIXELS_PER_COLUMN_SMALL) + 1;
2747       numGridsR = (height / PIXELS_PER_ROW_SMALL) + 1;
2748    }
2749
2750    /*
2751     * set up where to get the first grid spot and which directions to
2752     * search for one until one is found.  For directions True means in the
2753     * positive direction.  If whichFirst is True then row is moved first.
2754     */
2755    switch( desktopPlacement )
2756    {
2757        case (OBJ_PLACE_LEFT_PRIMARY | OBJ_PLACE_TOP_SECONDARY):
2758        case (OBJ_PLACE_TOP_PRIMARY | OBJ_PLACE_LEFT_SECONDARY):
2759            row = 0;
2760            column = 0;
2761            rDirection = True;
2762            cDirection = True;
2763            if(desktopPlacement & OBJ_PLACE_LEFT_PRIMARY)
2764              whichFirst = False;
2765            else
2766              whichFirst = True;
2767            break;
2768
2769        case (OBJ_PLACE_LEFT_PRIMARY | OBJ_PLACE_BOTTOM_SECONDARY):
2770        case (OBJ_PLACE_BOTTOM_PRIMARY | OBJ_PLACE_LEFT_SECONDARY):
2771            row = numRows - numGridsR;
2772            column = 0;
2773            rDirection = False;
2774            cDirection = True;
2775            if(desktopPlacement & OBJ_PLACE_LEFT_PRIMARY)
2776              whichFirst = False;
2777            else
2778              whichFirst = True;
2779            break;
2780
2781        case (OBJ_PLACE_RIGHT_PRIMARY | OBJ_PLACE_TOP_SECONDARY):
2782        case (OBJ_PLACE_TOP_PRIMARY | OBJ_PLACE_RIGHT_SECONDARY):
2783            row = 0;
2784            column = numColumns - numGridsC;
2785            rDirection = True;
2786            cDirection = False;
2787            if(desktopPlacement & OBJ_PLACE_RIGHT_PRIMARY)
2788              whichFirst = False;
2789            else
2790              whichFirst = True;
2791            break;
2792
2793        case (OBJ_PLACE_RIGHT_PRIMARY | OBJ_PLACE_BOTTOM_SECONDARY):
2794        case (OBJ_PLACE_BOTTOM_PRIMARY | OBJ_PLACE_RIGHT_SECONDARY):
2795            row = numRows - numGridsR;
2796            column = numColumns - numGridsC;
2797            rDirection = False;
2798            cDirection = False;
2799            if(desktopPlacement & OBJ_PLACE_RIGHT_PRIMARY)
2800              whichFirst = False;
2801            else
2802              whichFirst = True;
2803            break;
2804    }
2805
2806
2807    /*
2808     * Given the information which is set up above, find the first availible
2809     * spot in the grid where the Desktop Icon can be placed.  NOTE: if the
2810     * Icon turns out to be bigger then the size of the grid, this may have
2811     * to be recalculated.  But we won't know the size until we do a realize
2812     */
2813    ws_num = ((ws_num - 1) * numColumns * numRows);
2814    while(1)
2815    {
2816       if(desktop_grid[ws_num + (column * numRows) + row] == 0)
2817       {
2818          if(numGridsR == 1 && numGridsC == 1)
2819          {
2820             if(desktopIconType == LARGE)
2821             {
2822                *root_x = column * PIXELS_PER_COLUMN_LARGE;
2823                *root_y = row * PIXELS_PER_ROW_LARGE;
2824             }
2825             else
2826             {
2827                *root_x = column * PIXELS_PER_COLUMN_SMALL;
2828                *root_y = row * PIXELS_PER_ROW_SMALL;
2829             }
2830             return;
2831          }
2832
2833          for(i = 0; i < numGridsR; i++)
2834          {
2835             for(j = 0; j < numGridsC; j++)
2836             {
2837                if(desktop_grid[ws_num + ((column + j) * numRows) + (row + i)] > 0)
2838               {
2839                  error = True;
2840                  break;
2841               }
2842             }
2843             if(error)
2844                break;
2845          }
2846          if(!error)
2847          {
2848             if(desktopIconType == LARGE)
2849             {
2850                *root_x = column * PIXELS_PER_COLUMN_LARGE;
2851                *root_y = row * PIXELS_PER_ROW_LARGE;
2852             }
2853             else
2854             {
2855                *root_x = column * PIXELS_PER_COLUMN_SMALL;
2856                *root_y = row * PIXELS_PER_ROW_SMALL;
2857             }
2858             return;
2859          }
2860          else
2861             error = False;
2862       }
2863
2864       /*
2865        * area taken so let get the next grid depending on rDirection,
2866        * cDirection and whchis is first
2867        */
2868       if(whichFirst)
2869       {
2870          if(rDirection)
2871          {
2872             row += 1;
2873             if(row >= numRows)
2874             {
2875                row = 0;
2876                if(cDirection)
2877                {
2878                   column += 1;
2879                   if(column + numGridsC - 1 >= numColumns)
2880                   {
2881                      error = True;
2882                      break;
2883                   }
2884                }
2885                else
2886                {
2887                   column -= 1;
2888                   if(column < 0)
2889                   {
2890                      error = True;
2891                      break;
2892                   }
2893                }
2894             }
2895          }
2896          else
2897          {
2898             row -= 1;
2899             if(row <  0)
2900             {
2901                row = numRows - 1;
2902                if(cDirection)
2903                {
2904                   column += 1;
2905                   if(column + numGridsC - 1 >= numColumns)
2906                   {
2907                      error = True;
2908                      break;
2909                   }
2910                }
2911                else
2912                {
2913                   column -= 1;
2914                   if(column < 0)
2915                   {
2916                      error = True;
2917                      break;
2918                   }
2919                }
2920             }
2921          }
2922       }
2923       else
2924       {
2925          if(cDirection)
2926          {
2927             column += 1;
2928             if(column >= numColumns)
2929             {
2930                column = 0;
2931                if(rDirection)
2932                {
2933                   row += 1;
2934                   if( row + numGridsR - 1 >= numRows)
2935                   {
2936                      error = True;
2937                      break;
2938                   }
2939                }
2940                else
2941                {
2942                   row -= 1;
2943                   if( row < 0)
2944                   {
2945                      error = True;
2946                      break;
2947                   }
2948                }
2949             }
2950          }
2951          else
2952          {
2953             column -= 1;
2954             if(column < 0)
2955             {
2956                column = numColumns - 1;
2957                if(rDirection)
2958                {
2959                   row += 1;
2960                   if( row + numGridsR - 1>= numRows)
2961                   {
2962                      error = True;
2963                      break;
2964                   }
2965                }
2966                else
2967                {
2968                   row -= 1;
2969                   if( row < 0)
2970                   {
2971                      error = True;
2972                      break;
2973                   }
2974                }
2975             }
2976          }
2977       }
2978    }
2979 }
2980
2981
2982 void
2983 SetupDesktopWindow (
2984      Display *display,
2985      FileMgrData *file_mgr_data,
2986      FileMgrRec *file_mgr_rec,
2987      char *file_name,
2988      char *hst_name,
2989      char *dir_name,
2990      int root_x,
2991      int root_y,
2992      char *type,
2993      int EndIndex)
2994 {
2995    char *title;
2996    char title_buf[256];
2997    Boolean restricted_top;
2998    DesktopRec *desktopWindow;
2999    int i, j;
3000    int ws_num;
3001    Window   rootWindow;
3002    Atom     pCurrent;
3003    Screen   *currentScreen;
3004    int      screen;
3005    char   * workspace_name;
3006    char *ptr, * directory_name;
3007    Tt_status tt_status;
3008
3009
3010    DPRINTF(("SetupDesktopWindow: %s\n", file_name));
3011
3012    /*
3013     * Get the host, directory, and file name for the real file
3014     */
3015
3016    /* get the full path and eliminate dots */
3017    directory_name = ResolveLocalPathName(hst_name,
3018                                          dir_name,
3019                                          file_name,
3020                                          home_host_name,
3021                                          &tt_status);
3022    if( TT_OK != tt_status )
3023    { /* Should pop up an error dialog.
3024      */
3025      return;
3026    }
3027
3028    DtEliminateDots(directory_name);
3029
3030    /* check if this is a restricted directory */
3031    restricted_top = file_mgr_data &&
3032                     file_mgr_data->restricted_directory &&
3033                     strcmp(directory_name,
3034                            file_mgr_data->restricted_directory) == 0;
3035
3036    /* separate the rest of the path into directory and file name */
3037    ptr = strrchr(directory_name, '/');
3038    if (*(ptr + 1) != '\0')
3039    {
3040       *ptr++ = '\0';
3041       file_name = ptr;
3042    }
3043    else
3044       file_name = ".";
3045
3046    /*
3047     * Get the window title
3048     */
3049    if (restricted_top && file_mgr_data->title)
3050       title = file_mgr_data->title;
3051    else if (strcmp(file_name, ".") != 0)
3052       title = file_name;
3053    else
3054    {
3055       sprintf(title_buf, "%s:%s", home_host_name, root_title);
3056       title = title_buf;
3057    }
3058
3059
3060    screen = XDefaultScreen(display);
3061    currentScreen = XScreenOfDisplay(display, screen);
3062    rootWindow = RootWindowOfScreen(currentScreen);
3063
3064    /* want to get the current workspace so that the window maps
3065       to the right workspace */
3066    if (DtWsmGetCurrentWorkspace(display, rootWindow, &pCurrent) == Success)
3067    {
3068       workspace_name = XGetAtomName (display, pCurrent);
3069       CleanUpWSName(workspace_name);
3070    }
3071    else
3072       workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
3073
3074    desktop_data->event.type = INVALID_TYPE;
3075
3076    ws_num = -1;
3077    /* determine the workspace number */
3078    for(j = 0; j < desktop_data->numWorkspaces; j++)
3079    {
3080       if(strcmp(workspace_name, desktop_data->workspaceData[j]->name) == 0)
3081       {
3082           ws_num = desktop_data->workspaceData[j]->number;
3083           break;
3084       }
3085    }
3086
3087    /* if the workspace number is still -1, it means there are new
3088       workspaces, so lets go initialize them */
3089    if(ws_num == -1)
3090      ws_num = InitializeNewWorkspaces(display, workspace_name);
3091
3092
3093    /* loop through the current objects on the desktop and see if one
3094       with the same name is already in this workspace.  If it is,
3095       don't map the window and put out a warning message telling
3096       the user this */
3097    for(i = 0; i < EndIndex; i++)
3098    {
3099       if (strcmp(desktop_data->desktopWindows[i]->title, title) == 0 &&
3100           strcmp(desktop_data->desktopWindows[i]->workspace_name,
3101                  workspace_name) == 0)
3102       {
3103          char * msg;
3104          char * tmpStr;
3105
3106          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."));
3107          msg = XtNewString(tmpStr);
3108          FileOperationError(file_mgr_rec->main, msg, title);
3109          XtFree(msg);
3110          msg = NULL;
3111          XtFree(workspace_name);
3112          workspace_name = NULL;
3113          XtFree(directory_name);
3114          directory_name = NULL;
3115          return;
3116       }
3117    }
3118
3119    /* get the next available cached iconWindow and use it to map
3120       this topLevelWindow */
3121    desktopWindow = desktop_data->desktopWindows[desktop_data->numIconsUsed];
3122    desktop_data->numIconsUsed++;
3123    desktop_data->numCachedIcons--;
3124
3125    /* store some of the data needed for the Desktop object */
3126    desktopWindow->host = XtNewString(home_host_name);
3127    if( *directory_name == 0x0 )
3128      desktopWindow->dir_linked_to = XtNewString("/");
3129    else
3130      desktopWindow->dir_linked_to = XtNewString(directory_name);
3131    desktopWindow->file_name = XtNewString(file_name);
3132    desktopWindow->title = XtNewString(title);
3133
3134    desktopWindow->workspace_name = workspace_name;
3135    desktopWindow->workspace_num = ws_num;
3136
3137    if (file_mgr_data != NULL)
3138    {
3139        if (file_mgr_data->restricted_directory == NULL)
3140            desktopWindow->restricted_directory = NULL;
3141        else
3142          desktopWindow->restricted_directory =
3143                 XtNewString(file_mgr_data->restricted_directory);
3144
3145       if (file_mgr_data->helpVol == NULL)
3146          desktopWindow->helpVol = NULL;
3147       else
3148          desktopWindow->helpVol = XtNewString(file_mgr_data->helpVol);
3149
3150       desktopWindow->view = file_mgr_data->view;
3151       desktopWindow->order = file_mgr_data->order;
3152       desktopWindow->direction = file_mgr_data->direction;
3153       desktopWindow->positionEnabled = file_mgr_data->positionEnabled;
3154       desktopWindow->toolbox = file_mgr_data->toolbox;
3155    }
3156    else  /* there is no file_mgr_data associated with this file, so it
3157             must be "Put On Desktop" but not from a File Manager View
3158             (i.e. Find File) */
3159    {
3160        /* store the directory the file is linked to */
3161        /* need to determine the toolbox dir !!!*/
3162        if (type == NULL)
3163          desktopWindow->restricted_directory = NULL;
3164        else
3165          desktopWindow->restricted_directory = XtNewString(type);
3166        desktopWindow->helpVol = NULL;
3167        desktopWindow->toolbox = False;
3168        desktopWindow->view = UNSET_VALUE;
3169        desktopWindow->order = UNSET_VALUE;
3170        desktopWindow->direction = UNSET_VALUE;
3171        desktopWindow->positionEnabled = UNSET_VALUE;
3172    }
3173
3174    desktopWindow->file_view_data = BuildNewOrderlist(
3175                           NULL /* @@@ use cached info if possible! */,
3176                           desktopWindow->iconGadget,
3177                           home_host_name,
3178                           desktopWindow->dir_linked_to,
3179                           file_name,
3180                           desktopWindow->registered,
3181                           desktopWindow->toolbox);
3182
3183    MakeDesktopWindow(desktopWindow, root_x, root_y);
3184    desktopWindow->registered = desktopWindow->file_view_data->registered;
3185
3186    /* go cache some more windows if there isn't enough cached */
3187    if (desktop_data->numCachedIcons < 5)
3188       InitializeDesktopWindows(5, display);
3189
3190    /* go save the current state of the desktop */
3191    SaveDesktopInfo(NORMAL_RESTORE);
3192
3193    XtFree(directory_name);
3194    directory_name = NULL;
3195
3196    if(openDirType == NEW)
3197       ForceMyIconOpen(desktopWindow->host, NULL);
3198
3199    if( checkBrokenLink != 0 && checkBrokenLinkTimerId == 0 )
3200    {
3201      checkBrokenLinkTimerId = XtAppAddTimeOut(
3202                    XtWidgetToApplicationContext( toplevel ),
3203                    checkBrokenLink * 1000,
3204                    TimerEventBrokenLinks,
3205                    NULL );
3206    }
3207
3208 }
3209
3210
3211 static void
3212 FreeCachedIcons (
3213      int iconsToBeFreed)
3214 {
3215    int i, new_size;
3216    DesktopRec *desktop;
3217    DesktopRec *tmpDesktop;
3218
3219    new_size = (desktop_data->numCachedIcons + desktop_data->numIconsUsed) -
3220                                                               iconsToBeFreed;
3221    for(i = desktop_data->numCachedIcons + desktop_data->numIconsUsed;
3222                                                          i > new_size; i--)
3223    {
3224       desktop = desktop_data->desktopWindows[i - 1];
3225       if(desktop == sacredDesktop)
3226       {
3227          desktop = desktop_data->desktopWindows[desktop_data->numIconsUsed];
3228          desktop_data->desktopWindows[desktop_data->numIconsUsed] =
3229                                                                  sacredDesktop;
3230       }
3231       XtDestroyWidget(desktop->shell);
3232       XtFree((char *)desktop);
3233       desktop = NULL;
3234
3235       desktop_data->numCachedIcons--;
3236    }
3237    desktop_data->desktopWindows =
3238                (DesktopRec ** )XtRealloc((char *)desktop_data->desktopWindows,
3239                                             sizeof(DesktopRec *) * new_size);
3240 }
3241
3242 static void
3243 CreatePopupMenu (
3244      Widget drawA )
3245 {
3246    Widget popupBtns[15];
3247    XmString label_string;
3248    char * mnemonic;
3249    Arg args[6];
3250    int n;
3251
3252
3253    /*
3254     * WARNING!!!
3255     *
3256     * IF YOU ADD ANY NEW MENU ITEMS TO THE DESKTOP POPUP MENU, THEN YOU
3257     * MUST ALSO ADD A CHECK FOR IT IN DTHelpRequestCB() [in HelpCB.c],
3258     * SINCE THAT FUNCTION HAS A SPECIAL CHECK FOR EACH MENU BUTTON!
3259     */
3260
3261    n = 0;
3262    XtSetArg(args[n], XmNwhichButton, bMenuButton); n++;
3263    desktop_data->popupMenu->popup =
3264                            XmCreatePopupMenu(drawA, "DTPopup", args, n);
3265
3266    XtAddCallback (desktop_data->popupMenu->popup, XmNmapCallback,
3267                                         popupMenu, (XtPointer) NULL);
3268    XtAddCallback (desktop_data->popupMenu->popup, XmNhelpCallback,
3269                   (XtCallbackProc)DTHelpRequestCB,
3270                   HELP_DESKTOP_POPUP_MENU_STR);
3271
3272    label_string = XmStringCreateLocalized((GETMESSAGE(28,4, "Workspace Object")));
3273    XtSetArg (args[0], XmNlabelString, label_string);
3274    popupBtns[0] = (Widget) XmCreateLabelGadget(desktop_data->popupMenu->popup,
3275                                                           "title", args, 1);
3276    popupBtns[1] = XmCreateSeparatorGadget(desktop_data->popupMenu->popup,
3277                                                            "sep1", NULL, 0);
3278    popupBtns[2] = XmCreateSeparatorGadget(desktop_data->popupMenu->popup,
3279                                                            "sep2", NULL, 0);
3280    XmStringFree (label_string);
3281
3282    label_string = XmStringCreateLocalized((GETMESSAGE(28,5, "Remove From Workspace")));
3283    XtSetArg (args[0], XmNlabelString, label_string);
3284    mnemonic = ((char *)GETMESSAGE(28, 6, "R"));
3285    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
3286    desktop_data->popupMenu->removeDT = popupBtns[3] =
3287            XmCreatePushButtonGadget (desktop_data->popupMenu->popup,
3288                                                              "rmDT", args, 2);
3289    XmStringFree (label_string);
3290    XtAddCallback (desktop_data->popupMenu->removeDT, XmNhelpCallback,
3291                   (XtCallbackProc)DTHelpRequestCB,
3292                   HELP_DESKTOP_POPUP_MENU_STR);
3293
3294
3295    label_string = XmStringCreateLocalized ((GETMESSAGE(28,7, "Open Parent Folder")));
3296    XtSetArg (args[0], XmNlabelString, label_string);
3297    mnemonic = ((char *)GETMESSAGE(28, 8, "O"));
3298    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
3299    desktop_data->popupMenu->openFolder = popupBtns[4] =
3300             XmCreatePushButtonGadget (desktop_data->popupMenu->popup,
3301                                                              "info", args, 2);
3302    XmStringFree (label_string);
3303    XtAddCallback (desktop_data->popupMenu->openFolder, XmNhelpCallback,
3304                   (XtCallbackProc)DTHelpRequestCB,
3305                   HELP_DESKTOP_POPUP_MENU_STR);
3306
3307    label_string = XmStringCreateLocalized ((GETMESSAGE(20,128, "Rename")));
3308    XtSetArg (args[0], XmNlabelString, label_string);
3309    mnemonic = ((char *)GETMESSAGE(20, 129, "n"));
3310    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
3311    desktop_data->popupMenu->rename = popupBtns[5] =
3312             XmCreatePushButtonGadget (desktop_data->popupMenu->popup,
3313                                                             "rename", args, 2);
3314    XmStringFree (label_string);
3315    XtAddCallback (desktop_data->popupMenu->rename, XmNhelpCallback,
3316                   (XtCallbackProc)DTHelpRequestCB,
3317                   HELP_DESKTOP_POPUP_MENU_STR);
3318
3319    popupBtns[6] = XmCreateSeparatorGadget(desktop_data->popupMenu->popup,
3320                                                           "sep1", NULL, 0);
3321
3322    XtManageChildren(popupBtns, 7);
3323 }
3324
3325 static void
3326 popupMenu (
3327      Widget w,
3328      XtPointer client_data,
3329      XtPointer call_data)
3330 {
3331    Widget shell;
3332    Boolean found = False;
3333    int i;
3334    XmAnyCallbackStruct * callback;
3335    XEvent * event;
3336
3337    callback = (XmAnyCallbackStruct *) call_data;
3338    event = (XEvent *) callback->event;
3339
3340    shell = XmGetPostedFromWidget(w);
3341    for(i = 0; i < desktop_data->numIconsUsed; i++)
3342    {
3343       if(desktop_data->desktopWindows[i]->shell == shell ||
3344                       desktop_data->desktopWindows[i]->drawA == shell)
3345       {
3346          found = True;
3347          break;
3348       }
3349    }
3350    if(found)
3351    {
3352       DrawAInput(desktop_data->popupMenu->popup,
3353                  (XtPointer)desktop_data->desktopWindows[i],
3354                  event, (Boolean *)NULL);
3355    }
3356 }
3357
3358
3359 #ifdef SHAPE
3360 void
3361 GenerateShape(
3362       DesktopRec *desktopWindow)
3363 {
3364    Dimension shadowThickness, highlightThickness;
3365    Dimension pixmapWidth, pixmapHeight;
3366    Dimension stringWidth, stringHeight;
3367    XRectangle rect[2];
3368    unsigned char flags;
3369    unsigned char pixmapPosition;
3370    unsigned char alignment;
3371    Arg args[4];
3372    DtIconGadget g;
3373
3374    if(!shapeExtension)
3375       return;
3376
3377    XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
3378    XtSetArg (args[1], XmNhighlightThickness, &highlightThickness);
3379    XtSetArg (args[2], XmNpixmapPosition, &pixmapPosition);
3380    XtSetArg (args[3], XmNalignment, &alignment);
3381    XtGetValues (desktopWindow->iconGadget, args, 4);
3382
3383    g = (DtIconGadget)desktopWindow->iconGadget;
3384    pixmapWidth = g->icon.pixmap_width;
3385    pixmapHeight = g->icon.pixmap_height;
3386    stringWidth = g->icon.string_width;
3387    stringHeight = g->icon.cache->string_height;
3388
3389    _DtIconGetIconRects((DtIconGadget)desktopWindow->iconGadget,
3390                                                 &flags, &rect[0], &rect[1]);
3391
3392    switch ((int) pixmapPosition)
3393    {
3394       case XmPIXMAP_TOP:
3395         if(alignment != XmALIGNMENT_CENTER)
3396         {
3397            /* 1 */
3398             rect[0].x += 1;
3399             rect[0].y += 1;
3400             rect[0].width += 2*shadowThickness;
3401             rect[0].height += 2*shadowThickness;
3402
3403            /* 2 */
3404             rect[1].x += 1;
3405             rect[1].y += 1;
3406             rect[1].width += 2*shadowThickness;
3407             rect[1].height += 2*shadowThickness;
3408
3409             if(rect[0].width > rect[1].width)
3410                rect[1].width = rect[0].width;
3411          }
3412          else /* is XmALIGNMENT_CENTER */
3413          {
3414             if(stringWidth > pixmapWidth)
3415             {
3416               /* 1 */
3417                rect[0].x += 1;
3418                rect[0].y += 1;
3419                rect[0].width += 2*shadowThickness;
3420                rect[0].height += 2*shadowThickness;
3421
3422               /* 2 */
3423                rect[1].x += 1;
3424                rect[1].y += 1;
3425                rect[1].width += 2*shadowThickness;
3426                rect[1].height += 2*shadowThickness;
3427
3428                if(rect[0].width > rect[1].width)
3429                   rect[1].width = rect[0].width;
3430             }
3431             else
3432             {
3433              /* 1 */
3434                rect[0].x += 1;
3435                rect[0].y += 1;
3436                rect[0].width += 2*shadowThickness;
3437                rect[0].height += 2*shadowThickness;
3438
3439               /* 2 */
3440                rect[1].x = rect[0].x;
3441                rect[1].y += 1;
3442                rect[1].width = rect[0].width;
3443                rect[1].height += 2*shadowThickness;
3444             }
3445          }
3446
3447          break;
3448       case XmPIXMAP_LEFT:
3449          if((Dimension)(stringHeight+5) >= pixmapHeight)
3450          {
3451             if(pixmapHeight == 0)
3452             {
3453               /* 1 */
3454                rect[0].x = 0;
3455                rect[0].y = 0;
3456                rect[0].width = 0;
3457                rect[0].height = 0;
3458
3459                rect[1].x += 1;
3460                rect[1].y += 1;
3461                rect[1].width += 2*shadowThickness;
3462                rect[1].height += 2*shadowThickness;
3463             }
3464             else
3465             {
3466               /* 2 */
3467                rect[1].y = rect[0].y + 1;
3468                rect[1].x += 1;
3469                rect[1].width += 2*shadowThickness;
3470                if(pixmapHeight > stringHeight)
3471                   rect[1].height += 2*shadowThickness +
3472                                        (pixmapHeight - stringHeight);
3473                else
3474                   rect[1].height += 2*shadowThickness;
3475
3476               /* 1 */
3477                rect[0].x += 1;
3478                rect[0].y = rect[1].y;
3479                rect[0].width += shadowThickness;
3480                rect[0].height = rect[1].height;
3481             }
3482          }
3483          else
3484          {
3485            /* 1 */
3486             rect[0].x += 1;
3487             rect[0].y += 1;
3488             rect[0].width += 2*shadowThickness;
3489             rect[0].height += 2*shadowThickness;
3490
3491            /* 2 */
3492             rect[1].x += 1;
3493             rect[1].y += 1;
3494             rect[1].width += 2*shadowThickness;
3495             rect[1].height += 2*shadowThickness;
3496          }
3497          break;
3498    }
3499
3500    XShapeCombineRectangles(XtDisplay(desktopWindow->shell),
3501                            XtWindow(desktopWindow->shell),
3502                            ShapeBounding, 0, 0, &rect[0], 2,
3503                            ShapeSet, Unsorted);
3504 }
3505 #endif
3506
3507 static void
3508 BuildDesktopLinks (
3509        Display *display)
3510 {
3511    struct stat statBuf;
3512    Atom     *paWS;
3513    int       numInfo;
3514    Window   rootWindow;
3515    Screen   *currentScreen;
3516    int      i, screen, result;
3517    int      retry;
3518
3519    /* Build the 'Desktop' directory */
3520    desktop_dir = XtMalloc(strlen(users_home_dir) + strlen(DESKTOP_DIR) + 2);
3521    sprintf(desktop_dir, "%s%s", users_home_dir, DESKTOP_DIR);
3522    if (stat(desktop_dir, &statBuf) < 0)
3523       mkdir(desktop_dir, S_IRUSR|S_IWUSR|S_IXUSR);
3524
3525    /* Now build the list of workspaces */
3526    screen = XDefaultScreen(display);
3527    currentScreen = XScreenOfDisplay(display, screen);
3528    rootWindow = RootWindowOfScreen(currentScreen);
3529
3530    retry = retryLoadDesktopInfo;
3531    if (retry <= 0)
3532      retry = 1;
3533
3534    while (retry > 0)
3535    {
3536       result = DtWsmGetWorkspaceList (display, rootWindow, &paWS, &numInfo);
3537       if (result == Success)
3538       {
3539          desktop_data->numWorkspaces = (int)numInfo;
3540          break;
3541       }
3542       else
3543       {
3544          desktop_data->numWorkspaces = 1;
3545          sleep(2);
3546          retry--;
3547       }
3548    }
3549
3550    desktop_data->workspaceData = (WorkspaceRec **)
3551                XtMalloc(sizeof(WorkspaceRec *) * desktop_data->numWorkspaces);
3552    for (i=0; i < desktop_data->numWorkspaces; i++)
3553    {
3554       WorkspaceRec *workspaceData;
3555
3556       workspaceData = (WorkspaceRec *)XtMalloc(sizeof(WorkspaceRec));
3557
3558       if(result == Success)
3559       {
3560          workspaceData->name = XGetAtomName (display, paWS[i]);
3561          CleanUpWSName(workspaceData->name);
3562       }
3563       else
3564          workspaceData->name = XtNewString("One");
3565       workspaceData->number = i + 1;
3566       workspaceData->files_selected = 0;
3567       workspaceData->selectedDTWindows =
3568                          (DesktopRec **) XtMalloc (sizeof (DesktopRec *));
3569       workspaceData->selectedDTWindows[0] = NULL;
3570       workspaceData->primaryHelpDialog = NULL;
3571       workspaceData->secondaryHelpDialogCount = 0;
3572       workspaceData->secondaryHelpDialogList = NULL;
3573
3574       desktop_data->workspaceData[i] = workspaceData;
3575    }
3576
3577    if (result == Success)
3578    {
3579       XFree ((char *) paWS);
3580       paWS = NULL;
3581    }
3582 }
3583
3584 static int
3585 InitializeNewWorkspaces (
3586        Display *display,
3587        char *workspaceName)
3588 {
3589    struct stat statBuf;
3590    Atom     *paWS;
3591    int       numInfo;
3592    Window   rootWindow;
3593    Screen   *currentScreen;
3594    int      i, j, k, screen;
3595    Boolean  haveIt;
3596
3597    /* Now build the directories for each desktop (i.e. workspace) */
3598    screen = XDefaultScreen(display);
3599    currentScreen = XScreenOfDisplay(display, screen);
3600    rootWindow = RootWindowOfScreen(currentScreen);
3601
3602    if (DtWsmGetWorkspaceList (display, rootWindow, &paWS, &numInfo) == Success)
3603    {
3604       if(numInfo <= desktop_data->numWorkspaces)
3605       {
3606          /* should never get here, just put the new object in ws 0 */
3607          return(0);
3608       }
3609
3610       /* go realloc room for the workspace Data */
3611       desktop_data->workspaceData = (WorkspaceRec **) XtRealloc(
3612                                (char *)desktop_data->workspaceData,
3613                                sizeof(WorkspaceRec *) * numInfo);
3614
3615       /* now initialize the new workspaces */
3616       for(i=0; i < numInfo - desktop_data->numWorkspaces; i++)
3617       {
3618          WorkspaceRec *workspaceData;
3619
3620          workspaceData = (WorkspaceRec *)XtMalloc(sizeof(WorkspaceRec));
3621
3622          for(j=0; j < numInfo; j++)
3623          {
3624             workspaceData->name = XGetAtomName (display, paWS[j]);
3625             CleanUpWSName(workspaceData->name);
3626             haveIt = False;
3627             for(k=0; k<desktop_data->numWorkspaces; k++)
3628             {
3629                if(strcmp(workspaceData->name,
3630                             desktop_data->workspaceData[k]->name) == 0)
3631                {
3632                   haveIt = True;
3633                   break;
3634                }
3635             }
3636             if(!haveIt)
3637                break;
3638          }
3639
3640          workspaceData->number = desktop_data->numWorkspaces + i + 1;
3641          workspaceData->files_selected = 0;
3642          workspaceData->selectedDTWindows =
3643                             (DesktopRec **) XtMalloc (sizeof (DesktopRec *));
3644          workspaceData->selectedDTWindows[0] = NULL;
3645          workspaceData->primaryHelpDialog = NULL;
3646          workspaceData->secondaryHelpDialogCount = 0;
3647          workspaceData->secondaryHelpDialogList = NULL;
3648
3649          desktop_data->workspaceData[desktop_data->numWorkspaces + i] =
3650                                                                workspaceData;
3651       }
3652       XFree ((char *) paWS);
3653       paWS = NULL;
3654    }
3655
3656    /* now lets add more desktop grids for the new workspaces */
3657
3658    desktop_grid_size = numInfo * numColumns * numRows;
3659    desktop_grid = (Boolean *)XtRealloc((char *)desktop_grid,desktop_grid_size);
3660    for(i = desktop_data->numWorkspaces; i < numInfo; i++)
3661    {
3662       for(j = 0; j < numColumns; j++)
3663          for(k = 0; k < numRows; k++)
3664             desktop_grid[(i * numRows * numColumns) +
3665                                            (j * numRows) + k] = 0;
3666
3667       RegisterPanelInGrid( i + 1,
3668                            DisplayWidth(display,screen),
3669                            DisplayHeight(display, screen));
3670
3671    }
3672    desktop_data->numWorkspaces = numInfo;
3673
3674    /* now determine which workspace the new object is in */
3675    for(j = 0; j < desktop_data->numWorkspaces; j++)
3676    {
3677       if(strcmp(workspaceName, desktop_data->workspaceData[j]->name) == 0)
3678           return(desktop_data->workspaceData[j]->number);
3679    }
3680
3681    /* should never get here */
3682    return(0);
3683 }
3684
3685 /************************************************************************
3686  *
3687  *  TimerEvent
3688  *      This function is called when dtfile does an _DtActionInvoke. All
3689  *      it does is turn off the Hourglass cursor.
3690  *
3691  ************************************************************************/
3692
3693 static void
3694 TimerEvent(
3695         Widget widget,
3696         XtIntervalId *id )
3697 {
3698   _DtTurnOffHourGlass (widget);
3699 }
3700
3701
3702 /**********************************************************************
3703  *
3704  * CleanUpWSName - routine which makes sure there are no spaces, "/",
3705  *     "'", and ":" in a workspace name. If there are it changes them to
3706  *     "_".
3707  *
3708  *********************************************************************/
3709 void
3710 CleanUpWSName(
3711        char *workspace_name)
3712 {
3713    char *ptr;
3714
3715    /* the workspace name could be something other than "One" "Two" etc.
3716        if the user has change his/her xrdb.  Need to check for characters
3717        in the name which will break us.
3718       First check " "
3719    */
3720    ptr = DtStrchr(workspace_name, ' ');
3721    while(ptr != NULL)
3722    {
3723       *ptr = '_';
3724       ptr = DtStrchr(ptr, ' ');
3725    }
3726
3727    /*
3728      Next check "/"
3729    */
3730    ptr = DtStrchr(workspace_name, '/');
3731    while(ptr != NULL)
3732    {
3733       *ptr = '_';
3734       ptr = DtStrchr(ptr, '/');
3735    }
3736
3737    /*
3738      Next check ":"
3739    */
3740    ptr = DtStrchr(workspace_name, ':');
3741    while(ptr != NULL)
3742    {
3743       *ptr = '_';
3744       ptr = DtStrchr(ptr, ':');
3745    }
3746
3747    /*
3748      Next check "'"
3749    */
3750    ptr = DtStrchr(workspace_name, '\'');
3751    while(ptr != NULL)
3752    {
3753       *ptr = '_';
3754       ptr = DtStrchr(ptr, '\'');
3755    }
3756 }
3757
3758
3759 /**********************************************************************
3760  *
3761  *  CheckDesktoMarquee - given a x, y, width, and height determine
3762  *        whether a desktop objects pixmap falls within the bounded
3763  *        region.  If it does select it. If it is selected and no
3764  *        longer is in the bounded region, deslect it.
3765  *
3766  ***********************************************************************/
3767 void
3768 CheckDesktopMarquee(
3769    int x,
3770    int y,
3771    int width,
3772    int height)
3773 {
3774    int i, j;
3775    Window   rootWindow;
3776    Atom     pCurrent;
3777    Screen   *currentScreen;
3778    int      screen;
3779    char     *workspace_name;
3780    Dimension shadowThickness;
3781    XRectangle pixmapRect;
3782    XRectangle labelRect;
3783    XRectangle incoming_rect;
3784    unsigned char pixmapPosition;
3785    DtIconGadget g;
3786    WorkspaceRec *workspaceData = NULL;
3787    unsigned char flags;
3788    Region region;
3789    Display *display;
3790    Boolean match;
3791    Boolean pointInRegion;
3792
3793    if(desktop_data->numIconsUsed <= 0)
3794       return;
3795
3796    /* Create a region with the incoming x, y, width, and height */
3797    incoming_rect.x = (short)x;
3798    incoming_rect.y = (short)y;
3799    incoming_rect.width = (unsigned short)width;
3800    incoming_rect.height = (unsigned short)height;
3801    region = XCreateRegion();
3802    XUnionRectWithRegion (&incoming_rect, region, region);
3803
3804    /* Get the current workspace */
3805    display = XtDisplay(desktop_data->desktopWindows[0]->shell);
3806    screen = XDefaultScreen(display);
3807    currentScreen = XScreenOfDisplay(display, screen);
3808    rootWindow = RootWindowOfScreen(currentScreen);
3809
3810    if(DtWsmGetCurrentWorkspace(display, rootWindow, &pCurrent) == Success)
3811    {
3812       workspace_name = XGetAtomName (display, pCurrent);
3813       CleanUpWSName(workspace_name);
3814    }
3815    else
3816       workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
3817
3818    for(i = 0; i < desktop_data->numWorkspaces; i++)
3819    {
3820       if(strcmp(workspace_name, desktop_data->workspaceData[i]->name) == 0)
3821       {
3822          workspaceData = desktop_data->workspaceData[i];
3823          break;
3824       }
3825    }
3826
3827    /* This shouldn't happen, but... */
3828    if (!workspaceData)
3829    {
3830        fprintf(stderr, "%s: workspaceData == NULL!\n", __FUNCTION__);
3831        return;
3832    }
3833
3834    /* now lets loop through the icons used, first check to see if they are
3835     * in the same workspace. If not continue else we need to check to see
3836     * if they are in the region passed in.
3837     */
3838    for(i = 0; i < desktop_data->numIconsUsed; i++)
3839    {
3840       if(strcmp(desktop_data->desktopWindows[i]->workspace_name,
3841                                                   workspace_name) != 0)
3842          continue;
3843
3844       /* first we need to get the pixmap region for the desktop object */
3845       g = (DtIconGadget)desktop_data->desktopWindows[i]->iconGadget;
3846       shadowThickness = g->gadget.shadow_thickness;
3847       pixmapPosition = g->icon.cache->pixmap_position;
3848
3849       _DtIconGetIconRects((DtIconGadget)g, &flags, &pixmapRect, &labelRect);
3850
3851       switch ((int) pixmapPosition)
3852       {
3853          case XmPIXMAP_TOP:  /* 0 */
3854          case XmPIXMAP_LEFT: /* 2 */
3855             if( flags & XmPIXMAP_RECT )
3856             {
3857               pixmapRect.x = pixmapRect.x + desktop_data->desktopWindows[i]->root_x + 1;
3858               pixmapRect.y = pixmapRect.y + desktop_data->desktopWindows[i]->root_y + 1;
3859               pixmapRect.width += 2*shadowThickness;
3860               pixmapRect.height += 2*shadowThickness;
3861
3862               /* now lets check to see if the upper left and lower right corners
3863                * of the pixmap falls within the passed in region
3864                */
3865               pointInRegion = (XPointInRegion(region, pixmapRect.x, pixmapRect.y) &&
3866                                XPointInRegion(region, pixmapRect.x + pixmapRect.width,
3867                                               pixmapRect.y + pixmapRect.height));
3868             }
3869             else if( flags & XmLABEL_RECT )
3870             { /* For the ones that don't have pixmap */
3871               labelRect.x = labelRect.x + desktop_data->desktopWindows[i]->root_x + 1;
3872               labelRect.y = labelRect.y + desktop_data->desktopWindows[i]->root_y + 1;
3873               labelRect.width += 2*shadowThickness;
3874               labelRect.height += 2*shadowThickness;
3875
3876               /* now lets check to see if the upper left and lower right corners
3877                * of the pixmap falls within the passed in region
3878                */
3879               pointInRegion = (XPointInRegion(region, labelRect.x, labelRect.y) &&
3880                                XPointInRegion(region, labelRect.x + labelRect.width,
3881                                               labelRect.y + labelRect.height));
3882             }
3883             else
3884               pointInRegion = False;
3885
3886             if( pointInRegion )
3887             {
3888                /* it falls within the region, lets see if its already
3889                 * selected.
3890                 */
3891                match = False;
3892                for(j = 0; j < workspaceData->files_selected; j++)
3893                {
3894                   if(workspaceData->selectedDTWindows[j] ==
3895                                             desktop_data->desktopWindows[i])
3896                   {
3897                      match = True;
3898                      break;
3899                   }
3900                }
3901
3902                if(match)
3903                   continue;
3904
3905                /* its not already selected, so lets select it ... */
3906                workspaceData->files_selected++;
3907
3908                workspaceData->selectedDTWindows =
3909                      (DesktopRec **) XtRealloc ((char *)
3910                                   workspaceData->selectedDTWindows,
3911                                   sizeof(DesktopRec *) *
3912                                   (workspaceData->files_selected + 2));
3913
3914                /* Add to the front of the list */
3915                for (j = workspaceData->files_selected; j > 0; j--)
3916                {
3917                   workspaceData->selectedDTWindows[j] =
3918                                    workspaceData->selectedDTWindows[j-1];
3919                }
3920
3921                workspaceData->selectedDTWindows[0] =
3922                                        desktop_data->desktopWindows[i];
3923                SetToSelectColors ((Widget)g,
3924                                  desktop_data->desktopWindows[i]->frame,
3925                                  LINK_FILE);
3926                XSync(display, False);
3927             }
3928             else
3929             {
3930                /* its pixmap is not it the region so lets see if it is
3931                 * selected.  If it is lets deslect it.
3932                 */
3933                for(j = 0; j < workspaceData->files_selected; j++)
3934                {
3935                   if(workspaceData->selectedDTWindows[j] ==
3936                                               desktop_data->desktopWindows[i])
3937                   {
3938                      DeselectDTFile (workspaceData,
3939                                           desktop_data->desktopWindows[i]);
3940                      XSync(display, False);
3941                      break;
3942                   }
3943                }
3944             }
3945             break;
3946       }
3947    }
3948    XDestroyRegion (region);
3949    XtFree(workspace_name);
3950 }
3951
3952
3953 static void
3954 ProcessDropOnDesktopObject (
3955      Widget w,
3956      DtDndDropCallbackStruct *dropInfo,
3957      DesktopRec *desktopWindow)
3958 {
3959    char *command = NULL;
3960
3961    /******************/
3962    /* transfer phase */
3963    /******************/
3964    if (dropInfo->reason != DtCR_DND_DROP_ANIMATE)
3965    {
3966       DPRINTF(("DropOnObject: Transfer Callback\n"));
3967
3968       /* In case when the drag is from non File Manager client */
3969       if(!dragActive)
3970         initiating_view = NULL;
3971
3972       /* check for invalid trash drop */
3973       if (FileFromTrash(dropInfo->dropData->data.files[0]))
3974       {
3975          if (InvalidTrashDragDrop(dropInfo->operation,
3976                FROM_TRASH,
3977                desktopWindow->shell))
3978          {
3979             dropInfo->status = DtDND_FAILURE;
3980             return;
3981          }
3982       }
3983
3984       command = TypeToAction(dropInfo->operation,
3985                              desktopWindow->file_view_data->file_data->logical_type);
3986       if(command &&
3987          (strncmp("FILESYSTEM_", command, strlen("FILESYSTEM_")) != 0) &&
3988          dropInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
3989           dropInfo->completeMove = True;
3990       else
3991           /* set the complete move flag to False since we will be handling */
3992           /* the deletion of the original file                             */
3993           dropInfo->completeMove = False;
3994    }
3995
3996    /******************************************/
3997    /* animate phase, retrieve action and run */
3998    /******************************************/
3999    else
4000    {
4001       command =
4002         TypeToAction(dropInfo->operation,
4003                      desktopWindow->file_view_data->file_data->logical_type);
4004       if (command)
4005       {
4006          RunDTCommand (command,
4007                        desktopWindow,
4008                        dropInfo);
4009          DtDtsFreeAttributeValue(command);
4010       }
4011    }
4012 }
4013
4014
4015 static void
4016 DropOnDesktopObject (
4017      Widget w,
4018      XtPointer client_data,
4019      XtPointer call_data)
4020 {
4021    DtDndDropCallbackStruct *dropInfo = (DtDndDropCallbackStruct *)call_data;
4022
4023    switch (dropInfo -> dropData->protocol)
4024      {
4025        case DtDND_FILENAME_TRANSFER:
4026        case DtDND_BUFFER_TRANSFER:
4027          ProcessDropOnDesktopObject (w, dropInfo, (DesktopRec *) client_data);
4028          break;
4029        default :
4030          dropInfo->status = DtDND_FAILURE;
4031      } /* endswitch */
4032 }
4033
4034 void
4035 WorkSpaceRemoved (
4036      Widget w,
4037      Atom deleted_ws_atom,
4038      int type,
4039      XtPointer client_data)
4040 {
4041   Display  *display;
4042   Window   rootWindow;
4043   Atom     pCurrent;
4044   Screen   *currentScreen;
4045   int      screen;
4046   char     *workspace_name,*old_workspace_name;
4047   Atom     *paWS;
4048   int      numInfo,oldNumWorkspaces,old_ws_num,ws_num;
4049   int      i,j,k,retry,result,old_index,new_index;
4050
4051   display = XtDisplay(w);
4052   screen = XDefaultScreen(display);
4053   currentScreen = XScreenOfDisplay(display, screen);
4054   rootWindow = RootWindowOfScreen(currentScreen);
4055   oldNumWorkspaces = desktop_data->numWorkspaces;
4056
4057   old_workspace_name = XGetAtomName (display, deleted_ws_atom);
4058
4059   if( type == DtWSM_MODIFY_WORKSPACE_TYPE_DELETE )
4060   {
4061     retry = retryLoadDesktopInfo;
4062     if (retry <= 0)
4063       retry = 1;
4064     /* Get total new number of workspaces */
4065     while (retry > 0)
4066     {
4067        result = DtWsmGetWorkspaceList (display, rootWindow, &paWS, &numInfo);
4068        if (result == Success)
4069        {
4070           desktop_data->numWorkspaces = (int)numInfo;
4071           break;
4072        }
4073        else
4074        {
4075           desktop_data->numWorkspaces = 1;
4076           sleep(2);
4077           retry--;
4078        }
4079     }
4080     /* Get the current workspace */
4081     if(DtWsmGetCurrentWorkspace(display,rootWindow,&pCurrent) == Success)
4082     {
4083        workspace_name = XGetAtomName (display, pCurrent);
4084        CleanUpWSName(workspace_name);
4085     }
4086     else
4087        workspace_name = XtNewString(desktop_data->workspaceData[0]->name);
4088
4089     /* determine the workspaces number of deleted and current*/
4090     old_ws_num = GetWorkspaceNum(old_workspace_name,oldNumWorkspaces,&old_index);
4091     ws_num = GetWorkspaceNum(workspace_name,oldNumWorkspaces,&new_index);
4092
4093     /* Free up or reassign any workspace data in the deleted workspace */
4094     FreeUpOldWorkspace(oldNumWorkspaces,old_ws_num,ws_num,old_index,new_index);
4095
4096     /* Look up for the duplication of workspace objects in the new workspace */
4097     for(i=0;i<desktop_data->numIconsUsed;i++)
4098     {    /* Those objects whose workspace number matches the deleted workspace number */
4099        if (desktop_data->desktopWindows[i]->workspace_num == old_ws_num)
4100        {  /* Look up in all of the workspace objects */
4101          for(j=0;j<desktop_data->numIconsUsed;j++)
4102          {  /* Those objects in the current workspace */
4103            if (j!= i && desktop_data->desktopWindows[j]->workspace_num == ws_num)
4104            {
4105              /* If there is an object matching the old workspace object delete the old */
4106              if(strcmp(desktop_data->desktopWindows[j]->file_name,desktop_data
4107                ->desktopWindows[i]->file_name) == 0)
4108              {
4109                ws_num = GetWorkspaceNum(workspace_name,desktop_data->
4110                              numWorkspaces, &new_index);
4111                for(k=0;
4112                  k<desktop_data->workspaceData[new_index]->files_selected;k++)
4113                {
4114                 /* Adjust the selectedDTWindows of current to accommadate the old list */
4115                   if(desktop_data->workspaceData[new_index]->
4116                        selectedDTWindows[k] == desktop_data->desktopWindows[i])
4117                   {
4118                     desktop_data->workspaceData[new_index]->
4119                                         selectedDTWindows[k] = NULL;
4120                     for(;k<desktop_data->workspaceData[new_index]->files_selected;k++)
4121                       desktop_data->workspaceData[new_index]->
4122                        selectedDTWindows[k] = desktop_data->
4123                           workspaceData[new_index]-> selectedDTWindows[k+1];
4124                       desktop_data->workspaceData[new_index]->files_selected--;
4125                     break;
4126                   }
4127                }
4128                XtPopdown(desktop_data->desktopWindows[i]->shell);
4129                XWithdrawWindow(XtDisplay(desktop_data->desktopWindows[i]->shell),
4130                       XtWindow(desktop_data->desktopWindows[i]->shell),
4131                       XDefaultScreen(XtDisplay(desktop_data->desktopWindows[i]->shell)));
4132                FreeDesktopWindow(desktop_data->desktopWindows[i]);
4133                i--;  /* To make sure that other icons are also covered */
4134                break;
4135              }
4136            }
4137          }
4138          if(j == desktop_data->numIconsUsed)
4139          {
4140            desktop_data->desktopWindows[i]->workspace_num  = ws_num;
4141            XtFree(desktop_data->desktopWindows[i]->workspace_name);
4142            desktop_data->desktopWindows[i]->workspace_name = NULL;
4143            desktop_data->desktopWindows[i]->workspace_name =
4144                                       XtNewString(workspace_name);
4145          }
4146        }
4147     }
4148   }
4149   else if( type == DtWSM_MODIFY_WORKSPACE_TYPE_ADD )
4150   {
4151      InitializeNewWorkspaces(display, old_workspace_name);
4152   }
4153   XFree(old_workspace_name);
4154 }
4155
4156 static int
4157 GetWorkspaceNum(char *workspace_name,
4158                 int NumWorkspaces,
4159                 int  *workspace_index)
4160 {
4161   int j;
4162   int ws_num = -1;
4163   for(j = 0; j < NumWorkspaces; j++)
4164   {
4165     if(strcmp(workspace_name, desktop_data->workspaceData[j]->name) == 0)
4166     {
4167         ws_num = desktop_data->workspaceData[j]->number;
4168         break;
4169     }
4170   }
4171   *workspace_index = (j == NumWorkspaces)?-1:j;
4172   return ws_num;
4173 }
4174 static void
4175 FreeUpOldWorkspace(
4176    int oldNumWorkspaces,
4177    int old_ws_num,
4178    int ws_num,
4179    int  old_index,
4180    int  new_index)
4181 {
4182    int j,numnewfiles,numoldfiles;
4183
4184    if(old_ws_num==-1 || old_index==-1 ||
4185       desktop_data->workspaceData[old_index]==NULL) /* Something  is wrong */
4186      return;
4187    numnewfiles = desktop_data->workspaceData[new_index]->files_selected;
4188    numoldfiles = desktop_data->workspaceData[old_index]->files_selected;
4189    if(numoldfiles)
4190    {
4191      desktop_data->workspaceData[new_index]->selectedDTWindows=(DesktopRec **)
4192       XtRealloc((XtPointer) desktop_data->workspaceData[new_index]->selectedDTWindows,
4193           sizeof(DesktopRec *) * ( numnewfiles+numoldfiles));
4194      for(j=numnewfiles;j< numnewfiles+numoldfiles;j++)
4195      {
4196        desktop_data->workspaceData[new_index]->selectedDTWindows[j] =
4197       desktop_data->workspaceData[old_index]->selectedDTWindows[j-numnewfiles];
4198      }
4199      XtFree((XtPointer) desktop_data->workspaceData[old_index]->selectedDTWindows);
4200       desktop_data->workspaceData[old_index]->selectedDTWindows = NULL;
4201      desktop_data->workspaceData[new_index]->files_selected = numnewfiles+numoldfiles;
4202    }
4203
4204    numnewfiles=desktop_data->workspaceData[new_index]->secondaryHelpDialogCount;
4205    numoldfiles=desktop_data->workspaceData[old_index]->secondaryHelpDialogCount;
4206    if(numoldfiles)
4207    {
4208      desktop_data->workspaceData[new_index]->secondaryHelpDialogList=
4209       (DialogData **) XtRealloc((XtPointer) desktop_data->workspaceData[old_index]->
4210     secondaryHelpDialogList,sizeof(DialogData *) * ( numnewfiles+numoldfiles));
4211      for(j=numnewfiles;j< numnewfiles+numoldfiles;j++)
4212      {
4213       desktop_data->workspaceData[new_index]->secondaryHelpDialogList[j] =
4214       desktop_data->workspaceData[old_index]->secondaryHelpDialogList[j-ws_num];
4215      }
4216      desktop_data->workspaceData[new_index]->secondaryHelpDialogCount = numnewfiles+numoldfiles;
4217    }
4218    /* Move up the workspaceData */
4219    XtFree((XtPointer) desktop_data->workspaceData[old_index]);
4220     desktop_data->workspaceData[old_index] = NULL;
4221    for(j=old_index; j<desktop_data->numWorkspaces;j++)
4222       desktop_data->workspaceData[j] = desktop_data->workspaceData[j+1];
4223    desktop_data->workspaceData[j] = NULL;
4224 }
4225 /************************************************************************
4226  *
4227  ************************************************************************/
4228
4229 void
4230 PutOnWorkspaceHandler(
4231    Tt_message ttMsg)
4232 {
4233   DesktopRec * desktopWindow;
4234   struct stat fileInfo;
4235   char title[256], invalidWorkspace = 0x0;
4236   int numArgs, i, screen, ws;
4237   char * fullName, * fileName = NULL, * dirName = NULL, * workspace = NULL;
4238   char * requestWorkspace = NULL;
4239
4240   fullName = tt_message_file( ttMsg );
4241
4242   if( tt_is_err( tt_ptr_error( fullName ) ) )
4243   { /* No file name */
4244     tt_message_reply( ttMsg );
4245     tttk_message_destroy( ttMsg );
4246     return;
4247   }
4248
4249   if (NULL != fullName) DtEliminateDots( fullName );
4250
4251   if(NULL==fullName ||
4252      (stat(fullName, &fileInfo) != 0 && lstat(fullName, &fileInfo) != 0))
4253   {
4254     char *template, *errorMsg, *dialogTitle, *errorName;
4255
4256     /* File does not exist */
4257     tt_message_reply(ttMsg);
4258     tttk_message_destroy(ttMsg);
4259
4260     dialogTitle = XtNewString(GETMESSAGE(20, 84, "Put in Workspace"));
4261
4262     template = XtNewString(
4263                 GETMESSAGE(
4264                   28, 13,
4265                   "Object:\n\n   %s\n\ndoes not exist in the file system."));
4266     if (NULL == fullName)
4267       errorName = "";
4268     else
4269       errorName = fullName;
4270     errorMsg = (char *) XtMalloc(strlen(template) + strlen(errorName) + 1);
4271     sprintf(errorMsg, template, errorName);
4272     _DtMessage(toplevel, dialogTitle, errorMsg, NULL, HelpRequestCB);
4273
4274     XtFree(template);
4275     XtFree(errorMsg);
4276     if (NULL != fullName) tt_free(fullName);
4277     return;
4278   }
4279
4280   numArgs = tt_message_args_count( ttMsg );
4281   if( tt_is_err( tt_int_error( numArgs ) ) )
4282     numArgs = 0;
4283
4284   if( numArgs == 0 )
4285   { /* No argument */
4286     tt_message_reply( ttMsg );
4287     tttk_message_destroy( ttMsg );
4288     return;
4289   }
4290
4291   for( i = 0; i < numArgs; ++i )
4292   {
4293     char * vtype;
4294
4295     vtype = tt_message_arg_type( ttMsg, i );
4296
4297     if( (vtype == 0)
4298         || (tt_is_err( tt_ptr_error( vtype ))) )
4299       continue;
4300
4301     if( strcmp( vtype, "-workspace" ) == 0 )
4302     {
4303       requestWorkspace = tt_message_arg_val( ttMsg, i );
4304     }
4305     tt_free( vtype );
4306   }
4307
4308   /* separate the rest of the path into directory and file name */
4309   if( strcmp( fullName, "/" ) == 0 )
4310   {
4311     sprintf( title, "%s:%s", home_host_name, root_title );
4312     fileName = XtNewString( "." );
4313     dirName = XtNewString( "/" );
4314   }
4315   else
4316   {
4317     char * ptr;
4318     ptr = strrchr( fullName, '/' );
4319     if( ptr == fullName )
4320     {
4321       strcpy( title, ptr + 1 );
4322       dirName = XtNewString( "/" );
4323       fileName = XtNewString( ptr + 1 );
4324     }
4325     else if( *(ptr + 1) != '\0' )
4326     {
4327       char savedChar = *ptr;
4328       *ptr = '\0';
4329       dirName = XtNewString( fullName );
4330       *ptr = savedChar;
4331       strcpy( title, ptr + 1 );
4332       fileName = XtNewString( ptr + 1 );
4333     }
4334     else
4335     {
4336       tt_message_reply( ttMsg );
4337       tttk_message_destroy( ttMsg );
4338
4339       tt_free( fullName );
4340       return;
4341     }
4342   }
4343
4344   tt_free( fullName );
4345   workspace = XtNewString( requestWorkspace );
4346   tt_free( requestWorkspace );
4347
4348   if( strcmp( workspace, "current" ) == 0 )
4349   {
4350     Display  * display;
4351     Window   rootWindow;
4352     Atom     pCurrent;
4353     Screen   * currentScreen;
4354     int      screen;
4355
4356     XtFree( workspace );
4357
4358     /* Get the current workspace */
4359     display = XtDisplay( toplevel );
4360     screen = XDefaultScreen( display );
4361     currentScreen = XScreenOfDisplay( display, screen );
4362     rootWindow = RootWindowOfScreen( currentScreen );
4363
4364     if( DtWsmGetCurrentWorkspace( display, rootWindow, &pCurrent ) == Success )
4365       workspace = XGetAtomName( display, pCurrent );
4366     else
4367       workspace = XtNewString( desktop_data->workspaceData[0]->name );
4368   }
4369
4370   ws = -1;
4371   /* determine the workspace number
4372   */
4373   for( i = 0; i < desktop_data->numWorkspaces; ++i )
4374   {
4375     if( strcmp( workspace, desktop_data->workspaceData[i]->name ) == 0 )
4376     {
4377       ws = desktop_data->workspaceData[i]->number - 1;
4378       break;
4379     }
4380   }
4381
4382   if( ws == -1 )
4383   { /* Invalid workspace
4384        choose workspace one
4385     */
4386     ws = 0;
4387     XtFree( workspace );
4388     workspace = XtNewString( "ws0" );
4389     invalidWorkspace = 0x1;
4390   }
4391
4392   for( i = 0; i < desktop_data->numIconsUsed; ++i )
4393   {
4394     if( strcmp( desktop_data->desktopWindows[i]->title, title ) == 0
4395         && strcmp( desktop_data->desktopWindows[i]->workspace_name,
4396                    workspace ) == 0 )
4397     {
4398       char * template, * errorMsg, * dialogTitle;
4399
4400       dialogTitle = XtNewString(GETMESSAGE(20,84,"Put in Workspace"));
4401       if( invalidWorkspace )
4402         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."));
4403       else
4404         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."));
4405       errorMsg = (char *) XtMalloc( strlen( template )
4406                                     + strlen( title ) + 1 );
4407       sprintf( errorMsg, template, title );
4408       _DtMessage( toplevel, dialogTitle, errorMsg, NULL, HelpRequestCB );
4409
4410       XtFree( errorMsg );
4411       XtFree( workspace );
4412       XtFree( dirName );
4413       XtFree( fileName );
4414       XtFree( dialogTitle );
4415       XtFree( template );
4416
4417       tt_message_reply( ttMsg );
4418       tttk_message_destroy( ttMsg );
4419
4420       return;
4421     }
4422   }
4423
4424   /* get the next available cached iconWindow and use it to map
4425      this topLevelWindow */
4426   desktopWindow = desktop_data->desktopWindows[desktop_data->numIconsUsed];
4427   desktop_data->numIconsUsed++;
4428   desktop_data->numCachedIcons--;
4429
4430   /* store some of the data needed for the Desktop object */
4431   desktopWindow->host = XtNewString( home_host_name );
4432   desktopWindow->dir_linked_to = dirName;
4433   desktopWindow->file_name = fileName;
4434   desktopWindow->title = XtNewString( title );
4435
4436   desktopWindow->workspace_name = XtNewString( desktop_data->workspaceData[ws]->name );
4437   desktopWindow->workspace_num = desktop_data->workspaceData[ws]->number;
4438   desktopWindow->restricted_directory = NULL;
4439   desktopWindow->helpVol = NULL;
4440   desktopWindow->toolbox = False;
4441   desktopWindow->view = UNSET_VALUE;
4442   desktopWindow->order = UNSET_VALUE;
4443   desktopWindow->direction = UNSET_VALUE;
4444   desktopWindow->positionEnabled = UNSET_VALUE;
4445
4446   desktopWindow->file_view_data = BuildNewOrderlist(
4447                               NULL /* @@@ use cached info if possible! */,
4448                               desktopWindow->iconGadget,
4449                               home_host_name,
4450                               desktopWindow->dir_linked_to,
4451                               fileName,
4452                               desktopWindow->registered,
4453                               desktopWindow->toolbox );
4454
4455   MakeDesktopWindow( desktopWindow, -1, -1 );
4456   desktopWindow->registered = desktopWindow->file_view_data->registered;
4457
4458   /* go cache some more windows if there isn't enough cached */
4459   if( desktop_data->numCachedIcons < 5 )
4460     InitializeDesktopWindows( 5, XtDisplay( toplevel ) );
4461
4462   /* go save the current state of the desktop */
4463   SaveDesktopInfo( NORMAL_RESTORE );
4464
4465   tt_message_reply( ttMsg );
4466   tttk_message_destroy( ttMsg );
4467
4468   XtFree( workspace );
4469
4470   if( checkBrokenLink != 0 && checkBrokenLinkTimerId == 0 )
4471   {
4472     checkBrokenLinkTimerId = XtAppAddTimeOut(
4473                                  XtWidgetToApplicationContext( toplevel ),
4474                                  checkBrokenLink * 1000,
4475                                  TimerEventBrokenLinks,
4476                                  NULL );
4477   }
4478
4479 }
4480