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