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