2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: File.c /main/22 1999/12/09 13:05:50 mgreess $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 * COMPONENT_NAME: Desktop File Manager (dtfile)
31 * Description: File processing functions.
35 * BuildObjectPositions
36 * CommitWorkProcUpdates
39 * CreateNameChangeDialog
47 * DrawingAreaRedisplay
82 * HorizontalScrollbarIsVisible
84 * InMultipleObjectRegion
98 * RedisplayUsingStackingOrder
101 * RegisterDesktopHotspots
102 * RelocateDesktopIcon
103 * ReorderChildrenList
106 * RepairStackingPointers
108 * RepositionUpInStack
109 * RestorePositionalData
127 * TypeToDropOperations
134 * VerticalScrollbarIsVisible
141 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
142 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
143 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
144 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
146 ****************************************************************************
147 ************************************<+>*************************************/
156 #include <Xm/BulletinB.h>
157 #include <Xm/MwmUtil.h>
158 #include <X11/ShellP.h>
159 #include <X11/Shell.h>
160 #include <X11/Xutil.h>
161 #include <X11/Xatom.h>
162 #ifndef XK_MISCELLANY
163 #define XK_MISCELLANY
165 #include <X11/keysymdef.h>
168 #include <X11/extensions/shape.h>
171 #include <Xm/DrawingA.h>
172 #include <Xm/DrawingAP.h>
173 #include <Xm/RowColumn.h>
174 #include <Xm/LabelG.h>
175 #include <Xm/PushBG.h>
176 #include <Xm/ToggleBG.h>
177 #include <Xm/SeparatoG.h>
178 #include <Xm/ScrollBar.h>
179 #include <Xm/ScrolledW.h>
180 #include <Xm/TextF.h>
181 #include <Xm/Frame.h>
182 #include <Xm/Screen.h>
183 #include <sys/types.h>
184 #include <sys/stat.h>
186 #include <Dt/IconP.h>
187 #include <Dt/IconFile.h>
189 #include <Xm/DragIcon.h>
190 #include <Xm/DragC.h>
196 #include <Dt/Action.h>
197 #include <Dt/Connect.h>
199 #include <Dt/DtNlUtils.h>
200 #include <Dt/HourGlass.h>
202 #include <Dt/UserMsg.h>
203 #include <Dt/SharedProcs.h>
207 #include <Xm/XmPrivate.h> /* _XmIsEventUnique _XmSetInDragMode _XmRecordEvent */
210 #include "SharedProcs.h"
218 #include "SharedMsgs.h"
221 extern Widget _DtDuplicateIcon ( Widget, Widget, XmString, String, XtPointer, Boolean );
223 /* absolute value macro */
225 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
231 * MAXWINSIZE: maximum width of the file window
233 * Note: the file window width and height can't exceed the maximum value
234 * for a short (32767), because x and y coords of the icon gadgets placed
235 * in the file window are stored as short's by the Xt library (the
236 * Position type is a short).
237 * Furthermore, somewhere in the code for registering icon drop sites
238 * in libDt or libXm calculations are done that overflow if the window
239 * size is too close to the maximum of 32767. The symptom is observed
240 * most easily in tree mode on a directory large enough for icons to
241 * overflow into a second column: for values of MAXWINSIZE of 32767,
242 * none of the icons are sensitive as drop sites any more. The value
243 * for MAXWINSIZE defined below has been found to be "safe" by experiment.
245 #define MAXWINSIZE 32600
247 /******** Static Function Declarations ********/
249 static int FileNameAscending(
252 static int FileNameDescending(
255 static int FileTypeAscending(
258 static int FileTypeDescending(
261 static int FileSizeAscending(
264 static int FileSizeDescending(
267 static int FileDateAscending(
270 static int FileDateDescending(
273 static void CompressObjectList (
274 ObjectPosition ** object_positions,
276 int starting_index) ;
277 static ObjectPosition *GetPositionalData (
278 FileMgrData * file_mgr_data,
279 FileViewData * object,
282 static void RedisplayUsingStackingOrder (
283 FileMgrData * file_mgr_data,
287 static void ReorderChildrenList (
288 XmManagerWidget file_window,
293 static Boolean IsDesktopPtr (
294 FileViewData * fileViewData,
295 FileMgrData ** fileMgrData,
296 DesktopRec ** desktopRec) ;
297 static Boolean IntersectRects(
306 static void InitiateIconDrag(
307 FileViewData * fileViewData,
311 static void RelocateDesktopIcon(
312 DesktopRec * desktopRec,
315 static void BuildObjectPositions(
316 FileMgrData *file_mgr_data);
317 static void moveCopyLinkCancel(
319 XtPointer client_data,
320 XtPointer call_data );
321 static void moveCopyLinkOK(
323 XtPointer client_data,
324 XtPointer call_data );
325 static void DropOnRootCB (
327 XtPointer client_data,
328 XtPointer call_data);
329 static void _UpdateFileIcons(
330 FileMgrRec *file_mgr_rec,
331 FileMgrData *file_mgr_data,
332 Boolean new_directory,
333 DirectorySet * add_dir_set );
334 static void CreateTreeIcons(
336 static void TreeBtnCallback(
338 XtPointer clientData,
339 XmAnyCallbackStruct * callData );
340 static void LayoutDesktopIcons(
341 FileMgrRec *file_mgr_rec,
342 FileMgrData *file_mgr_data,
343 FileViewData ** order_list,
345 Boolean turn_off_hourglass);
346 static XmGadget InputInGadget (
350 static XmGadget InputForGadget (
355 /******** End Static Function Declarations ********/
357 /* cursor for double-click-drag (@@@ should be a resource) */
358 static Cursor loc_cursor1 = None;
359 static Cursor loc_cursor2 = None;
360 #define DBLCLICK_DRAG_THRESHOLD 20
362 /* layout constants (@@@ could be made resources) */
365 #define YSPACING(fmd) \
367 (fmd->view != BY_NAME? - ((IconLayoutData *)fmd->layout_data)->highlight: \
368 - ((IconLayoutData *)fmd->layout_data)->highlight + 2): \
371 #define TreeOffset 15
372 #define TreeOneWd(sz) (TreeOffset + TreeBtnWd[sz]/2)
373 #define TreeLX(level,sz) (TreeBtnWd[sz]/2 + ((level) - 1)*TreeOneWd(sz))
374 #define TreeWd(level,sz) \
375 (TreeLX(level,sz) + TreeOffset + TreeBtnWd[sz] + TreeSep)
377 /* maximum size of the small, medium, and large tree buttons */
378 static int TreeBtnWd[3] = { 0, 0, 0 };
379 static int TreeBtnHt[3] = { 0, 0, 0 };
381 static int TreeNilWd[3] = { 0, 0, 0 };
382 static int TreeNilHt[3] = { 0, 0, 0 };
384 /* tree expansion circle pixmap indices */
386 tpxNotRead, /* dotted circle */
387 tpxError, /* crossed circle */
388 tpxMore, /* "+" circle */
389 tpxLess, /* "-" circle */
390 tpxBoth, /* "+/-" circle */
391 tpxEmpty, /* empty circle */
392 tpxNil, /* empty-set symbol */
396 /* pixmaps for expand circles in tree mode */
397 static struct TreePx {
398 char *name; /* name of pixmap file */
399 Pixmap px[3]; /* small, medium, and large pixmap */
411 static char *TreePxSuffix[3] = { ".s", ".m", ".l" };
413 /* value need to to convert drop position to icon placement */
414 static int dragIconPixmapOffsetX;
415 static int dragIconPixmapOffsetY;
421 #define FILE_INVALID 2
424 FileMgrPopup fileMgrPopup = {NULL};
427 /* Obsolete Motif highlighting and unhighlighting routines */
428 extern void _XmHighlightBorder(Widget w);
429 extern void _XmUnhighlightBorder(Widget w);
431 extern void SelectDTFile (DesktopRec *desktopWindow);
433 /************************************************************************
434 ************************************************************************
436 * Comparison functions used for sorting the files
438 ************************************************************************
439 ************************************************************************/
440 /* only use when LANG=C on platforms that don't
441 provide strcasecmp(). Otherwise, use strcoll() */
447 /* Note: This is not really a string case insensitive compare. So don't
448 even think of replacing it with any other library routines.
450 char *s1a = (char *)s1, *s2a = (char *)s2;
452 if (s1 == s2) return 0;
454 for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) {
457 /* File Manager depends heavily on this routine to position the
459 We want case INSENSITIVE comparision, however when we have
460 2 same size and case equivalent strings i.e. "A" and "a", we
461 need this routine to behave like a case SENSITIVE comparision, so
462 the position of the icon is constant so "A" is always
467 for (; *s1a == *s2a; ++s1a, ++s2a) {
478 return tolower(*s1) - tolower(*s2);
481 StrcollProc FMStrcoll = NULL;
488 struct locale_data * li;
495 /* if locale is C, use the explicit case insensitive compare */
497 li = getlocale(LOCALE_STATUS);
498 if ( NULL == li->LC_COLLATE_D || strcmp(C_LANG,li->LC_COLLATE_D) == 0 )
501 locale = setlocale(LC_COLLATE,NULL); /* put locale in buf */
502 if (strcmp(locale,C_LANG) == 0)
509 return ((StrcollProc)strcoll);
519 if (((FileMgrData *)((DirectorySet *)((*t1)->directory_set))->file_mgr_data)
520 ->show_type == MULTIPLE_DIRECTORY)
522 if (!(*t1)->file_data->is_subdir && (*t2)->file_data->is_subdir)
524 else if ((*t1)->file_data->is_subdir && !(*t2)->file_data->is_subdir)
538 if (FMStrcoll ((*t1)->file_data->file_name, "." ) == 0 )
544 if (FMStrcoll ((*t1)->file_data->file_name, "..") == 0 )
546 if ( FMStrcoll ((*t2)->file_data->file_name, ".") == 0 )
553 if (FMStrcoll ((*t2)->file_data->file_name, ".") == 0 || FMStrcoll ((*t2)->file_data->file_name, "..") == 0)
567 if (!(*t1)->file_data->is_subdir && (*t2)->file_data->is_subdir)
573 if ((*t1)->file_data->is_subdir && !(*t2)->file_data->is_subdir)
589 if( SpecialCases( t1, t2, &rc ) )
592 if((*t1)->file_data->action_name == NULL)
594 if((*t2)->file_data->action_name == NULL)
595 rc = FMStrcoll((*t1)->file_data->file_name,
596 (*t2)->file_data->file_name);
598 rc = FMStrcoll((*t1)->file_data->file_name,
599 (*t2)->file_data->action_name);
603 if((*t2)->file_data->action_name != NULL)
604 rc = FMStrcoll((*t1)->file_data->action_name,
605 (*t2)->file_data->action_name);
607 rc = FMStrcoll((*t1)->file_data->action_name,
608 (*t2)->file_data->file_name);
621 if( SpecialCases( t1, t2, &rc ) )
624 if((*t1)->file_data->action_name == NULL)
626 if((*t2)->file_data->action_name == NULL)
627 rc = FMStrcoll((*t1)->file_data->file_name,
628 (*t2)->file_data->file_name);
630 rc = FMStrcoll((*t1)->file_data->file_name,
631 (*t2)->file_data->action_name);
635 if((*t2)->file_data->action_name != NULL)
636 rc = FMStrcoll((*t1)->file_data->action_name,
637 (*t2)->file_data->action_name);
639 rc = FMStrcoll((*t1)->file_data->action_name,
640 (*t2)->file_data->file_name);
659 if( SpecialCases( t1, t2, &rc ) )
662 rc = strcoll( (*t1)->file_data->logical_type, (*t2)->file_data->logical_type );
664 rc = FileNameAscending( t1, t2 );
676 if( SpecialCases( t1, t2, &rc ) )
679 rc = strcoll( (*t1)->file_data->logical_type, (*t2)->file_data->logical_type );
687 rc = FileNameDescending( t1, t2 );
699 if( SpecialCases( t1, t2, &rc ) )
702 if ((*t1)->file_data->stat.st_size < (*t2)->file_data->stat.st_size)
705 else if ((*t1)->file_data->stat.st_size > (*t2)->file_data->stat.st_size)
718 if( SpecialCases( t1, t2, &rc ) )
721 if ((*t1)->file_data->stat.st_size < (*t2)->file_data->stat.st_size)
724 if ((*t1)->file_data->stat.st_size > (*t2)->file_data->stat.st_size)
737 if( SpecialCases( t1, t2, &rc ) )
740 if ((*t1)->file_data->stat.st_mtime < (*t2)->file_data->stat.st_mtime)
743 if ((*t1)->file_data->stat.st_mtime > (*t2)->file_data->stat.st_mtime)
757 if( SpecialCases( t1, t2, &rc ) )
760 if ((*t1)->file_data->stat.st_mtime < (*t2)->file_data->stat.st_mtime)
763 if ((*t1)->file_data->stat.st_mtime > (*t2)->file_data->stat.st_mtime)
773 /************************************************************************
776 * Sort the file display list according to the ordering data.
778 ************************************************************************/
782 FileMgrData *file_mgr_data,
783 DirectorySet *directory_set )
785 FileViewData ** file_view_data;
787 FileViewData ** order_list;
793 file_view_data = directory_set->file_view_data;
794 file_count = directory_set->file_count;
797 /* Allocate an ordering list */
799 if (directory_set->order_list != NULL)
801 XtFree ((char *) directory_set->order_list);
802 directory_set->order_list = NULL;
806 directory_set->order_list = order_list =
807 (FileViewData **) XtMalloc (sizeof (FileViewData **) * file_count);
809 directory_set->order_list = order_list = NULL;
811 /* Get pointers to all of the file data into the order list */
813 for (i = 0; i < file_count; i++)
814 order_list[i] = file_view_data[i];
816 /* Set up the sorting functions according to the order and direction. */
820 if (file_mgr_data->order == ORDER_BY_FILE_TYPE)
822 if (file_mgr_data->direction == DIRECTION_ASCENDING)
824 sort = (int *) FileTypeAscending;
825 sub_sort = (int *) FileNameAscending;
829 sort = (int *) FileTypeDescending;
830 sub_sort = (int *) FileNameDescending;
834 else if (file_mgr_data->order == ORDER_BY_ALPHABETICAL)
836 if (file_mgr_data->direction == DIRECTION_ASCENDING)
837 sort = (int *) FileNameAscending;
839 sort = (int *) FileNameDescending;
841 else if (file_mgr_data->order == ORDER_BY_DATE)
843 if (file_mgr_data->direction == DIRECTION_ASCENDING)
844 sort = (int *) FileDateAscending;
846 sort = (int *) FileDateDescending;
849 else if (file_mgr_data->order == ORDER_BY_SIZE)
851 if (file_mgr_data->direction == DIRECTION_ASCENDING)
852 sort = (int *) FileSizeAscending;
854 sort = (int *) FileSizeDescending;
858 /* Sort the files and if the sub_sort function is non-null, */
859 /* sort sets of the files broken according to file type. */
861 qsort (order_list, file_count, sizeof (FileViewData *), (int (*)())sort);
863 if (sub_sort != NULL)
868 while (i < file_count)
870 if (order_list[start]->file_data->logical_type !=
871 order_list[i]->file_data->logical_type)
873 qsort (order_list + start, i - start,
874 sizeof (FileViewData *), (int (*)())sub_sort);
881 qsort (order_list + start, i - start, sizeof (FileViewData *),
882 (int (*)())sub_sort);
888 /************************************************************************
891 * Filter out the files which do not match the filtering criteria.
893 * The `mustMatch' flag is used to determine whether the user has
894 * requested that the files which match the specification are to
895 * be displayed, or instead, filtered out.
897 ************************************************************************/
901 FileMgrData *file_mgr_data,
902 DirectorySet *directory_set )
904 FileViewData **file_view_data;
905 FilterData * filter_data;
909 Boolean mustMatch, matches;
911 int invisibleCount = 0;
912 FileViewData *sub_root;
913 #ifdef DT_PERFORMANCE
914 struct timeval update_time_s;
915 struct timeval update_time_f;
917 printf(" Begin FilterFiles\n");
918 gettimeofday(&update_time_s, NULL);
921 _DtPerfChkpntMsgSend("Begin Filtering Files");
925 file_view_data = directory_set->file_view_data;
927 filter_data = (FilterData *)(file_mgr_data->filter_active->data);
928 show_hidden = filter_data->show_hidden;
929 filter = filter_data->filter;
930 mustMatch = filter_data->match_flag;
932 /* set the show hidden boolean depending on the filter specification */
934 file_mgr_data->show_hid_enabled = True;
936 file_mgr_data->show_hid_enabled = False;
938 /* Filter out all files not matching the specifications */
940 for (i = 0; i < directory_set->file_count; i++)
942 /* Initially assume the file is not filtered out */
944 file_view_data[i]->filtered = False;
946 /* If in tree mode, explicitly filter out . and .. */
947 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY &&
948 (strcmp(file_view_data[i]->file_data->file_name, ".") == 0 ||
949 strcmp(file_view_data[i]->file_data->file_name, "..") == 0))
952 file_view_data[i]->filtered = True;
956 /* filter out any files that have their attributes "invisible" */
957 /* field set to false */
958 if((_DtCheckForDataTypeProperty(
959 file_view_data[i]->file_data->logical_type,
961 (file_mgr_data != trashFileMgrData))
964 file_view_data[i]->filtered = True;
969 /* Filter hidden files, according to the user setting */
971 if (file_view_data[i]->file_data->file_name[0] == '.')
973 if(strcmp(file_mgr_data->current_directory, "/") == 0 &&
974 strcmp(file_view_data[i]->file_data->file_name, "..") == 0)
977 file_view_data[i]->filtered = True;
980 if(file_mgr_data->restricted_directory != NULL)
982 if((strcmp(file_mgr_data->restricted_directory,
983 file_mgr_data->current_directory) == 0 &&
984 (strcmp(file_view_data[i]->file_data->file_name, ".") == 0 || strcmp(file_view_data[i]->file_data->file_name, "..") == 0 )) ||
985 (strncmp(file_mgr_data->restricted_directory,file_mgr_data->current_directory, strlen(file_mgr_data->restricted_directory)) == 0 &&
986 strcmp(file_view_data[i]->file_data->file_name, ".") == 0 ))
989 file_view_data[i]->filtered = True;
996 (strcmp(file_view_data[i]->file_data->file_name, "..") == 0 ||
997 strcmp(file_view_data[i]->file_data->file_name, ".") == 0))
1001 tempName = (char *)XtMalloc( strlen(file_mgr_data->current_directory) + 3);
1002 sprintf( tempName, "%s/", file_mgr_data->current_directory );
1003 if( strcmp(users_home_dir, tempName) == 0 ||
1004 strcmp(users_home_dir, file_mgr_data->current_directory) == 0)
1007 file_view_data[i]->filtered = True;
1015 /* if we want to show the hidden files no more should be filtered out */
1019 /* don't show .trashinfo in the trash directory */
1020 if(trashFileMgrData == file_mgr_data &&
1021 (strcmp(file_view_data[i]->file_data->file_name, ".trashinfo") == 0))
1024 file_view_data[i]->filtered = True;
1028 /* Check for a match against the filter expression string, except for
1029 * files in the trash directory and sub directories in tree mode. */
1032 if (strcmp(filter, "") != 0 &&
1033 file_mgr_data != trashFileMgrData &&
1034 !(file_mgr_data->show_type == MULTIPLE_DIRECTORY &&
1035 file_view_data[i]->file_data->is_subdir))
1037 /* Special case for ".." that need not be filtered */
1038 if( !strcmp( file_view_data[i]->file_data->file_name, ".." )
1039 || !strcmp( file_view_data[i]->file_data->file_name, "." ) )
1042 else if (file_view_data[i]->file_data->action_name)
1044 if(fnmatch((const char *)filter,
1045 (const char *)file_view_data[i]->file_data->action_name,
1051 file_view_data[i]->filtered = True;
1058 else if (fnmatch((const char *)filter,
1059 (const char *)file_view_data[i]->file_data->file_name, 0) == 0)
1064 file_view_data[i]->filtered = True;
1072 /* now lets check through the filter filetypes and if the file is */
1073 /* filtered, filter it out */
1074 if(file_mgr_data != trashFileMgrData)
1076 /* This is for the case of files likes 'action' files which
1077 do not have a logical_type */
1079 if(strcmp(file_view_data[i]->file_data->file_name,file_view_data[i]->
1080 file_data->logical_type) == 0)
1082 if(!filter_data->match_flag)
1087 file_view_data[i]->filtered = True;
1092 for(j = 0; j < filter_data->count; j++)
1094 if(strcmp(filter_data->user_data[j]->filetype,
1095 file_view_data[i]->file_data->logical_type) == 0)
1097 if((filter_data->user_data[j]->selected == True &&
1098 filter_data->match_flag) ||
1099 (filter_data->user_data[j]->selected == False &&
1100 !filter_data->match_flag))
1105 file_view_data[i]->filtered = True;
1114 /* update ndir, nfile counts for this sub directory */
1115 directory_set->filtered_file_count = filterCount;
1116 directory_set->invisible_file_count = invisibleCount;
1117 sub_root = directory_set->sub_root;
1118 sub_root->ndir = sub_root->nfile = 0;
1121 for (i = 0; i < directory_set->file_count; i++)
1123 if (!file_view_data[i]->filtered)
1125 if (file_view_data[i]->file_data->is_subdir)
1132 UpdateBranchState(file_mgr_data, sub_root, BRANCH_UPDATE, False);
1134 #ifdef DT_PERFORMANCE
1135 gettimeofday(&update_time_f, NULL);
1136 if (update_time_s.tv_usec > update_time_f.tv_usec) {
1137 update_time_f.tv_usec += 1000000;
1138 update_time_f.tv_sec--;
1140 printf(" done FilterFiles, time: %ld.%ld\n\n", update_time_f.tv_sec - update_time_s.tv_sec, update_time_f.tv_usec - update_time_s.tv_usec);
1143 _DtPerfChkpntMsgSend("Done Filtering Files");
1151 /************************************************************************
1153 * GetAncestorInfo, GetLevel, GetFullName
1155 ************************************************************************/
1159 FileMgrData *file_mgr_data,
1165 * Get information related to the ancestory of an entry:
1166 * - tree depth level
1168 * - for each level: flag indicating whether there are additional siblings
1169 * to be diplayed after this entry
1172 FileViewData *pp, *pa[256];
1176 /* determine tree depth level of this entry */
1178 for (pp = ip->parent; pp; pp = pp->parent)
1183 /* get a list of all ancestors (including ip) in top down order */
1185 for (pp = ip; pp; pp = pp->parent)
1188 /* construct path name of this entry */
1190 strcpy(path, file_mgr_data->current_directory);
1191 p = path + strlen(path);
1192 for (l = 1; l <= level; l++) {
1195 strcpy(p, pa[l]->file_data->file_name);
1200 /* compile more array */
1202 for (l = 0; l <= level; l++) {
1203 DirectorySet *ds = (DirectorySet *)pa[l]->directory_set;
1205 if (ds->order_list == NULL)
1207 for (i = 0; i < ds->file_count; i++)
1208 if (ds->order_list[i] == pa[l])
1210 for (i = i + 1; i < ds->file_count; i++) {
1211 if (ds->order_list[i]->displayed) {
1223 FileMgrData *file_mgr_data,
1227 GetAncestorInfo(file_mgr_data, ip, NULL, path, NULL);
1233 FileMgrData *file_mgr_data,
1239 GetAncestorInfo(file_mgr_data, ip, NULL, path, NULL);
1240 p = strrchr(path, '/');
1251 for (ip = ip->parent; ip; ip = ip->parent)
1257 /************************************************************************
1261 ************************************************************************/
1266 FileViewData *fvd_array[],
1269 * Copy all entries from the tree to an array
1272 DirectorySet *directory_set;
1275 fvd_array[*index] = ip;
1280 directory_set = (DirectorySet *)ip->desc->directory_set;
1281 for (i = 0; i < directory_set->file_count; i++)
1282 CopyOrderedEntries(directory_set->order_list[i], fvd_array, index);
1289 FileMgrData *file_mgr_data,
1290 FileViewData ***file_view_data,
1296 for (i = 0; i < file_mgr_data->directory_count; i++)
1297 *file_count += file_mgr_data->directory_set[i]->file_count;
1300 (FileViewData **) XtMalloc (*file_count * sizeof(FileViewData *));
1302 CopyOrderedEntries(file_mgr_data->tree_root, *file_view_data, &i);
1306 /************************************************************************
1309 * Callback function invoked upon an action occurring on an icon.
1311 ************************************************************************/
1319 return (ep->type == MotionNotify || ep->type == ButtonRelease);
1326 XtPointer clientData,
1327 XtPointer callData )
1329 XmAnyCallbackStruct * callback;
1330 XButtonEvent * event;
1331 FileViewData * fileViewData;
1332 FileMgrData * fileMgrData;
1333 static Boolean highlightType = INIT_VALUE;
1334 static Widget highlightWidget = NULL;
1337 DesktopRec * desktopRec;
1342 WindowPosition position;
1344 static int adjustState=-1;
1345 XrmValue value_return;
1346 char *str_type_return;
1349 if( adjustState == -1)
1351 if (XrmGetResource(XrmGetDatabase(XtDisplay(w)), "*enableBtn1Transfer", "*EnableBtn1Transfer",&str_type_return, &value_return) && !strcmp(value_return.addr,"True") )
1359 callback = (XmAnyCallbackStruct *) callData;
1360 fileViewData = (FileViewData *) clientData;
1361 event = (XButtonEvent *) callback->event;
1363 if (callback->reason == XmCR_DRAG && event->button == bMenuButton)
1364 callback->reason = XmCR_POPUP;
1366 if(callback->reason != XmCR_UNHIGHLIGHT)
1368 /* Get the directory data and the file manager data */
1369 (void)IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
1372 /* Process the different callback types */
1373 if ((callback->reason == XmCR_ARM) || (callback->reason == XmCR_SELECT))
1376 * Both ARM and SELECT are generated using Button1. We pass on these
1377 * requests to the code responsible for processing button 1 selects
1380 FileMgrRec * fileMgrRec;
1381 DtIconGadget new = (DtIconGadget)w;
1383 if( event->type == KeyPress )
1385 /* if a keypress we only want to select on an SELECT */
1386 if( callback->reason == XmCR_ARM )
1394 kevent = (XKeyEvent *)event;
1395 if (kevent->state & ShiftMask)
1400 keysym = XLookupKeysym((XKeyEvent *)kevent, offset);
1402 if( keysym == XK_Return )
1403 goto run_default_action;
1407 if (callback->reason == XmCR_ARM)
1408 new->icon.armed = False;
1412 B1DragPossible = False;
1413 B2DragPossible = False;
1414 XtCallCallbacks(desktopRec->drawA, XmNinputCallback, callData);
1418 B1DragPossible = False;
1419 B2DragPossible = False;
1421 fileMgrRec = (FileMgrRec *)fileMgrData->file_mgr_rec;
1422 XtCallCallbacks(fileMgrRec->file_window, XmNinputCallback, callData);
1425 if (callback->reason == XmCR_ARM)
1426 new->icon.armed = True;
1428 else if (callback->reason==XmCR_DISARM)
1431 * DISARM is generated as the result of a button 1 up event.
1432 * If we are in the middle of a button 2 drag, then we'll ignore this;
1433 * otherwise, we now know a drag will not start, so clear all state flags.
1438 B1DragPossible = False;
1439 B2DragPossible = False;
1440 ProcessBtnUp = False;
1442 else if (callback->reason == XmCR_DROP)
1445 * DROP is generated as the result of a button 2 up event.
1446 * If we are in the middle of a button 1 drag, then we'll ignore this;
1447 * otherwise, we now know a drag will not start, so clear all state flags.
1452 B1DragPossible = False;
1453 B2DragPossible = False;
1454 ProcessBtnUp = False;
1456 else if (callback->reason == XmCR_DEFAULT_ACTION)
1460 if(event->type == KeyPress)
1466 kevent = (XKeyEvent *)event;
1467 if (kevent->state & ShiftMask)
1472 keysym = XLookupKeysym((XKeyEvent *)kevent, offset);
1474 if (keysym == XK_Escape)
1476 /* an escape unposts the name change text widget */
1478 UnpostDTTextField();
1480 UnpostTextField(fileMgrData);
1485 KeySym SpaceKeySym = XStringToKeysym( "space" );
1486 if( keysym == SpaceKeySym )
1496 * If DEFAULT_ACTION was generated by button press,
1497 * wait for the button release
1500 if(event->type == ButtonPress)
1502 if (loc_cursor1 == None)
1503 loc_cursor1 = XCreateFontCursor(XtDisplay(w), 40);
1504 if (loc_cursor2 == None)
1505 loc_cursor2 = XCreateFontCursor(XtDisplay(w), 34);
1507 root = RootWindowOfScreen(XtScreen(w));
1508 XGrabPointer(XtDisplay(w), root,
1509 False, ButtonReleaseMask | PointerMotionMask,
1510 GrabModeAsync, GrabModeAsync,
1511 None, loc_cursor1, CurrentTime);
1513 XIfEvent(XtDisplay(w), &bevent, IsButtonOrMotion, NULL);
1514 if (!dragged && bevent.type == MotionNotify) {
1515 dx = event->x_root - bevent.xmotion.x_root; if (dx < 0) dx = -dx;
1516 dy = event->y_root - bevent.xmotion.y_root; if (dy < 0) dy = -dy;
1517 if (dx > DBLCLICK_DRAG_THRESHOLD || dy > DBLCLICK_DRAG_THRESHOLD) {
1518 DPRINTF(("dragged!\n"));
1519 XGrabPointer(XtDisplay(w), root,
1520 False, ButtonReleaseMask | PointerMotionMask,
1521 GrabModeAsync, GrabModeAsync,
1522 None, loc_cursor2, CurrentTime);
1526 } while (bevent.type != ButtonRelease);
1528 XUngrabPointer(XtDisplay(w), CurrentTime);
1529 XFlush(XtDisplay(w));
1531 position.x = bevent.xbutton.x_root;
1532 position.y = bevent.xbutton.y_root;
1536 * DEFAULT_ACTION is generated by a double-click of button 1.
1537 * We now know a drag will not start, so clear all state flags.
1539 B1DragPossible = False;
1540 B2DragPossible = False;
1541 ProcessBtnUp = False;
1543 logicalType = fileViewData->file_data->logical_type;
1544 command = _DtRetrieveDefaultAction(logicalType);
1548 /* Any button event unposts the text field */
1549 UnpostDTTextField();
1552 RunDTCommand(command, desktopRec, NULL);
1558 /* Any button event unposts the text field */
1559 UnpostTextField(fileMgrData);
1561 if((openDirType == NEW && strcmp(command, openInPlace) == 0) ||
1562 (openDirType != NEW && strcmp(command, openNewView) == 0))
1564 unsigned int modifiers = event->state;
1566 RunCommand (openNewView, fileMgrData, fileViewData,
1567 dragged? &position: NULL, NULL, NULL);
1568 if((modifiers != 0) && ((modifiers & ControlMask) != 0))
1570 DialogData *dialog_data;
1572 dialog_data = _DtGetInstanceData(fileMgrData->file_mgr_rec);
1573 CloseView(dialog_data);
1580 if ((fileMgrData->show_type == MULTIPLE_DIRECTORY || dragged) &&
1581 strcmp(command, openInPlace) == 0)
1583 RunCommand (openNewView, fileMgrData, fileViewData,
1584 dragged? &position: NULL, NULL, NULL);
1587 RunCommand (command, fileMgrData, fileViewData,
1603 tmpStr = (GETMESSAGE(9,6, "Action Error"));
1604 title = (char *)XtMalloc(strlen(tmpStr) + 1);
1605 strcpy(title, tmpStr);
1607 (void) sprintf (msg,
1608 (GETMESSAGE(9,7, "There are no actions defined for %s\n")),
1611 _DtMessage (desktopRec->shell, title, msg, NULL, HelpRequestCB);
1613 _DtMessage (fileViewData->widget, title, msg, NULL, HelpRequestCB);
1617 else if (callback->reason == XmCR_DRAG)
1620 * DRAG is generated by a button 2 down event. It flags that
1621 * the user may possible be initiating a drag; we won't know
1622 * for sure until the drag threshold is surpassed.
1623 * Ignore this if a Button 1 drag is ramping up.
1628 /* Any button event unposts the text field */
1631 UnpostDTTextField();
1632 if(!DTFileIsSelected(desktopRec, fileViewData) && adjustState)
1633 SelectDTFile(desktopRec);
1637 if( fileMgrData && !FileIsSelected(fileMgrData,fileViewData) &&
1641 SelectFile(fileMgrData, fileViewData);
1643 UnpostTextField(fileMgrData);
1646 /* Save starting X & Y, in case a drag really starts */
1647 initialDragX = event->x;
1648 initialDragY = event->y;
1649 B2DragPossible = True;
1650 memcpy((char *) &desktop_data->event, (char *) event,
1651 (int) sizeof(XButtonEvent));
1653 else if (callback->reason == XmCR_POPUP)
1657 FmPopup (w, clientData, (XEvent *)event, fileMgrData);
1660 else if (callback->reason == XmCR_HIGHLIGHT)
1662 DtIconGadget g = (DtIconGadget)w;
1666 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1667 _XmUnhighlightBorder(w);
1669 B1DragPossible = False;
1670 B2DragPossible = False;
1674 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1677 if ((highlightType != INIT_VALUE) && (highlightWidget))
1681 if (highlightType == NOT_DESKTOP)
1682 DrawUnhighlight(highlightWidget, NOT_DESKTOP);
1683 else if (highlightWidget != w)
1684 DrawUnhighlight(highlightWidget, DESKTOP);
1688 if (highlightType == DESKTOP)
1689 DrawUnhighlight(highlightWidget, DESKTOP);
1690 else if (highlightWidget != w)
1691 DrawUnhighlight(highlightWidget, NOT_DESKTOP);
1697 DrawHighlight(w, NULL, NULL, DESKTOP);
1698 highlightType = DESKTOP;
1702 DrawHighlight(w, fileViewData, fileMgrData, NOT_DESKTOP);
1703 highlightType = NOT_DESKTOP;
1705 highlightWidget = w;
1707 else if (callback->reason == XmCR_UNHIGHLIGHT)
1709 DtIconGadget g = (DtIconGadget)w;
1713 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1714 _XmHighlightBorder(w);
1716 B1DragPossible = False;
1717 B2DragPossible = False;
1721 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1724 if (w == highlightWidget)
1726 if (highlightType == DESKTOP)
1727 DrawUnhighlight(w, DESKTOP);
1729 DrawUnhighlight(w, NOT_DESKTOP);
1731 highlightType = INIT_VALUE;
1732 highlightWidget = NULL;
1735 else if (callback->reason == XmCR_SHADOW)
1736 DrawShadowTh(w, NULL, DESKTOP);
1742 FileViewData * fileViewData,
1743 FileMgrData * fileMgrData,
1744 DesktopRec * desktopRec,
1747 int selectedCount = 0;
1751 /* If the initiation of the drag occurred upon an */
1752 /* already selected icon, check for a multiple drag. */
1754 if ((desktopRec == NULL) && FileIsSelected(fileMgrData, fileViewData))
1755 selectedCount = fileMgrData->selected_file_count;
1756 else if (desktopRec == NULL)
1760 if (DTFileIsSelected(desktopRec, fileViewData))
1762 if(DtWsmGetCurrentWorkspace(XtDisplay(desktopRec->shell),
1763 RootWindowOfScreen(XtScreen(desktopRec->shell)),
1764 &pCurrent) == Success)
1766 wsName = XGetAtomName(XtDisplay(desktopRec->shell), pCurrent);
1767 CleanUpWSName(wsName);
1770 wsName = XtNewString("One");
1772 for(*dt = 0; *dt < desktop_data->numWorkspaces; (*dt)++)
1774 if(strcmp(wsName, desktop_data->workspaceData[*dt]->name) == 0)
1776 selectedCount = desktop_data->workspaceData[*dt]->files_selected;
1786 return(selectedCount);
1797 Display *dpy = XtDisplay(w);
1798 unsigned char flags;
1799 XRectangle pRect, lRect;
1803 Dimension shadowThickness;
1804 Dimension marginWidth, marginHeight;
1806 Boolean minXUndefined, minYUndefined;
1808 dragMask = XCreatePixmap(dpy, RootWindowOfScreen (XtScreenOfObject(w)),
1811 /* Create a GC for drawing 0's into the pixmap */
1812 fillGC = XCreateGC(dpy, dragMask, 0, (XGCValues *) NULL);
1814 XFillRectangle(dpy, dragMask, fillGC, 0, 0, wid, hei);
1816 values.foreground = 1;
1817 XChangeGC(dpy, fillGC, GCForeground, &values);
1819 /* Create the drag pixmap, and the associated mask bitmap */
1820 _DtIconGetIconRects((DtIconGadget)w, &flags, &pRect, &lRect);
1824 minXUndefined = minYUndefined = True;
1825 if (flags & XmPIXMAP_RECT)
1829 minXUndefined = minYUndefined = False;
1831 if (flags & XmLABEL_RECT)
1833 if ((lRect.x < minX) || minXUndefined)
1835 if ((lRect.y < minY) || minYUndefined)
1839 XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
1840 XtSetArg (args[1], XmNmarginWidth, &marginWidth);
1841 XtSetArg (args[2], XmNmarginHeight, &marginHeight);
1842 XtGetValues (w, args, 3);
1844 if (flags & XmPIXMAP_RECT)
1845 XFillRectangle(dpy, dragMask, fillGC,
1846 pRect.x - minX + shadowThickness + marginWidth,
1847 pRect.y - minY + shadowThickness + marginHeight,
1848 pRect.width - 2*marginWidth,
1849 pRect.height - 2*marginHeight);
1850 if (flags & XmLABEL_RECT)
1852 XFillRectangle(dpy, dragMask, fillGC,
1853 lRect.x - minX + shadowThickness + marginWidth,
1854 lRect.y - minY + shadowThickness + marginHeight,
1855 lRect.width - 2*marginWidth,
1856 lRect.height - 2*marginHeight);
1858 XFreeGC(dpy, fillGC);
1866 FileViewData * fileViewData )
1868 XmManagerWidget mw = (XmManagerWidget) XtParent(w);
1869 Widget screen_object = (Widget) XmGetXmScreen(XtScreenOfObject(w));
1872 unsigned int wid, hei, d, junk;
1877 dragPixmap = _DtIconDraw (w, 0, 0, 0, False);
1879 XGetGeometry (XtDisplay(w), dragPixmap,
1880 (Window *) &junk, /* returned root window */
1881 (int *) &junk, (int *) &junk, /* x, y of pixmap */
1882 &wid, &hei, /* width, height of pixmap */
1883 &junk, /* border width */
1887 && ((FileMgrData *)initiating_view)->view == BY_ATTRIBUTES)
1889 XmFontList fontList;
1890 XmString fileNameString;
1891 DtIconGadget g = (DtIconGadget)w;
1894 XtSetArg( args[0], XmNfontList, &fontList );
1895 XtGetValues( fileViewData->widget, args, 1 );
1897 fileNameString = XmStringCreateLocalized( fileViewData->file_data->file_name );
1898 wid = XmStringWidth( fontList, fileNameString )
1899 + g->icon.pixmap_width
1900 + g->icon.cache->margin_width
1901 + g->icon.cache->spacing
1902 + G_ShadowThickness(g)
1903 + G_HighlightThickness(g);
1904 XmStringFree( fileNameString );
1907 dragMask = GetDragIconMask(w, wid, hei);
1910 XtSetArg(args[n], XmNhotX, 0); n++;
1911 XtSetArg(args[n], XmNhotY, 0); n++;
1912 XtSetArg(args[n], XmNwidth, wid); n++;
1913 XtSetArg(args[n], XmNheight, hei); n++;
1914 XtSetArg(args[n], XmNmaxWidth, wid); n++;
1915 XtSetArg(args[n], XmNmaxHeight, hei); n++;
1916 XtSetArg(args[n], XmNdepth, d); n++;
1917 XtSetArg(args[n], XmNpixmap, dragPixmap); n++;
1918 XtSetArg(args[n], XmNmask, dragMask); n++;
1919 XtSetArg(args[n], XmNforeground, mw->core.background_pixel); n++;
1920 XtSetArg(args[n], XmNbackground, mw->manager.foreground); n++;
1921 dragIcon = XtCreateWidget("drag_icon", xmDragIconObjectClass,
1922 screen_object, args, n);
1929 /* The following function is called if the completeMove flag is */
1930 /* set to TRUE. Internally, dtfile sets this to FALSE; thus, only */
1931 /* receiving clients that set this to true will get this function */
1932 /* called for them. */
1933 /* This function will delete the files/dirs that were dropped */
1934 /* on the receiving client. */
1939 FileViewData * fileViewData,
1943 static char *pname = "NewConvertDelete";
1947 DPRINTF(("%s: Entering function\n", pname));
1949 /* fork a background child process to honor the Move Completion */
1952 if (child_pid == -1)
1954 char *msg, *tmpStr, *title;
1956 DBGFORK(("%s: Cannot create child process\n", pname));
1958 tmpStr = GETMESSAGE(11,59,
1959 "Cannot create a child process to delete the dropped files.");
1960 msg = XtNewString(tmpStr);
1961 title = XtNewString((GETMESSAGE(11,58,"Process Create Error")));
1963 /* Display Error message */
1964 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
1971 /* In the Child Process, we simply erase the files */
1972 /* and directories that were dropped on the receiver */
1975 DBGFORK(("%s: child forked\n", pname));
1977 for (i = 0; i < numFiles; i++)
1979 DPRINTF(("%s: Erasing file %s\n", pname, fileList[i]));
1980 EraseObject(fileList[i]);
1983 DBGFORK(("%s: child exiting\n", pname));
1988 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
1996 FileViewData * fileViewData,
2000 FileMgrData * fileMgrData;
2001 DesktopRec * desktopRec;
2004 char * directoryName;
2008 if(fileViewData != NULL)
2010 (void)IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
2011 selectedCount = GetSelectedCount(fileViewData, fileMgrData, desktopRec, &dt);
2015 /* If fileViewData is NULL, then the file no long exists */
2016 fileMgrData = (FileMgrData *)initiating_view;
2019 selectedCount = fileMgrData->selected_file_count;
2024 if (selectedCount > 1)
2026 for (i = (selectedCount-1); i >= 0; i--)
2030 fileViewData = desktop_data->workspaceData[dt]->
2031 selectedDTWindows[i]->file_view_data;
2032 directoryName = desktop_data->workspaceData[dt]->
2033 selectedDTWindows[i]->dir_linked_to;
2034 fileName = fileViewData->file_data->file_name;
2038 fileViewData = fileMgrData->selection_list[i];
2039 directoryName = ((DirectorySet *)fileViewData->directory_set)->name;
2040 fileName = fileViewData->file_data->file_name;
2042 path = (char *)XtMalloc(strlen(directoryName) + strlen(fileName) + 2);
2043 sprintf(path,"%s/%s", directoryName, fileName);
2045 if ((!desktopRec) && (fileMgrData->toolbox))
2046 path = _DtResolveAppManPath(path,
2047 fileMgrData->restricted_directory);
2049 fileList[i] = DtEliminateDots(path);
2051 *numFiles = selectedCount;
2057 directoryName = desktopRec->dir_linked_to;
2058 fileName = fileViewData->file_data->file_name;
2060 else if(fileViewData)
2062 directoryName = ((DirectorySet *)fileViewData->directory_set)->name;
2063 fileName = fileViewData->file_data->file_name;
2067 directoryName = fileMgrData->current_directory;
2070 path = (char *)XtMalloc(strlen(directoryName) + strlen(fileName) + 2);
2071 sprintf(path,"%s/%s", directoryName, fileName);
2073 if ((!desktopRec) && (fileMgrData->toolbox))
2074 path = _DtResolveAppManPath(path, fileMgrData->restricted_directory);
2076 fileList[0] = DtEliminateDots( path );
2083 printf("NewConvertFileName: returns %d files\n", selectedCount);
2084 for (i = 0; i < selectedCount; i++) {
2085 printf("\t\"%s\"\n", fileList[i]);
2087 if (selectedCount == 0)
2088 printf("\t\"%s\"\n", fileList[0]);
2101 FileViewData * fileViewData = (FileViewData *) client;
2102 DtDndConvertCallback cb = (DtDndConvertCallback) call;
2103 FileMgrData *fmd = (FileMgrData *)initiating_view;
2107 fileViewData = fmd->drag_file_view_data;
2108 fmd->drag_file_view_data = NULL;
2110 if (cb->reason == DtCR_DND_CONVERT_DATA)
2112 if(fmd && !fmd->selected_file_count && fileViewData == NULL)
2114 cb->status = DtDND_FAILURE;
2115 cb->dragData->numItems = 0; /* Just to be on safe side */
2118 NewConvertFileName(w, fileViewData,
2119 cb->dragData->data.files, &cb->dragData->numItems);
2120 } else if (cb->reason == DtCR_DND_CONVERT_DELETE)
2122 NewConvertDelete(w, fileViewData,
2123 cb->dragData->data.files, cb->dragData->numItems);
2128 /* This callback procedure removes the icons when the drop is complete */
2131 DragFinishCB(Widget w, XtPointer client, XtPointer call)
2133 DtDndDragFinishCallback cb = (DtDndDragFinishCallback) call;
2135 static Window root = 0;
2137 DPRINTF(("DragFinishCB: dragActive -> False\n"));
2142 B1DragPossible = False;
2143 B2DragPossible = False;
2144 ProcessBtnUp = False;
2147 XtDestroyWidget(cb->sourceIcon);
2149 DPRINTF (("DragFinishCB: Number of items being freed are %d\n",
2150 cb->dragData->numItems));
2151 for (i = 0; i < cb->dragData->numItems; i++) {
2153 DPRINTF(("DragFinishCB: Freeing %s\n", cb->dragData->data.files[i]));
2154 XtFree(cb->dragData->data.files[i]);
2155 cb->dragData->data.files[i] = NULL;
2164 FileViewData * fileViewData,
2167 static XtCallbackRec fileConvertCB[] = { {FileConvertCB, NULL},
2169 static XtCallbackRec dragFinishCB[] = { {DragFinishCB, NULL},
2171 static XtCallbackRec dropOnRootCB[] = { {DropOnRootCB, NULL},
2176 FileMgrData * fileMgrData = NULL;
2177 DesktopRec * desktopRec = NULL;
2181 unsigned char operations;
2183 if (event->type == INVALID_TYPE) return;
2185 if (fileViewData == NULL) return;
2187 fileConvertCB[0].closure = (XtPointer)fileViewData;
2188 dropOnRootCB[0].closure = (XtPointer)fileViewData;
2190 desktopObj = IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
2191 selectedCount = GetSelectedCount(fileViewData, fileMgrData,
2194 if (selectedCount > 1)
2197 drag_icon = GetDragIcon(w, fileViewData);
2200 XtSetArg(args[numArgs], DtNsourceIcon, drag_icon); numArgs++;
2201 XtSetArg(args[numArgs], DtNdropOnRootCallback, dropOnRootCB); numArgs++;
2203 if ((desktopObj && desktopRec->toolbox) ||
2204 (!desktopObj && fileMgrData->toolbox))
2205 operations = XmDROP_COPY;
2207 operations = XmDROP_MOVE | XmDROP_COPY | XmDROP_LINK;
2209 if (DtDndDragStart(w, event, DtDND_FILENAME_TRANSFER, selectedCount,
2211 fileConvertCB, dragFinishCB, args, numArgs) == NULL) {
2212 DPRINTF(("StartDrag: dragActive -> False\n"));
2217 B1DragPossible = False;
2218 B2DragPossible = False;
2219 ProcessBtnUp = False;
2225 * This function is capable of initiating either a button 1 or button 2
2226 * drag operation; which one gets started is dependent upon which of the
2227 * two state flags (B1DragPossible or B2DragPossible) is set.
2232 FileViewData * fileViewData,
2238 FileMgrData * fileMgrData;
2243 char * directoryName;
2245 XRectangle dragMask[2];
2247 XRectangle pRect, lRect;
2248 unsigned char flags;
2252 Boolean allowDropInInitiatingWindow;
2255 Boolean minXUndefined, minYUndefined;
2256 DesktopRec * desktopRec;
2259 Boolean spaces = False;
2260 Boolean trash = False;
2261 char *tmpStr, *link_path, *ptr;
2263 /* Don't allow multi-drags to start */
2268 B1DragPossible = False;
2269 B2DragPossible = False;
2270 ProcessBtnUp = False;
2276 DPRINTF(("InitiateIconDrag: dragActive -> True\n"));
2278 dragIcon = fileViewData->widget;
2279 (void)IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
2281 /* if what we are dragging is a trash item, we want the objects to be
2282 * real objects, not their links
2284 if(fileMgrData == trashFileMgrData && trashFileMgrData != NULL)
2288 * We need to mark the icon which initiated the drag as no longer
2289 * being 'armed', since it will not receive the button up event,
2290 * because we will have release the drag.
2292 iconG = (DtIconGadget)dragIcon;
2293 iconG->icon.armed = False;
2296 * Remember the posistion of the icon pixmap within the drag icon.
2298 dragIconPixmapOffsetX = G_ShadowThickness(iconG) + G_MarginWidth(iconG);
2299 dragIconPixmapOffsetY = G_ShadowThickness(iconG) + G_MarginHeight(iconG);
2303 initiating_view = (XtPointer) NULL;
2304 widget_dragged = dragIcon;
2308 initiating_view = (XtPointer) fileMgrData;
2309 widget_dragged = NULL;
2311 StartDrag(dragIcon, fileViewData, event);
2316 * These are replacements for the corresponding libXm functions. They allow
2317 * us to treat icon gadgets as non-rectangular, so that input processing
2318 * is handled correctly.
2328 CompositeWidget cw = (CompositeWidget)w;
2329 static Region r = NULL;
2330 FileMgrData * file_mgr_data;
2331 Boolean simpleCheck = False;
2333 unsigned char flags;
2334 XRectangle pRect, lRect;
2337 file_mgr_data = ReturnDesktopPtr((Widget)cw);
2340 * Tree views and attribute views do not have the non-rectangular
2341 * hotspots, so we can resort to the standard checking algorithm.
2343 if ((file_mgr_data == NULL) ||
2344 (file_mgr_data->show_type != SINGLE_DIRECTORY) ||
2345 (file_mgr_data->view == BY_ATTRIBUTES))
2350 for (i = 0; i < cw->composite.num_children; i++)
2352 widget = cw->composite.children[i];
2354 if (XmIsGadget(widget) && XtIsManaged(widget))
2358 if (x >= widget->core.x && y >= widget->core.y &&
2359 (Position) x < (Position) (widget->core.x + widget->core.width) &&
2360 (Position) y < (Position) (widget->core.y + widget->core.height))
2362 return ((XmGadget) widget);
2367 /* Initialize the region to be empty */
2369 r = XCreateRegion();
2371 XSubtractRegion(r, r, r);
2373 _DtIconGetIconRects((DtIconGadget)widget, &flags, &pRect, &lRect);
2375 if (flags & XmPIXMAP_RECT)
2376 XUnionRectWithRegion(&pRect, r, r);
2378 if (flags & XmLABEL_RECT)
2379 XUnionRectWithRegion(&lRect, r, r);
2381 if (XPointInRegion(r, x, y))
2382 return ((XmGadget) widget);
2392 * This function is identical to the libXm version; it needs to be here
2393 * so that it will call our InputInGadget() instead of the libXm
2394 * version, which was bundled together with it in GadgetUtil.c
2405 gadget = InputInGadget (cw, x, y);
2407 if (!gadget || !XtIsSensitive ((Widget)gadget))
2409 return ((XmGadget) NULL);
2417 * This function processes motion events anytime a B1 or B2 drag operation
2418 * has the potential of starting for a file icon. When the drag threshold
2419 * is surpassed, a drag operation will be started.
2425 XtPointer clientData,
2429 FileViewData * fileViewData = NULL;
2430 Position rootX, rootY;
2431 DirectorySet * directoryData = NULL;
2436 if ((B1DragPossible && (event->xmotion.state & Button1Mask)) ||
2437 (B2DragPossible && (event->xmotion.state & Button2Mask)))
2439 /* Have we passed the drag threshold? */
2440 diffX = initialDragX - event->xmotion.x;
2441 diffY = initialDragY - event->xmotion.y;
2443 if ((ABS(diffX) >= dragThreshold) || (ABS(diffY) >= dragThreshold))
2445 /* Map the original (x,y) into a gadget Id */
2446 if (dragIcon =(Widget)InputForGadget(w, initialDragX, initialDragY))
2448 /* Map the icon into its fileViewData structure */
2449 /* Check for desktop icon first */
2450 for (i = 0, fileViewData = NULL; i<desktop_data->numIconsUsed; i++)
2452 if (desktop_data->desktopWindows[i]->iconGadget == dragIcon)
2454 fileViewData = desktop_data->desktopWindows[i]->file_view_data;
2458 if (fileViewData == NULL)
2460 /* Not a desktop icon */
2461 XtSetArg(args[0], XmNuserData, (XtPointer) &directoryData);
2462 XtGetValues(dragIcon, args, 1);
2463 for (i = 0; i < directoryData->file_count; i++)
2465 if (directoryData->file_view_data[i]->widget == dragIcon &&
2466 directoryData->file_view_data[i]->displayed)
2468 fileViewData = directoryData->file_view_data[i];
2475 /* Map to root coordinates */
2476 XtTranslateCoords(w, (Position)initialDragX, (Position)initialDragY,
2482 fmd = (FileMgrData *)(directoryData->file_mgr_data);
2484 fmd->drag_file_view_data = fileViewData;
2486 InitiateIconDrag(fileViewData, (int)rootX, (int)rootY, event);
2491 * The file manager view must have changed between the time
2492 * the user did the button down, and the time they moved
2493 * enough to pass the drag threshold, because there is now
2494 * no icon located where the drag initiated. Therefore,
2495 * we'll just clean up, because there is much else we can do.
2497 B1DragPossible = False;
2498 B2DragPossible = False;
2499 ProcessBtnUp = False;
2502 /* Force the button up to be ignored */
2510 /* Compute position of desktop icon shell for given a drop position */
2512 PositionDesktopIcon(
2519 int pixmap_offset_x;
2520 int pixmap_offset_y;
2524 * We want to position the shell, so that the icon pixmap in the icon
2525 * gadget will appear at the same spot that the icon pixmap of the drag
2526 * cursor was when the drop occurred.
2529 /* First we caculate the top left corner of the drag pixmap by adding
2530 * the offset of the pixmap within the drag icon to the drop position. */
2531 drop_x += dragIconPixmapOffsetX;
2532 drop_y += dragIconPixmapOffsetY;
2534 /* In order to calculate the correct position of the dektop icon shell
2535 * such that the pixmap within the icon gadget will end up at the desired
2536 * position, we need to know the offset of the gadget's icon pixmap relative
2537 * to the desktop icon shell.
2538 * Since a desktop icon consists a frame widget, a drawing area and an
2539 * icon gadget (all within a popup shell), this offset is computed by adding
2540 * the frame width and and drawing area margins to the icon gadget's
2541 * highlight thickness.
2542 * The frame width is 3 and and and the drawing area margin width is 1
2543 * (both hardcoded in Desktop.c). We determine the remaining components
2544 * by looking at one of the existing desktop icon gadgets. */
2545 if (desktop_data != NULL &&
2546 desktop_data->numIconsUsed + desktop_data->numCachedIcons > 0)
2548 g = (DtIconGadget) desktop_data->desktopWindows[0]->iconGadget;
2550 pixmap_offset_y = 3 + 1 + G_HighlightThickness(g) + G_ShadowThickness(g);
2551 pixmap_offset_x += G_MarginWidth(g);
2552 pixmap_offset_y += G_MarginHeight(g);
2556 /* don't have an icon gadget; assume default values */
2557 pixmap_offset_x = pixmap_offset_y = 3 + 1 + 2 + 2 + 2;
2560 /* Finally, calculate the position of the dektop icon shell by
2561 * subtracting the offset of the gadget's icon pixmap from the
2562 * desired pixmap position */
2563 *root_x = drop_x - pixmap_offset_x;
2564 *root_y = drop_y - pixmap_offset_y;
2568 /* Code to reposition a desktop icon after a drag */
2571 RelocateDesktopIcon(
2572 DesktopRec * desktopRec,
2578 Dimension width, height;
2580 XSizeHints wmSizeHints;
2582 pu_shell = desktopRec->shell;
2585 XtSetArg (args[0], XmNwidth, &width);
2586 XtSetArg (args[1], XmNheight, &height);
2587 XtGetValues(pu_shell, args, 2);
2589 RegisterInGrid((int)width, (int)height,
2592 desktopRec->workspace_num,
2595 XtSetArg (args[0], XmNx, root_x);
2596 XtSetArg (args[1], XmNy, root_y);
2598 XtSetValues (pu_shell, args, 2);
2599 XRaiseWindow(XtDisplay(pu_shell), XtWindow(pu_shell));
2600 XSync(XtDisplay(pu_shell), False);
2602 RegisterInGrid((int)width, (int)height, root_x, root_y,
2603 desktopRec->workspace_num, True);
2605 desktopRec->root_x = root_x;
2606 desktopRec->root_y = root_y;
2607 SaveDesktopInfo(NORMAL_RESTORE);
2611 /************************************************************************
2614 * Loop through the file selection list to see if the specified
2617 ************************************************************************/
2621 FileMgrData *file_mgr_data,
2622 FileViewData *file_view_data )
2624 return file_view_data->selected;
2630 /************************************************************************
2633 * Display the icon representing file_data as selected.
2635 ************************************************************************/
2639 FileMgrData *file_mgr_data,
2640 FileViewData *file_view_data )
2643 file_view_data->selected = True;
2645 /* if this file has an up-to-date gadget, change its colors */
2646 if (!file_view_data->need_update)
2648 if (file_view_data->file_data->link == NULL)
2649 SetToSelectColors (file_view_data->widget,
2650 (Widget)((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window,
2653 SetToSelectColors (file_view_data->widget,
2654 (Widget)((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window,
2656 if (PositioningEnabledInView(file_mgr_data))
2657 RedrawOneGadget(file_view_data->widget, NULL, NULL);
2661 /************************************************************************
2664 * Display the icon representing file_data as not selected.
2666 ************************************************************************/
2670 FileMgrData *file_mgr_data,
2671 FileViewData *file_view_data )
2674 file_view_data->selected = False;
2676 /* if this file has an up-to-date gadget, change its colors */
2677 if (!file_view_data->need_update)
2679 if (file_view_data->file_data->link != NULL)
2680 SetToNormalColors (file_view_data->widget,
2681 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->file_window,
2682 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->main,
2685 SetToNormalColors (file_view_data->widget,
2686 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->file_window,
2687 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->main,
2690 if (PositioningEnabledInView(file_mgr_data))
2691 RedrawOneGadget(file_view_data->widget, NULL, NULL);
2695 /************************************************************************
2698 * Add the file to the selection list.
2700 ************************************************************************/
2704 FileMgrData *file_mgr_data,
2705 FileViewData *file_view_data )
2707 int selection_count;
2710 /* Add to the front of the selection list */
2711 selection_count = file_mgr_data->selected_file_count;
2712 file_mgr_data->selected_file_count++;
2714 file_mgr_data->selection_list = (FileViewData **)
2715 XtRealloc ((char *) file_mgr_data->selection_list,
2716 sizeof(FileViewData *) * (selection_count + 2));
2718 for (i = file_mgr_data->selected_file_count; i > 0; i--)
2719 file_mgr_data->selection_list[i] = file_mgr_data->selection_list[i-1];
2721 file_mgr_data->selection_list[0] = file_view_data;
2724 SetFileSelected(file_mgr_data, file_view_data);
2730 /************************************************************************
2733 * Remove the file from the selection list.
2735 ************************************************************************/
2739 FileMgrData *file_mgr_data,
2740 FileViewData *file_view_data,
2743 int selection_count;
2748 selection_count = file_mgr_data->selected_file_count;
2749 file_mgr_data->selected_file_count--;
2751 for (i = 0; i < selection_count; i++)
2752 if (file_mgr_data->selection_list[i] == file_view_data)
2755 for (j = i; j < selection_count - 1; j++)
2756 file_mgr_data->selection_list[j] = file_mgr_data->selection_list[j + 1];
2758 file_mgr_data->selection_list = (FileViewData **)
2759 XtRealloc ((char *) file_mgr_data->selection_list,
2760 sizeof(FileViewData *) * selection_count);
2761 file_mgr_data->selection_list[selection_count - 1] = NULL;
2764 SetFileUnselected(file_mgr_data, file_view_data);
2766 file_view_data->selected = False;
2772 /************************************************************************
2775 * Unselect all of the selected icons within the file manager data
2777 ************************************************************************/
2781 FileMgrData *file_mgr_data )
2783 FileViewData * file_view_data;
2786 FileViewData ** repaint_list;
2789 /* Get the color to reset the icons. */
2791 /* Loop through the selection set, resetting the visuals for */
2792 /* each selected icon. */
2794 if (!PositioningEnabledInView(file_mgr_data))
2796 for (i = 0; i < file_mgr_data->selected_file_count; i++)
2798 file_view_data = file_mgr_data->selection_list[i];
2799 SetFileUnselected(file_mgr_data, file_view_data);
2802 else if (file_mgr_data->selected_file_count > 0)
2805 * We can't simply redraw the selected files; we must also redraw
2806 * any unselected files which are higher on the stacking order.
2809 repaint_list = (FileViewData **)XtMalloc(sizeof(FileViewData *) *
2810 file_mgr_data->selected_file_count);
2812 /* Order the objects to be unselected */
2813 for (i = 0; i < file_mgr_data->selected_file_count; i++)
2815 file_view_data = file_mgr_data->selection_list[i];
2816 for (j = 0; j < i; j++)
2818 if (file_view_data->position_info->stacking_order <
2819 repaint_list[j]->position_info->stacking_order)
2821 /* Insert here, pushing down all lower entries */
2822 for (k = file_mgr_data->selected_file_count - 1; k > j; k--)
2823 repaint_list[k] = repaint_list[k-1];
2825 repaint_list[j] = file_view_data;
2830 /* Insert at end, if necessary */
2832 repaint_list[i] = file_view_data;
2835 /* Start the redraw process */
2836 i = file_mgr_data->selected_file_count - 1;
2837 bottom = repaint_list[i]->position_info;
2841 if ((i >= 0) && (bottom == repaint_list[i]->position_info))
2843 /* Unselect this object */
2844 SetFileUnselected(file_mgr_data, bottom->file_view_data);
2847 if(bottom->file_view_data != NULL &&
2848 !bottom->file_view_data->need_update)
2850 RedrawOneGadget(bottom->file_view_data->widget, NULL, NULL);
2852 bottom = bottom->prev;
2855 XtFree((char *)repaint_list);
2856 repaint_list = NULL;
2859 if (file_mgr_data->selection_list != NULL)
2861 XtFree ((char *) file_mgr_data->selection_list);
2862 file_mgr_data->selection_list = NULL;
2865 file_mgr_data->selection_list =
2866 (FileViewData **) XtMalloc (sizeof (FileViewData *));
2867 file_mgr_data->selection_list[0] = NULL;
2868 file_mgr_data->selected_file_count = 0;
2875 /************************************************************************
2878 * Select all of the files within the file manager data.
2880 ************************************************************************/
2884 FileMgrData *file_mgr_data )
2886 DirectorySet * directory_data;
2887 FileViewData ** order_list;
2888 int directory_count;
2889 int selection_count;
2893 FileViewData ** selection_list;
2896 if (PositioningEnabledInView(file_mgr_data))
2898 /* Force selection list order to match stacking order */
2899 selection_list = (FileViewData **)XtMalloc(sizeof(FileViewData *) *
2900 (file_mgr_data->num_objects));
2902 top = GetTopOfStack(file_mgr_data);
2903 selection_count = 0;
2904 for (i = 0; i < file_mgr_data->num_objects; i++)
2906 /* If the there isn't file_view_data for it
2907 Or if it's a parent folder (..go up)
2908 Don't bother to select them
2910 if( top->file_view_data != NULL
2911 && strcmp( top->name, ".." ) != 0 )
2913 selection_list[selection_count] = top->file_view_data;
2918 selection_list[selection_count] = NULL;
2920 /* Force redraw in bottom to top order */
2921 for (i = selection_count - 1; i >= 0; i--)
2923 if (!FileIsSelected(file_mgr_data, selection_list[i]))
2924 SetFileSelected(file_mgr_data, selection_list[i]);
2927 /* Free old selection list, and save new one */
2928 XtFree ((char *) file_mgr_data->selection_list);
2929 file_mgr_data->selection_list = selection_list;
2933 /* Free up any current selection and get the selection color. */
2935 if (file_mgr_data->selection_list != NULL)
2937 DeselectAllFiles( file_mgr_data );
2940 if (file_mgr_data->show_type == SINGLE_DIRECTORY)
2941 directory_count = 1;
2943 directory_count = file_mgr_data->directory_count;
2946 /* Loop through the set of directories checking each file view */
2947 /* structure to see if the icon is filtered. If not, select it */
2948 /* and increment the selection count. */
2950 selection_count = 0;
2952 /* For tree mode the index has to be -1 */
2954 i = (file_mgr_data->show_type == MULTIPLE_DIRECTORY)?-1:0;
2955 for (; i < directory_count; i++)
2957 directory_data = file_mgr_data->directory_set[i];
2958 order_list = directory_data->order_list;
2960 for (j = 0; j < directory_data->file_count; j++)
2962 /* If the file is being filtered out
2963 Or if it's a parent folder (..go up)
2964 Don't bother to select them
2966 if (order_list[j]->filtered == True
2967 || strcmp( order_list[j]->file_data->file_name, ".." ) == 0 )
2972 file_mgr_data->selection_list = (FileViewData **)
2973 XtRealloc ((char *) file_mgr_data->selection_list,
2974 sizeof(FileViewData *) * (selection_count + 1));
2976 file_mgr_data->selection_list[selection_count] = NULL;
2977 file_mgr_data->selection_list[selection_count - 1] = order_list[j];
2978 SetFileSelected(file_mgr_data, order_list[j]);
2983 file_mgr_data->selected_file_count = selection_count;
2985 if(file_mgr_data != trashFileMgrData)
2987 if (selection_count == 0)
2988 ActivateNoSelect ((FileMgrRec *)file_mgr_data->file_mgr_rec);
2989 else if (selection_count == 1)
2991 ActivateSingleSelect ((FileMgrRec *)file_mgr_data->file_mgr_rec,
2992 file_mgr_data->selection_list[0]->file_data->logical_type);
2995 ActivateMultipleSelect ((FileMgrRec *)file_mgr_data->file_mgr_rec);
3002 /************************************************************************
3005 * Set a single icon widget to selected colors.
3007 ************************************************************************/
3016 Pixel background_color;
3020 /* Get the select color to be used as the background of */
3021 /* the icon gadgets. */
3024 XtSetArg (args[j], XmNbackground, &background_color); j++;
3025 XtGetValues (file_window, args, j);
3028 if (background_color == white_pixel)
3030 XtSetArg (args[j], XmNbackground, black_pixel); j++;
3031 XtSetArg (args[j], XmNforeground, white_pixel); j++;
3033 else if (background_color == black_pixel)
3035 XtSetArg (args[j], XmNbackground, white_pixel); j++;
3036 XtSetArg (args[j], XmNforeground, black_pixel); j++;
3040 XtSetArg (args[j], XmNbackground, white_pixel); j++;
3041 XtSetArg (args[j], XmNforeground, black_pixel); j++;
3044 XtSetValues (widget, args, j);
3047 /************************************************************************
3050 * Set a single icon widget to normal colors.
3052 ************************************************************************/
3057 Widget bg_fg_colors,
3058 Widget top_shadow_colors,
3062 Pixel background_color;
3063 Pixel foreground_color;
3064 Pixel pixmap_background;
3065 DtIconGadget new = (DtIconGadget)widget;
3068 /* Get the colors to be used for drawing the icons */
3071 XtSetArg (args[j], XmNbackground, &background_color); j++;
3072 XtSetArg (args[j], XmNforeground, &foreground_color); j++;
3073 XtGetValues (bg_fg_colors, args, j);
3076 XtSetArg (args[j], XmNtopShadowColor, &pixmap_background); j++;
3077 XtGetValues (top_shadow_colors, args, j);
3081 if(type == LINK_FILE)
3082 XtSetArg (args[j], XmNforeground, pixmap_background); j++;
3085 XtSetArg (args[j], XmNforeground, foreground_color); j++;
3087 if (background_color == white_pixel)
3089 XtSetArg (args[j], XmNbackground, white_pixel); j++;
3091 else if (background_color == black_pixel)
3093 XtSetArg (args[j], XmNbackground, black_pixel); j++;
3097 XtSetArg (args[j], XmNbackground, background_color); j++;
3100 /* we want to make sure the armed value is off so that it will get
3102 if(new->icon.armed == True)
3104 new->icon.armed = False;
3107 XtSetValues (widget, args, j);
3112 * When a text widget is destroyed, we need to free up the string we
3113 * attached as userData.
3119 XtPointer client_data,
3120 XtPointer call_data)
3125 XtSetArg(args[0], XmNuserData, &str);
3126 XtGetValues(w, args, 1);
3133 GetInsertPosition( x1, x2, fontList, name )
3136 XmFontList fontList;
3139 GetInsertPosition( int x1, int x2, XmFontList fontList, char * name )
3142 int i, width, stringWidth;
3151 while ((len = mblen(tmp, MB_CUR_MAX)) > 0)
3159 string = XmStringCreateLocalized( name );
3160 stringWidth = XmStringWidth( fontList, string );
3161 XmStringFree( string );
3163 if( stringWidth > width )
3173 CreateNameChangeDialog (
3175 FileViewData *file_view_data,
3176 XtPointer client_data,
3179 XRectangle textExtent;
3180 FileMgrData * file_mgr_data;
3181 DesktopRec * desktopWindow;
3182 Widget parent = XtParent(w);
3187 Widget frame, shell;
3188 Dimension fHeight, sHeight;
3190 Dimension tWidth, tHeight;
3193 XtTranslations trans_table;
3194 XmFontList fontList;
3195 Dimension stringWidth;
3196 XmString fileNameString;
3197 char tmpBuf[MAX_PATH];
3199 _DtIconGetTextExtent_r(w, &textExtent);
3203 char buf[MAXPATHLEN];
3205 desktopWindow = (DesktopRec *)client_data;
3206 if(desktopWindow->text != NULL)
3209 sprintf( buf, "%s:%s", home_host_name, root_title );
3212 * If the object is on the DESKTOP and its name is root_title, then
3213 * the user can't rename it.
3215 if( strcmp( buf, desktopWindow->title ) == 0
3216 && strcmp( desktopWindow->dir_linked_to, "/" ) == 0
3217 && strcmp( desktopWindow->file_name, "." ) == 0 )
3221 file_mgr_data = (FileMgrData *)client_data;
3223 /* if the object is in the trash, can't rename it */
3225 && file_mgr_data == trashFileMgrData )
3228 /* if the object is an action, can't rename it */
3229 if( DtDtsDataTypeIsAction( file_view_data->file_data->logical_type ) )
3231 char *tmpStr, *title, *msg;
3233 tmpStr = GETMESSAGE(10, 39, "Rename error");
3234 title = XtNewString(tmpStr);
3235 tmpStr = GETMESSAGE(10, 40, "This object is an Action.\nAction icon labels cannot be directly renamed." );
3236 msg = XtNewString(tmpStr);
3238 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
3243 else if(file_view_data->file_data->action_name)
3245 char *tmpStr, *title, *msg;
3247 tmpStr = GETMESSAGE(10, 39, "Rename error");
3248 title = XtNewString(tmpStr);
3249 tmpStr = GETMESSAGE(11, 32, "Cannot rename %s");
3250 msg = XtMalloc(strlen(tmpStr)+strlen(file_view_data->file_data->
3252 sprintf(msg,tmpStr,file_view_data->file_data->action_name);
3254 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
3261 * The selected objects name is attached as 'userData' to text field,
3262 * to aid us in mapping back to the original object later.
3264 if( type == DESKTOP &&
3265 ( (strcmp(".", file_view_data->file_data->file_name) == 0)
3266 || strcmp("..", file_view_data->file_data->file_name) == 0) )
3268 name = XtNewString(desktopWindow->file_name);
3270 else if ( strcmp(".", file_view_data->file_data->file_name) == 0 ||
3271 strcmp("..", file_view_data->file_data->file_name) == 0 )
3276 name = XtNewString(file_view_data->file_data->file_name);
3278 /* set up translations in main edit widget */
3279 trans_table = XtParseTranslationTable(translations_escape);
3281 /* We need to set the width of the text widget.
3282 Can't use XmNcolumns because of the double-byte.
3285 XtSetArg( args[0], XmNfontList, &fontList );
3286 XtGetValues( file_view_data->widget, args, 1 );
3288 sprintf( tmpBuf, "%s ", file_view_data->file_data->file_name );
3289 fileNameString = XmStringCreateLocalized( tmpBuf );
3290 stringWidth = XmStringWidth( fontList, fileNameString );
3291 XmStringFree( fileNameString );
3294 XtSetArg(args[n], XmNuserData, name); n++;
3295 XtSetArg(args[n], XmNmarginHeight, 0); n++;
3296 XtSetArg(args[n], XmNmarginWidth, 0); n++;
3297 XtSetArg(args[n], XmNvalue, name); n++;
3298 XtSetArg(args[n], XmNwidth, stringWidth); n++;
3303 text = XmCreateTextField(parent, "nameChangeT_DT", args, n);
3304 XtAddCallback (text, XmNactivateCallback, ChangeIconNameDT,
3305 (XtPointer)desktopWindow);
3306 XtAddCallback(text, XmNhelpCallback, (XtCallbackProc)DTHelpRequestCB,
3307 HELP_NAMECHANGE_DIALOG_STR);
3308 desktopWindow->text = text;
3310 frame = XtParent(parent);
3311 shell = XtParent(frame);
3312 XtSetArg(args[0], XmNheight, &fHeight);
3313 XtGetValues(frame, args, 1);
3314 XtSetArg(args[0], XmNheight, &sHeight);
3315 XtGetValues(shell, args, 1);
3319 text = XmCreateTextField(parent, "nameChangeT", args, n);
3320 file_mgr_data->renaming = file_view_data;
3321 XtAddCallback (text, XmNmotionVerifyCallback,
3322 (XtCallbackProc)ChangeIconName,
3323 (XtPointer)file_mgr_data);
3324 XtAddCallback (text, XmNmodifyVerifyCallback,
3325 (XtCallbackProc)ChangeIconName,
3326 (XtPointer)file_mgr_data);
3327 XtAddCallback (text, XmNactivateCallback,
3328 (XtCallbackProc)ChangeIconName,
3329 (XtPointer)file_mgr_data);
3330 XtAddCallback(text, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
3331 HELP_NAMECHANGE_DIALOG_STR);
3334 XtAddCallback (text, XmNdestroyCallback, DestroyIconName, (XtPointer)NULL);
3336 /* set up translations in main edit widget */
3337 XtOverrideTranslations(text, trans_table);
3339 if(type == DESKTOP && sHeight > fHeight) {
3340 /* status area has been attached in multi-byte case */
3346 y = textExtent.y - (Dimension)(text->core.height - textExtent.height);
3350 Window rootWindow, childWindow;
3351 int pX, pY, rootX, rootY, insertPosition;
3354 XQueryPointer( XtDisplay( parent ), XtWindow( file_view_data->widget ),
3355 &rootWindow, &childWindow, &rootX, &rootY, &pX, &pY,
3358 insertPosition = strlen( name );
3361 if( type != DESKTOP )
3363 if( pX > (int) x && pX < (int) x + (int) stringWidth )
3364 insertPosition = GetInsertPosition( x, pX, fontList, name );
3366 insertPosition = strlen( name );
3369 insertPosition = GetInsertPosition( x, x + pX, fontList, name );
3372 XtSetArg( args[n], XmNcursorPosition, insertPosition); n++;
3373 XtSetArg( args[n], XmNx, x); n++;
3374 XtSetArg( args[n], XmNy, y); n++;
3375 XtSetValues (text, args, n);
3382 Dimension shadowThickness;
3384 unsigned char flags;
3386 XtSetArg (args[0], XmNwidth, &tWidth);
3387 XtSetArg (args[1], XmNheight, &tHeight);
3388 XtGetValues (text, args, 2);
3390 XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
3391 XtGetValues (desktopWindow->iconGadget, args, 1);
3393 _DtIconGetIconRects((DtIconGadget)desktopWindow->iconGadget,
3394 &flags, &rect[0], &rect[1]);
3398 rect[0].width += 2*shadowThickness;
3399 rect[0].height += 2*shadowThickness;
3402 if(type == DESKTOP && sHeight > fHeight) {
3403 /* status area has been attached in multi-byte case */
3406 rect[1].width = 2*shadowThickness + tWidth;
3407 rect[1].height = sHeight - y - 1;
3412 rect[1].width = shadowThickness + tWidth;
3413 rect[1].height = tHeight;
3416 if(rect[0].width > rect[1].width)
3417 rect[1].width = rect[0].width;
3419 XShapeCombineRectangles(XtDisplay(desktopWindow->shell),
3420 XtWindow(desktopWindow->shell),
3421 ShapeBounding, 0, 0, &rect[0], 2,
3422 ShapeSet, Unsorted);
3425 XtManageChild(text);
3426 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
3430 FileMgrRec *file_mgr_rec;
3432 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3433 file_mgr_rec->menuStates &= ~RENAME;
3437 /************************************************************************
3439 * SavePositionalData
3440 * Save the desktop icon positional data.
3442 ************************************************************************/
3445 SavePositionalData (
3447 FileMgrData * file_mgr_data,
3452 FILE * fd_stream = fdopen(fd, "w");
3453 ObjectPosition * ptr;
3458 if(file_mgr_data->positionEnabled == RANDOM_ON &&
3459 file_mgr_data->object_positions &&
3460 file_mgr_data->show_type == SINGLE_DIRECTORY &&
3461 file_mgr_data->host != NULL)
3463 /* Number of object positions */
3464 fprintf(fd_stream, "*%s.%s.%s.%s: %d\n#\n", name_list[0], name_list[1],
3465 name, "num_positions", file_mgr_data->num_objects);
3467 for (i = 0; i < file_mgr_data->num_objects; i++)
3469 ptr = file_mgr_data->object_positions[i];
3470 fprintf(fd_stream, "*%s.%s.%s.%s%d: %s %d %d %d\n",
3471 name_list[0], name_list[1], name, "object", i,
3475 ptr->stacking_order);
3480 /* Number of object positions */
3481 fprintf(fd_stream, "*%s.%s.%s.%s: %d\n#\n", name_list[0], name_list[1],
3482 name, "num_positions", 0);
3490 /************************************************************************
3492 * RestorePositionalData
3493 * Restore the desktop icon positional data.
3495 ************************************************************************/
3498 RestorePositionalData (
3501 FileMgrData * file_mgr_data,
3504 XrmName xrm_name[10];
3507 char objectName[20];
3508 XrmRepresentation rep_type;
3513 ObjectPosition * ptr;
3517 while (name_list[i])
3519 xrm_name[i] = XrmStringToQuark(name_list[i]);
3522 xrm_name[i++] = XrmStringToQuark(name);
3523 xrm_name[i] = XrmStringToQuark("num_positions");
3524 xrm_name[i+1] = '\0';
3526 /* Find out how many objects there are to be loaded */
3527 file_mgr_data->object_positions = NULL;
3529 if (XrmQGetResource (db, xrm_name, NULL, &rep_type, &value))
3531 if ((num_objects = atoi (value.addr)) <= 0)
3535 file_mgr_data->object_positions = (ObjectPosition **)XtMalloc(
3536 sizeof(ObjectPosition *) * num_objects);
3540 file_mgr_data->num_objects = num_objects;
3542 for (j = 0; j < num_objects; j++)
3544 sprintf(objectName, "object%d", j);
3545 xrm_name[i] = XrmStringToQuark(objectName);
3546 ptr = file_mgr_data->object_positions[j] = (ObjectPosition *)
3547 XtMalloc(sizeof(ObjectPosition));
3549 XrmQGetResource (db, xrm_name, NULL, &rep_type, &value);
3550 str = (char *)value.addr;
3551 obj_name = XtMalloc(strlen(str) + 1);
3552 sscanf((char *)value.addr, "%s %d %d %d", obj_name, &x, &y, &s_order);
3553 ptr->name = obj_name;
3556 ptr->stacking_order = s_order;
3557 ptr->in_use = False;
3558 ptr->late_bind = False;
3559 ptr->file_view_data = NULL;
3564 /* Repair all of the next and prev pointers */
3565 RepairStackingPointers(file_mgr_data);
3571 FileMgrData * file_mgr_data)
3574 XmManagerWidget file_window;
3576 FileMgrRec * file_mgr_rec;
3578 file_mgr_data->renaming = NULL;
3580 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3581 file_window = (XmManagerWidget) file_mgr_rec->file_window;
3582 for (i = 0; i < file_window->composite.num_children; i++)
3584 if (XmIsTextField(file_window->composite.children[i]) &&
3585 !file_window->composite.children[i]->core.being_destroyed)
3587 XtUnmanageChild(file_window->composite.children[i]);
3588 XtDestroyWidget(file_window->composite.children[i]);
3597 FileMgrData * file_mgr_data)
3600 FileMgrRec * file_mgr_rec;
3603 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3605 XtSetArg (args[0], XmNallowShellResize, False);
3606 XtSetValues(file_mgr_rec->shell, args, 1);
3608 XtUnmanageChild(file_mgr_rec->current_directory_text);
3610 XtSetArg (args[0], XmNallowShellResize, True);
3611 XtSetValues(file_mgr_rec->shell, args, 1);
3613 file_mgr_data->fast_cd_enabled = False;
3618 * Function to force a redraw of a single gadget.
3628 if (child->core.widget_class->core_class.expose)
3629 (*(child->core.widget_class->core_class.expose))(child, event, region);
3634 * Given a region describing the area to be repainted, repaint all icons,
3635 * in bottom to top order, which fall into this region.
3640 FileMgrData * file_mgr_data,
3646 ObjectPosition * bottom = GetBottomOfStack(file_mgr_data);
3648 /* Redraw all affected gadgets */
3651 if (!bottom->late_bind)
3653 if (bottom->file_view_data != NULL &&
3654 !bottom->file_view_data->need_update)
3656 child = bottom->file_view_data->widget;
3657 if (XRectInRegion(region, child->core.x, child->core.y,
3658 child->core.width, child->core.height))
3660 RedrawOneGadget(child, event, region);
3665 bottom = bottom->prev;
3671 * This function will extract all exposure events intended for this file
3672 * window, combine them into a single region, and then determine which of
3673 * the file icons need to be redrawn. It is a two step process, as
3674 * described by the comments in the code.
3678 RedisplayUsingStackingOrder (
3679 FileMgrData * file_mgr_data,
3686 FileViewData * file_view_data;
3687 ObjectPosition * bottom;
3688 ObjectPosition * top;
3689 Region redrawRegion = XCreateRegion();
3692 int numChildren = 0;
3693 Widget * children = NULL;
3694 Region widget_region;
3697 /* Get the initial region to redraw */
3699 XUnionRegion(redrawRegion, region, redrawRegion);
3702 rect.x = event->xexpose.x;
3703 rect.y = event->xexpose.y;
3704 rect.height = event->xexpose.height;
3705 rect.width = event->xexpose.width;
3707 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
3711 * Capture and encompass any other exposure events which are destined for
3712 * us, but are waiting in the wings.
3714 while (XCheckWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask, &expEvent))
3716 rect.x = expEvent.xexpose.x;
3717 rect.y = expEvent.xexpose.y;
3718 rect.height = expEvent.xexpose.height;
3719 rect.width = expEvent.xexpose.width;
3721 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
3724 /* Nothing to do if the redraw region is empty */
3725 if (XEmptyRegion(redrawRegion))
3727 XDestroyRegion(redrawRegion);
3732 * Starting at the top of the stack, find any items which fall into
3733 * the redraw region. As items are found which need to be redrawn,
3734 * subtract them from the redraw region, so that any items lower on the
3735 * stack which might be under these gadgets, but are within the region,
3738 * The second phase is to start at the bottom of the stack, and start
3739 * redrawing the gadgets which fell into the region, along with any
3740 * other gadgets on top of these (since they too now need to be redrawn.
3742 top = GetTopOfStack(file_mgr_data);
3748 if (!top->late_bind)
3750 file_view_data = top->file_view_data;
3751 if(file_view_data != NULL)
3753 child = file_view_data->widget;
3755 if (child && XmIsGadget(child) && XtIsManaged(child))
3757 widget_region = XCreateRegion();
3758 WidgetRectToRegion(file_mgr_data, child, widget_region);
3759 XIntersectRegion(redrawRegion, widget_region, widget_region);
3760 if (!XEmptyRegion(widget_region))
3762 XSubtractRegion(redrawRegion, widget_region, redrawRegion);
3763 children = (Widget *)XtRealloc((char *)children,
3764 (numChildren + 1) * sizeof(Widget));
3765 children[numChildren] = child;
3768 XDestroyRegion(widget_region);
3772 top = (ObjectPosition *)top->next;
3775 /* Now, start redrawing, in bottom to top order */
3776 bottom = GetBottomOfStack(file_mgr_data);
3780 if (!bottom->late_bind)
3782 file_view_data = bottom->file_view_data;
3783 if(file_view_data != NULL)
3785 child = file_view_data->widget;
3787 if (child && XmIsGadget(child) && XtIsManaged(child))
3789 widget_region = XCreateRegion();
3790 WidgetRectToRegion(file_mgr_data, child, widget_region);
3791 if ((numChildren >= 0) && (children[numChildren] == child))
3793 XUnionRegion(redrawRegion, widget_region, redrawRegion);
3794 RedrawOneGadget(child, event, redrawRegion);
3799 /* Do we overlap something which was previously redrawn? */
3800 tmp_region = XCreateRegion();
3801 XIntersectRegion(redrawRegion, widget_region, tmp_region);
3802 if (!XEmptyRegion(tmp_region))
3804 XUnionRegion(redrawRegion, widget_region, redrawRegion);
3805 RedrawOneGadget(child, event, redrawRegion);
3807 XDestroyRegion(tmp_region);
3809 XDestroyRegion(widget_region);
3813 bottom = (ObjectPosition *)bottom->prev;
3816 XDestroyRegion(redrawRegion);
3817 XtFree((char *)children);
3823 * This is the function which we use to override the class expose function
3824 * for the drawing area widget. It allows us to catch exposure events
3825 * intended for the desktop, so that we can force the redrawing of the
3826 * gadgets to occur occording to the stacking order.
3830 DrawingAreaRedisplay (
3836 XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid;
3837 XmDrawingAreaCallbackStruct cb;
3838 FileMgrData * file_mgr_data;
3840 cb.reason = XmCR_EXPOSE;
3842 cb.window = XtWindow (da);
3844 DPRINTF2(("DrawingAreaRedisplay: event %d, x/y %d/%d, wd/ht %d/%d\n",
3846 event->xexpose.x, event->xexpose.y,
3847 event->xexpose.width, event->xexpose.height));
3849 file_mgr_data = ReturnDesktopPtr(wid);
3851 if (file_mgr_data && PositioningEnabledInView(file_mgr_data))
3852 RedisplayUsingStackingOrder(file_mgr_data, (Widget)da, event, region);
3854 XmeRedisplayGadgets((Widget)da, event, region);
3856 XtCallCallbackList ((Widget)da, da->drawing_area.expose_callback, &cb);
3861 * Return the bottom of the stacking order list.
3866 FileMgrData * file_mgr_data)
3872 for (i = 0, bottom = NULL; i < file_mgr_data->num_objects; i++)
3874 if (file_mgr_data->object_positions[i]->next == NULL)
3876 bottom = file_mgr_data->object_positions[i];
3886 * Return the top of the stacking order list.
3891 FileMgrData * file_mgr_data)
3896 for (i = 0, top = NULL; i < file_mgr_data->num_objects; i++)
3898 if (file_mgr_data->object_positions[i]->prev == NULL)
3900 top = file_mgr_data->object_positions[i];
3910 * Move an object up in the stacking order. Will not work for moving an
3911 * object further down in the stacking order, but we currently have no
3912 * need for doing that.
3914 * NOTE: The top of the stack is '1', not '0'!!
3918 RepositionUpInStack (
3919 FileMgrData * file_mgr_data,
3924 ObjectPtr ptr, ptr2, savePtr;
3926 XmManagerWidget file_window;
3928 if (oldPos == newPos)
3931 ptr = GetTopOfStack(file_mgr_data);
3933 /* Find where item is to be inserted */
3934 while (ptr->stacking_order != newPos)
3937 /* Find where item currently is */
3939 while (ptr2->stacking_order != oldPos)
3944 if(savePtr->file_view_data == NULL)
3947 /* Remove from its current location */
3949 ptr2->prev->next = ptr2->next;
3951 ptr2->next->prev = ptr2->prev;
3953 /* Link into new position */
3954 ptr2->prev = ptr->prev;
3957 ptr2->prev->next = ptr2;
3960 /* Update the stacking order value */
3961 for (i = newPos; i <= oldPos; i++)
3963 ptr2->stacking_order = i;
3967 /* Update the children's list for the file window */
3968 file_window = (XmManagerWidget)
3969 (((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
3971 /* Find the affect child */
3972 for (i = 0; (i < file_window->composite.num_children) &&
3973 (file_window->composite.children[i] != savePtr->file_view_data->widget);
3976 /* Push intervening entries down */
3977 for (j = i; j >= newPos; j--)
3978 file_window->composite.children[j] = file_window->composite.children[j-1];
3980 /* Insert into new position in children list */
3981 file_window->composite.children[newPos-1] = savePtr->file_view_data->widget;
3986 * Reorder the file window's children list so that it matches the stacking
3991 ReorderChildrenList (
3992 XmManagerWidget file_window,
3999 Widget * children = file_window->composite.children;
4002 for (i = 0; i < manageCount; i++)
4003 children[i] = manage[i];
4005 for (j = 0; j < unmanageCount; j++)
4006 children[i++] = unmanage[j];
4011 * If positional information is available for the indicated file, then
4012 * return it; if not, then return NULL.
4016 FindCurrentPosition (
4017 FileMgrData * file_mgr_data,
4023 for (i = 0; i < file_mgr_data->num_objects; i++)
4025 if (strcmp(file_name, file_mgr_data->object_positions[i]->name) == 0)
4028 file_mgr_data->object_positions[i]->in_use = True;
4029 return(file_mgr_data->object_positions[i]);
4038 RepairStackingPointers (
4039 FileMgrData * file_mgr_data)
4044 ObjectPosition * ptr;
4045 ObjectPosition * prev;
4047 for (i = 1, prev = NULL; i <= file_mgr_data->num_objects; i++)
4049 for (j = 0; j < file_mgr_data->num_objects; j++)
4051 ptr = file_mgr_data->object_positions[j];
4052 if (ptr->stacking_order == i)
4067 * Reorder the children's list for the file_window, so that it matches
4068 * the stacking order. Also, set up all next and previous pointers.
4073 FileMgrData * file_mgr_data)
4076 FileMgrRec * file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
4077 XmManagerWidget file_window;
4082 ObjectPosition * top;
4085 file_window = (XmManagerWidget) file_mgr_rec->file_window;
4086 managed = (Widget *)XtMalloc(sizeof(Widget *) *
4087 file_window->composite.num_children);
4088 unmanaged = (Widget *)XtMalloc(sizeof(Widget *) *
4089 file_window->composite.num_children);
4090 num_managed = num_unmanaged = 0;
4092 top = GetTopOfStack(file_mgr_data);
4095 if (top->file_view_data != NULL && top->file_view_data->widget != NULL)
4096 managed[num_managed++] = top->file_view_data->widget;
4100 /* All the rest get put at the end of the children's list */
4101 for (i = 0; i < file_window->composite.num_children; i++)
4103 for (j = 0; j < num_managed; j++)
4105 if (managed[j] == file_window->composite.children[i])
4109 if (j >= num_managed)
4110 unmanaged[num_unmanaged++] = file_window->composite.children[i];
4113 ReorderChildrenList(file_window, managed, num_managed, unmanaged,
4115 XtFree( (char *)managed );
4116 XtFree( (char *)unmanaged );
4126 FileViewData * file_view_data,
4127 XtCallbackProc callback,
4128 XtPointer callback_data)
4133 if (file_view_data->displayed)
4135 /*************************/
4136 /* icon gadget displayed */
4137 /*************************/
4138 DtIconGadget g = (DtIconGadget) file_view_data->widget;
4139 unsigned char operations;
4141 /* find defined operations (M/C/L) for file type */
4142 operations = TypeToDropOperations(
4143 file_view_data->file_data->logical_type);
4145 /* if icon gadget not yet registered as a drop site, do so now */
4146 if (!file_view_data->registered)
4148 /* register drop site for MCL but make drop site inactive */
4149 XtSetArg (args[0], XmNdropSiteOperations,
4150 XmDROP_COPY | XmDROP_MOVE | XmDROP_LINK);
4151 XtSetValues (file_view_data->widget, args, 1);
4153 file_view_data->registered = True;
4158 /***********************************/
4159 /* file has associated MCL actions */
4160 /***********************************/
4161 XRectangle rects[2];
4162 unsigned char flags;
4165 Dimension s_t, adj_xy, adj_size;
4167 /* ensure drop site operations and drop area are correct */
4168 _DtIconGetIconRects(g, &flags, &rects[0], &rects[1]);
4171 * Compute adjustments to the drop area:
4173 * - Add shadowThickness to the drop area:
4174 * The icon gadget leaves space of width shadowThickness around
4175 * the pixmap and label; use this space to make the drop zone
4178 * - Compensate for bug in drop zone registration/drawing:
4179 * For some reason the drop zone displayed on the screen is
4180 * actually smaller than the rectangle we register:
4181 * The drag&drop library seems to reduce the size of the drop
4182 * area by the value of highlightThickness at the top and left
4183 * border and by highlightThickness-1 at the bottom and right.
4184 * Is this a Motif drag&drop bug?
4185 * We compensate by registering a larger rectangle.
4187 s_t = G_ShadowThickness(g);
4188 adj_xy = s_t + G_HighlightThickness(g);
4189 adj_size = adj_xy + s_t + G_HighlightThickness(g) - 1;
4191 if (flags & XmPIXMAP_RECT)
4193 rects[0].x -= g->rectangle.x + adj_xy;
4194 rects[0].y -= g->rectangle.y + adj_xy;
4195 rects[0].width += adj_size;
4196 rects[0].height += adj_size;
4200 if (flags & XmLABEL_RECT)
4202 rects[1].x -= g->rectangle.x + adj_xy;
4203 rects[1].y -= g->rectangle.y + adj_xy;
4204 rects[1].width += adj_size;
4205 rects[1].height += adj_size;
4206 if (!numRects) rects[0] = rects[1];
4212 XtSetArg(args[n], XmNdropRectangles, rects); n++;
4213 XtSetArg(args[n], XmNnumDropRectangles, numRects); n++;
4215 XtSetArg (args[n], XmNdropSiteOperations, operations); n++;
4217 XmDropSiteUpdate (file_view_data->widget, args, n);
4218 g->icon.operations = operations;
4220 /* add client data */
4221 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4222 XtAddCallback(file_view_data->widget, XmNdropCallback,
4223 callback, callback_data);
4227 /*********************************************/
4228 /* file does not have associated MCL actions */
4229 /*********************************************/
4230 /* make drop site inactive */
4231 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
4232 XmDropSiteUpdate (file_view_data->widget, args, 1);
4233 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4238 /*****************************/
4239 /* icon gadget not displayed */
4240 /*****************************/
4241 if (file_view_data->registered)
4243 /***************************************/
4244 /* icon gadget registered as drop site */
4245 /***************************************/
4246 /* make drop site inactive */
4247 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
4248 XmDropSiteUpdate (file_view_data->widget, args, 1);
4249 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4257 * TypeToDropOperations
4261 TypeToDropOperations (
4265 unsigned char operations = 0L;
4268 /* does object have MOVE, COPY, and/or LINK actions */
4269 /* -- or no actions at all */
4270 if (action = DtDtsDataTypeToAttributeValue(file_type,
4271 DtDTS_DA_MOVE_TO_ACTION,
4274 operations = operations | XmDROP_MOVE;
4275 DtDtsFreeAttributeValue(action);
4277 if (action = DtDtsDataTypeToAttributeValue(file_type,
4278 DtDTS_DA_COPY_TO_ACTION,
4281 operations = operations | XmDROP_COPY;
4282 DtDtsFreeAttributeValue(action);
4284 if (action = DtDtsDataTypeToAttributeValue(file_type,
4285 DtDTS_DA_LINK_TO_ACTION,
4288 operations = operations | XmDROP_LINK;
4289 DtDtsFreeAttributeValue(action);
4302 unsigned char dropOperation,
4303 char * logical_type)
4307 /* retrieve action from database based on dropOperation */
4308 switch(dropOperation)
4311 action = DtDtsDataTypeToAttributeValue(logical_type,
4312 DtDTS_DA_MOVE_TO_ACTION,
4316 action = DtDtsDataTypeToAttributeValue(logical_type,
4317 DtDTS_DA_COPY_TO_ACTION,
4321 action = DtDtsDataTypeToAttributeValue(logical_type,
4322 DtDTS_DA_LINK_TO_ACTION,
4335 * Given a fileViewData pointer, determine if it is part of a FileMgrData,
4336 * or a DesktopRec; return the appropriate pointer.
4342 FileViewData * fileViewData,
4343 FileMgrData ** fileMgrData,
4344 DesktopRec ** desktopRec)
4349 *fileMgrData = NULL;
4351 for (i = 0; i < desktop_data->numIconsUsed; i++)
4353 if (desktop_data->desktopWindows[i]->file_view_data == fileViewData)
4355 *desktopRec = desktop_data->desktopWindows[i];
4360 *fileMgrData = (FileMgrData *)
4361 ((DirectorySet *)fileViewData->directory_set)->file_mgr_data;
4366 /******************************************************************
4368 * PositionFileView -
4369 * Given a particular file, position the file view that file
4370 * is in on that particular file.
4372 ********************************************************************/
4375 FileViewData *file_view_data,
4376 FileMgrData *file_mgr_data)
4380 int value, size, increment, page, max;
4381 FileMgrRec * file_mgr_rec = (FileMgrRec *)(file_mgr_data->file_mgr_rec);
4384 /* if the file is filtered we can't highlight it! */
4385 if(!file_view_data->displayed)
4388 /* Get the y location of the icon_gadget */
4389 y = file_view_data->y - file_mgr_data->grid_height;
4393 * 1) not sure exactly how slow this is, but there seems to be no other
4394 * way to do this. (CDExc23427)
4395 * 2) XmScrollVisible does not work if the work window is not managed...
4396 * so, we call it, and then get the appropriate x,y back from the
4397 * scroll bars and set them (CDExc23428) */
4398 p = XtVaCreateManagedWidget("positionicon", xmGadgetClass,
4399 file_mgr_rec->file_window,
4400 XmNmappedWhenManaged, False,
4401 XmNx, file_view_data->x,
4403 XmNwidth, file_mgr_data->grid_width,
4404 XmNheight, file_mgr_data->grid_height,
4407 XmScrollVisible(file_mgr_rec->scroll_window, p,
4408 XSPACING, YSPACING(file_mgr_data));
4412 XmScrollBarGetValues(file_mgr_rec->horizontal_scroll_bar,
4413 &value, &size, &increment, &page);
4414 x = -((Position) value);
4416 XmScrollBarGetValues(file_mgr_rec->vertical_scroll_bar,
4417 &value, &size, &increment, &page);
4418 y = -((Position) value);
4420 XtVaSetValues(file_mgr_rec->file_window, XmNx, x, XmNy, y, NULL);
4425 InMultipleObjectRegion (FileMgrData * file_mgr_data, FileViewData * fileViewData)
4428 for( i = 0; i < file_mgr_data->selected_file_count; ++i )
4429 if( strcmp( file_mgr_data->selection_list[i]->file_data->file_name, fileViewData->file_data->file_name ) == 0 )
4437 XtPointer client_data,
4439 FileMgrData *file_mgr_data)
4441 FileMgrRec *file_mgr_rec;
4443 FileViewData *fileViewData = NULL;
4444 int i, num_of_children, obj_btns;
4445 XmManagerWidget action_pane;
4446 XmString label_string;
4449 /* set number of popup children based on annotation */
4450 num_of_children = FM_POPUP_CHILDREN_NA;
4451 obj_btns = OBJ_BTNS_NA;
4453 /* attach the popup widget info to the menu */
4454 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
4455 XtSetArg(args[0], XmNuserData, file_mgr_rec);
4456 XtSetValues(fileMgrPopup.menu, args, 1);
4459 file_mgr_data->popup_menu_icon = NULL;
4461 /* we are dealing with a white space popup */
4463 && (client_data == NULL)
4465 && (file_mgr_data->selected_file_count == 0)
4469 DirectorySet *directory_set;
4471 /* retrieve the fileViewData for the current directory */
4472 directory_set = file_mgr_data->directory_set[0];
4473 for (i = 0; i < directory_set->file_count; i++)
4475 if(strcmp(directory_set->order_list[i]->file_data->file_name, ".")
4478 fileViewData = directory_set->order_list[i];
4483 /* manage the white space buttons and unmanage the object buttons */
4484 XtManageChildren(fileMgrPopup.wsPopup, WS_BTNS);
4485 XtUnmanageChildren(fileMgrPopup.objPopup, obj_btns);
4486 XtUnmanageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4488 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_UNSELECTALL]);
4490 if(file_mgr_data == trashFileMgrData)
4492 /* Set popup menu label */
4493 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 2, "Current Folder")));
4494 XtSetArg (args[0], XmNlabelString, label_string);
4495 XtSetValues (fileMgrPopup.title, args, 1);
4496 XtManageChild(fileMgrPopup.title);
4497 XmStringFree (label_string);
4499 /* trash white space popup -- unmanage the properties and show */
4500 /* hidden files buttons */
4501 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4502 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_FIND]);
4503 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN]);
4505 /* align the remaining buttons */
4506 XtSetArg(args[0], XmNmarginLeft, 0);
4507 if( PositioningEnabledInView( file_mgr_data ) )
4509 file_mgr_rec->menuStates |= CLEAN_UP;
4510 XtSetValues(fileMgrPopup.wsPopup[BTN_CLEANUP], args, 1);
4514 file_mgr_rec->menuStates &= ~(CLEAN_UP);
4515 XtUnmanageChild( fileMgrPopup.wsPopup[BTN_CLEANUP] );
4517 XtSetValues(fileMgrPopup.wsPopup[BTN_SELECTALL], args, 1);
4519 /* unmanage the action portion of the popup menu */
4520 XtUnmanageChild(fileMgrPopup.action_separator);
4522 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4523 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4524 XtUnmanageChild(action_pane->composite.children[i]);
4530 /* manage the properties and show hidden files buttons */
4531 if( file_mgr_data->toolbox )
4532 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4534 XtManageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4535 XtManageChild(fileMgrPopup.wsPopup[BTN_FIND]);
4536 XtManageChild(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN]);
4538 /* Set popup menu label */
4539 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 2, "Current Folder")));
4540 XtSetArg (args[0], XmNlabelString, label_string);
4541 XtSetValues (fileMgrPopup.title, args, 1);
4542 XtManageChild(fileMgrPopup.title);
4543 XmStringFree (label_string);
4545 /* align the menu buttons */
4546 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4547 XtSetArg(args[0], XmNmarginLeft, &margin);
4548 XtGetValues(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], args, 1);
4549 XtSetArg(args[0], XmNmarginLeft, margin);
4551 if( PositioningEnabledInView( file_mgr_data ) )
4553 file_mgr_rec->menuStates |= CLEAN_UP;
4554 XtSetValues(fileMgrPopup.wsPopup[BTN_CLEANUP], args, 1);
4558 file_mgr_rec->menuStates &= ~(CLEAN_UP);
4559 XtUnmanageChild( fileMgrPopup.wsPopup[BTN_CLEANUP] );
4562 XtSetValues(fileMgrPopup.wsPopup[BTN_SELECTALL], args, 1);
4566 if (file_mgr_data->show_hid_enabled)
4567 XmToggleButtonGadgetSetState(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], True, False);
4569 XmToggleButtonGadgetSetState(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], False, False);
4572 /* ensure that there was fileViewData for the current directory */
4573 if(fileViewData != NULL)
4575 /* attach the current fileViewData to the 'Properties' button */
4576 if( ! file_mgr_data->toolbox )
4578 XtRemoveAllCallbacks(fileMgrPopup.wsPopup[BTN_PROPERTIES],
4579 XmNactivateCallback);
4580 XtAddCallback (fileMgrPopup.wsPopup[BTN_PROPERTIES],
4581 XmNactivateCallback,
4582 ShowModAttrDialog, (XtPointer) fileViewData);
4584 /* sensitize the 'Properties' option */
4585 XtSetSensitive(fileMgrPopup.wsPopup[BTN_PROPERTIES], True);
4587 /* update the actions portion of the popup menu */
4588 XtManageChild(fileMgrPopup.action_separator);
4590 XtFree(fileMgrPopup.action_pane_file_type);
4591 fileMgrPopup.action_pane_file_type =
4592 XtNewString(fileViewData->file_data->logical_type);
4594 UpdateActionMenuPane ((XtPointer)fileViewData, file_mgr_rec,
4595 fileViewData->file_data->logical_type,
4596 FM_POPUP, num_of_children,
4598 fileViewData->file_data->physical_type);
4600 /* align actions portion of the popup menu */
4601 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4602 XtSetValues(action_pane->composite.children[i], args, 1);
4606 if( ! file_mgr_data->toolbox )
4608 /* remove callback from 'Properties' button */
4609 XtRemoveAllCallbacks(fileMgrPopup.wsPopup[BTN_PROPERTIES],
4610 XmNactivateCallback);
4612 /* desensitize the 'Properties' button */
4613 XtSetSensitive(fileMgrPopup.wsPopup[BTN_PROPERTIES], False);
4616 /* unmanage the action portion of the popup menu */
4617 XtUnmanageChild(fileMgrPopup.action_separator);
4619 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4620 XtUnmanageChild(action_pane->composite.children[i]);
4625 /* we are dealing with an object popup */
4628 char label[MAX_PATH];
4630 /* retrieve the fileViewData for the selected icon */
4632 fileViewData = (FileViewData *) client_data;
4633 else if (file_mgr_data->selected_file_count != 0)
4634 fileViewData = file_mgr_data->selection_list[0];
4637 /* unmanage the white space buttons */
4638 XtUnmanageChildren(fileMgrPopup.wsPopup, WS_BTNS);
4640 if(file_mgr_data == trashFileMgrData)
4642 file_mgr_data->popup_menu_icon = fileViewData;
4644 /* Set popup menu label */
4645 if( file_mgr_data->selected_file_count > 1
4646 && InMultipleObjectRegion(file_mgr_data, fileViewData))
4649 label_string = XmStringCreateLocalized ((GETMESSAGE(33,1, "Multiple Objects")));
4655 if (fileViewData->file_data->action_name)
4656 tmp_label = fileViewData->file_data->action_name;
4658 tmp_label = fileViewData->file_data->file_name;
4660 if( strlen( tmp_label ) > 20 )
4661 sprintf( label, "%-20.20s...", tmp_label );
4663 sprintf( label, "%s", tmp_label );
4665 label_string = XmStringCreateLocalized (label);
4667 XtSetArg (args[0], XmNlabelString, label_string);
4668 XtSetValues (fileMgrPopup.title, args, 1);
4669 XtManageChild(fileMgrPopup.title);
4670 XmStringFree (label_string);
4672 /* trash popup--unmanage the non-trash buttons, manage the trash */
4673 XtUnmanageChildren(fileMgrPopup.objPopup, obj_btns);
4674 XtManageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4676 /* adjust callbacks */
4677 XtRemoveAllCallbacks(fileMgrPopup.trash_objPopup[BTN_RESTORE],
4678 XmNactivateCallback);
4679 XtAddCallback(fileMgrPopup.trash_objPopup[BTN_RESTORE],
4680 XmNactivateCallback, Restore, (XtPointer) fileViewData);
4682 XtRemoveAllCallbacks(fileMgrPopup.trash_objPopup[BTN_REMOVE],
4683 XmNactivateCallback);
4684 XtAddCallback(fileMgrPopup.trash_objPopup[BTN_REMOVE],
4685 XmNactivateCallback, ConfirmRemove,
4686 (XtPointer) fileViewData);
4688 /* unmanage the action portion of the popup menu */
4689 XtUnmanageChild(fileMgrPopup.action_separator);
4691 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4692 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4693 XtUnmanageChild(action_pane->composite.children[i]);
4697 /* non-trash popup--manage the non-trash buttons, unmanage the trash */
4698 XtManageChildren(fileMgrPopup.objPopup, obj_btns);
4699 XtUnmanageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4700 if( file_mgr_data->toolbox )
4701 XtUnmanageChild(fileMgrPopup.objPopup[BTN_PROPERTIES]);
4703 if(file_mgr_data->selected_file_count > 1
4704 && InMultipleObjectRegion(file_mgr_data, fileViewData))
4706 /* we have many files selected; remove callbacks from the */
4707 /* 'Properties', 'Put on Desktop', and 'Review' buttons */
4708 /* and attach the selection list to the remaining buttons; */
4709 /* desensitize the 3 buttons listed above; unmanage the */
4710 /* actions part of the popup menu */
4712 /* adjust callbacks */
4713 if( ! file_mgr_data->toolbox )
4714 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PROPERTIES],
4715 XmNactivateCallback);
4717 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PUTON],
4718 XmNactivateCallback);
4719 XtAddCallback(fileMgrPopup.objPopup[BTN_PUTON], XmNactivateCallback,
4720 PutOnDTCB, (XtPointer) fileViewData);
4722 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_TRASH],
4723 XmNactivateCallback);
4724 XtAddCallback(fileMgrPopup.objPopup[BTN_TRASH], XmNactivateCallback,
4725 TrashFiles, (XtPointer) fileViewData);
4727 if( file_mgr_data->toolbox && geteuid() != root_user &&
4728 access(file_mgr_data->current_directory,W_OK|X_OK) != 0)
4729 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], False);
4732 /* sensitize buttons */
4733 if( !file_mgr_data->toolbox )
4734 XtSetSensitive(fileMgrPopup.objPopup[BTN_PROPERTIES], False);
4736 XtSetSensitive(fileMgrPopup.objPopup[BTN_HELP], False);
4738 /* Set popup menu label */
4739 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 1, "Multiple Objects")));
4740 XtSetArg (args[0], XmNlabelString, label_string);
4741 XtSetValues (fileMgrPopup.title, args, 1);
4742 XtManageChild(fileMgrPopup.title);
4743 XmStringFree (label_string);
4746 /* unmanage actions */
4747 XtUnmanageChild(fileMgrPopup.action_separator);
4748 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4749 for(i = num_of_children;
4750 i < action_pane->composite.num_children;
4752 XtUnmanageChild(action_pane->composite.children[i]);
4758 /* we have one file selected; attach fileViewData to buttons; */
4759 /* sensitize any desensitized buttons; update the actions */
4760 /* part of the popup menu */
4762 /* adjust callbacks */
4763 if( ! file_mgr_data->toolbox )
4765 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PROPERTIES],
4766 XmNactivateCallback);
4767 XtAddCallback(fileMgrPopup.objPopup[BTN_PROPERTIES],
4768 XmNactivateCallback, ShowModAttrDialog, (XtPointer) fileViewData);
4771 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PUTON],
4772 XmNactivateCallback);
4773 XtAddCallback(fileMgrPopup.objPopup[BTN_PUTON],
4774 XmNactivateCallback, PutOnDTCB, (XtPointer) fileViewData);
4776 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_TRASH],
4777 XmNactivateCallback);
4778 XtAddCallback(fileMgrPopup.objPopup[BTN_TRASH],
4779 XmNactivateCallback, TrashFiles, (XtPointer) fileViewData);
4781 if ( file_mgr_data->toolbox && geteuid() != root_user &&
4782 access(file_mgr_data->current_directory,W_OK|X_OK) != 0 )
4783 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], False);
4785 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], True);
4788 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_HELP],
4789 XmNactivateCallback);
4790 XtAddCallback(fileMgrPopup.objPopup[BTN_HELP],
4791 XmNactivateCallback, ObjectHelp, (XtPointer) fileViewData->widget);
4793 /* sensitize buttons */
4794 if( ! file_mgr_data->toolbox )
4795 XtSetSensitive(fileMgrPopup.objPopup[BTN_PROPERTIES], True);
4797 XtSetSensitive(fileMgrPopup.objPopup[BTN_PUTON], True);
4798 XtSetSensitive(fileMgrPopup.objPopup[BTN_HELP], True);
4800 if (fileViewData->file_data->action_name)
4801 tmp_label = fileViewData->file_data->action_name;
4803 tmp_label = fileViewData->file_data->file_name;
4805 if( strlen( tmp_label ) > 20 )
4806 sprintf( label, "%-20.20s...", tmp_label );
4808 sprintf( label, "%s", tmp_label );
4810 /* Set popup menu label */
4811 label_string = XmStringCreateLocalized (label);
4812 XtSetArg (args[0], XmNlabelString, label_string);
4813 XtSetValues (fileMgrPopup.title, args, 1);
4814 XtManageChild(fileMgrPopup.title);
4815 XmStringFree (label_string);
4818 /* update actions */
4819 XtManageChild(fileMgrPopup.action_separator);
4821 XtFree(fileMgrPopup.action_pane_file_type);
4822 fileMgrPopup.action_pane_file_type =
4823 XtNewString(fileViewData->file_data->logical_type);
4825 UpdateActionMenuPane ((XtPointer)fileViewData, file_mgr_rec,
4826 fileViewData->file_data->logical_type,
4827 FM_POPUP, num_of_children,
4829 fileViewData->file_data->physical_type);
4832 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4833 XtSetArg(args[0], XmNmarginLeft, 0);
4834 for(i = num_of_children; i < action_pane->composite.num_children; i++)
4835 XtSetValues(action_pane->composite.children[i], args, 1);
4841 /* position and manage popup menu */
4845 Dimension width, height;
4846 Dimension gWidth, gHeight;
4847 int displayWidth, displayHeight;
4848 DtIconGadget g = (DtIconGadget)w;
4850 XtSetArg (args[0], XmNwidth, &width);
4851 XtSetArg (args[1], XmNheight, &height);
4852 XtGetValues(XtParent(fileMgrPopup.menu), args, 2);
4854 gWidth = g->icon.pixmap_width;
4855 gHeight = g->icon.pixmap_height;
4857 displayWidth = DisplayWidth(XtDisplay(w), DefaultScreen(XtDisplay(w)));
4858 displayHeight =DisplayHeight(XtDisplay(w), DefaultScreen(XtDisplay(w)));
4860 x = file_mgr_rec->shell->core.x +
4861 file_mgr_rec->scroll_window->core.x +
4862 w->core.x + gWidth/2;;
4864 y = file_mgr_rec->shell->core.y +
4865 file_mgr_rec->header_frame->core.y +
4866 file_mgr_rec->header_frame->core.height +
4867 file_mgr_rec->scroll_window->core.y +
4868 w->core.y + gHeight/2;;
4870 if((Dimension)(x + width) > (Dimension)displayWidth)
4871 x = displayWidth - width - 4;
4872 if((Dimension)(y + height) > (Dimension)displayHeight)
4873 y = displayHeight - height - 4;
4875 XtSetArg (args[0], XmNx, x);
4876 XtSetArg (args[1], XmNy, y);
4877 XtSetValues(XtParent(fileMgrPopup.menu), args, 2);
4881 if(( event->type == ButtonPress || event->type == ButtonRelease) ||
4882 ( ( event->type == KeyPress || event->type == KeyRelease) &&
4883 _XmIsEventUnique(event) ) )
4885 XmMenuPosition(fileMgrPopup.menu, (XButtonPressedEvent *)event);
4889 XtManageChild(fileMgrPopup.menu);
4891 if( event->type == KeyPress || event->type == KeyRelease )
4893 /* Specify that the focus is being moved by key, NOT mouse
4895 _XmSetInDragMode(fileMgrPopup.menu,False);
4897 XmProcessTraversal(fileMgrPopup.menu,XmTRAVERSE_CURRENT);
4899 /* This function is being called twice.
4900 Record this event so the above check _XmIsEventUnique will work
4902 _XmRecordEvent(event);
4910 XtPointer client_data,
4911 XtPointer call_data)
4913 DtDndDropCallbackStruct *fileList = (DtDndDropCallbackStruct *)call_data;
4915 char ** file_set = NULL;
4916 char ** host_set = NULL;
4917 FileMgrRec * file_mgr_rec;
4918 FileMgrData * file_mgr_data;
4925 int effScreenWidth = 0;
4926 int effScreenHeight = 0;
4927 int start_x = 0, start_y = 0;
4929 int step = 0, dstep = 0;
4931 /* Check the protocol, set to failure if not the */
4932 /* File Transfer protocol */
4933 if (fileList->dropData->protocol != DtDND_FILENAME_TRANSFER)
4935 fileList->status = DtDND_FAILURE;
4940 numFiles = fileList->dropData->numItems;
4942 DPRINTF (("DropOnRoot: Number of files dropped are %d\n", numFiles));
4944 if(fileList->reason != DtCR_DND_DROP_ANIMATE)
4946 /* set the complete move flag to False since it is not required to be called */
4947 /* In case when the drag is from non File manager client */
4949 initiating_view = NULL;
4951 fileList->completeMove = False;
4953 _DtSetDroppedFileInfo(fileList, &file_set, &host_set);
4955 if(initiating_view != NULL)
4957 file_mgr_rec = (FileMgrRec *)
4958 (((FileMgrData *) initiating_view)->file_mgr_rec);
4959 file_mgr_data = (FileMgrData *) initiating_view;
4962 file_mgr_data = NULL;
4964 /* get the correct position for the desktop icon shell */
4965 PositionDesktopIcon(fileList->x, fileList->y, &root_x, &root_y);
4970 * We will place the icons by marching down a diagonal starting
4971 * at the drop point. But we don't want to march off-screen
4972 * if there are too many icons. So ...
4973 * - We choose a step width of 20, 10, 5, or 2 depending
4974 * on the number of icons dropped.
4975 * - When we run into the edge of the screen, we start a new
4976 * diagonal shifted one step to the right.
4977 * - If all icons still won't fit, we move the starting point
4978 * closer to the top left corner of the screen.
4981 /* compute effective screen size (largest x,y where an icon
4982 * can be placed without going off-screen) */
4983 effScreenWidth = WidthOfScreen(XtScreen(w)) - (4 + 4+48+4 + 5);
4984 effScreenHeight = HeightOfScreen(XtScreen(w)) - (4 + 4+48+3+15+4 + 5);
4986 /* chosee step depending on number of icons */
4987 if (numFiles <= 200)
4989 else if (numFiles <= 400)
4991 else if (numFiles <= 1000)
4995 dstep = 40 + 4+48+4 + 5;
4997 /* choose starting point so at least two icons will fit */
4998 if (root_x <= effScreenWidth - step)
5001 start_x = effScreenWidth - step;
5003 if (root_y <= effScreenWidth - step)
5006 start_y = effScreenWidth - step;
5008 DPRINTF(("DropOnRootCB: numFiles %d, root_x %d, root_y %d, step %d\n",
5009 numFiles, root_x, root_y, step));
5011 /* check if all icons will fit */
5014 /* cacluclate how many will fit (add up icons on all diagonals) */
5016 for (root_x = start_x; root_x <= effScreenWidth; root_x += dstep)
5018 int nx = (effScreenWidth - root_x)/step + 1;
5019 int ny = (effScreenHeight - start_y)/step + 1;
5020 n += (nx <= ny)? nx: ny;
5024 DPRINTF(("start_x %d, start_y %d, nd %d, n %d\n",
5025 start_x, start_y, nd, n));
5027 /* if everything fits - great! */
5031 /* move the start point closer to the top left corner */
5032 if (effScreenWidth - start_x < effScreenHeight - start_y &&
5035 /* move left so more icons will fit */
5038 else if (effScreenWidth - start_x > effScreenHeight - start_y &&
5041 /* move up so one more icon will fit in each diagonal */
5044 else if (start_x > 0 || start_y > 0)
5046 /* move left and up */
5047 if (start_x >= step)
5051 if (start_y >= step)
5057 /* ran out of space - too bad! */
5064 /* the icon that was dropped on the root window was an
5065 icon that was already on the root window */
5066 if (file_mgr_data == NULL)
5068 DPRINTF(("DropOnRoot: Object already on Desktop\n"));
5070 /* loop through the existing desktop icons to determine which
5071 ones are being dragged, then change their location */
5072 for(i=0; i < desktop_data->numIconsUsed; i++)
5074 if((Widget)desktop_data->desktopWindows[i]->iconGadget ==
5075 (Widget)widget_dragged)
5077 if (DTFileIsSelected(desktop_data->desktopWindows[i],
5078 desktop_data->desktopWindows[i]->file_view_data))
5080 for(j=0;j< desktop_data->numWorkspaces;j++)
5081 if(desktop_data->workspaceData[j]->number ==
5082 desktop_data->desktopWindows[i]->workspace_num)
5086 j < desktop_data->workspaceData[wsNum]->files_selected;
5089 RelocateDesktopIcon(desktop_data->workspaceData[wsNum]->
5090 selectedDTWindows[j],
5094 if (root_x > effScreenWidth || root_y > effScreenHeight)
5097 if (start_x > effScreenWidth)
5106 RelocateDesktopIcon(desktop_data->desktopWindows[i],
5113 else if( file_mgr_data == trashFileMgrData )
5115 /* if the file manager data is the trash, we want to tell the
5116 user that they can't drop trash on the desktop
5121 DPRINTF(("DropOnRoot: Attempting to Drag Trash Object to Desktop\n"));
5122 file_mgr_rec = (FileMgrRec *)trashFileMgrData->file_mgr_rec;
5123 tmpStr = (GETMESSAGE(11,37, "You can't drop files from\nthe Trash Can on to the Workspace.\nTo remove an object from Trash,\n -Select the object, and\n -Choose 'Put Back'\nfrom the File menu or the object's popup menu.\nYou can then drag the object out of File Manager and drop it on\nthe Workspace backdrop."));
5124 msg = XtNewString(tmpStr);
5125 FileOperationError (file_mgr_rec->main, msg, NULL);
5129 else /* it was dropped on the root window so lets process it */
5131 int EndIndex = desktop_data->numIconsUsed;
5133 for(i = 0; i < numFiles; i++)
5135 ptr = strrchr(file_set[i], '/');
5136 if( strcmp(file_mgr_data->current_directory, file_set[i]) == 0)
5138 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5139 file_mgr_data, file_mgr_rec,
5140 ".", host_set[i], file_set[i],
5144 else if(strncmp(file_mgr_data->current_directory, file_set[i], strlen(file_set[i]) ) == 0 )
5146 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5147 file_mgr_data, file_mgr_rec,
5148 "..", host_set[i],file_mgr_data->current_directory,
5155 if(*(file_set[i]) == 0)
5157 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5158 file_mgr_data, file_mgr_rec,
5159 ptr + 1, host_set[i], "/",
5165 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5166 file_mgr_data, file_mgr_rec,
5167 ptr + 1, host_set[i], file_set[i],
5174 if (root_x > effScreenWidth || root_y > effScreenHeight)
5177 if (start_x > effScreenWidth)
5183 initiating_view = (XtPointer)NULL;
5186 _DtFreeDroppedFileInfo(numFiles, file_set, host_set);
5192 /************************************************************************
5196 ************************************************************************/
5199 FreeLayoutData(XtPointer p)
5201 IconLayoutData *layout_data;
5206 layout_data = (IconLayoutData *)p;
5208 if (layout_data->work_id != 0)
5210 DPRINTF(("FreeLayoutData: removing workproc\n"));
5211 XtRemoveWorkProc(layout_data->work_id);
5212 XmDropSiteEndUpdate(layout_data->drop_site_w);
5215 XtFree((char *)layout_data->order_list);
5216 layout_data->order_list = NULL;
5217 XtFree((char *)layout_data->reuse_icons);
5218 layout_data->reuse_icons = NULL;
5219 XtFree((char *)layout_data->reuse_btns);
5220 layout_data->reuse_btns = NULL;
5221 XtFree((char *)layout_data->manage);
5222 layout_data->manage = NULL;
5224 XtFree((char *)layout_data);
5228 /************************************************************************
5231 * Unmanage a subset of the file icons.
5233 ************************************************************************/
5235 void UnmanageFileIcons(
5236 FileMgrRec *file_mgr_rec,
5237 FileMgrData *file_mgr_data,
5238 FileViewData *file_view_data)
5240 XmManagerWidget file_window;
5241 FileViewData **order_list;
5249 /* Set the size of the file window BIG so that it does not */
5250 /* try to force positioning on its children. */
5252 file_window = (XmManagerWidget) file_mgr_rec->file_window;
5253 XtResizeWidget ((Widget)file_window, 32767, 32767, 0);
5256 /* Set the scrolled window and file window appropriately */
5257 /* to prevent a lot of gyrations. */
5259 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmSTATIC);
5260 XtSetValues (file_mgr_rec->scroll_window, args, 1);
5262 order_list = ((IconLayoutData *)file_mgr_data->layout_data)->order_list;
5263 order_count = ((IconLayoutData *)file_mgr_data->layout_data)->order_count;
5265 unmanage = (Widget *)XtMalloc(2*order_count*sizeof(Widget));
5267 for (i = 0; i < order_count; i++)
5269 if (order_list[i]->filtered)
5272 if ((n > 0 || order_list[i] == file_view_data) &&
5273 !order_list[i]->need_update)
5275 unmanage[n++] = order_list[i]->widget;
5276 if (order_list[i]->treebtn)
5277 unmanage[n++] = order_list[i]->treebtn;
5281 /* remember which icon currently has the focus */
5282 if (XtIsManaged(file_mgr_rec->file_window))
5284 /* see if the focus is inside the file window */
5285 child = XmGetFocusWidget(file_mgr_rec->file_window);
5286 if (child != NULL && XtParent(child) == file_mgr_rec->file_window)
5287 file_mgr_rec->focus_widget = child;
5290 /* unmanage the selected children */
5292 XtUnmanageChildren(unmanage, n);
5294 XtFree((char *)unmanage);
5298 /************************************************************************
5301 * Create or reuse a set of file icons used to get the files
5302 * displayed. This is never called for the desktop.
5304 ************************************************************************/
5308 FileMgrRec *file_mgr_rec,
5309 FileMgrData *file_mgr_data,
5310 Boolean new_directory)
5312 _UpdateFileIcons(file_mgr_rec, file_mgr_data, new_directory, NULL);
5317 FileMgrRec *file_mgr_rec,
5318 FileMgrData *file_mgr_data,
5319 DirectorySet * add_dir_set)
5321 _UpdateFileIcons(file_mgr_rec, file_mgr_data, False, add_dir_set);
5325 /*--------------------------------------------------------------------
5328 * Background information:
5329 * After a refresh on a directory we want to reuse old icon and tree
5330 * button widgets instead of destroying the old widgets and creating
5331 * new ones. Fourthermore, we want to reuse the same widgets for the
5332 * same files, so that if the icon and/or label didn't change, less
5333 * work needs to be done in _UpdateFileIcons().
5334 * For this reason, after a refresh the GetFileData() routine copies
5335 * Widgets from the old FileViewData list to the new FileViewData list
5336 * for files that are both on the old and new list (i.e., files that
5337 * already existed before the refresh and are still there after the
5338 * refresh). This allows _UpdateFileIcons() to reuse the old
5341 * The purpose of MakeReuseList() is to find widgets that are no
5342 * longer found in the new FileViewData list. These are widgets
5343 * from files that disappeared after the refresh (either because the
5344 * file was deleted or because file is now filtered out). These
5345 * widgets can then be reused by _UpdateFileIcons()for new files that
5346 * just appeared after the refresh.
5348 *------------------------------------------------------------------*/
5350 /* compare function for qsort and bsearch */
5352 WidgetCmp(Widget *w1, Widget *w2)
5361 FileViewData **order_list,
5363 Widget **reuse_icons,
5364 Widget **reuse_btns)
5367 int n_old, n_filtered, del_icon, del_btn;
5369 Widget *sorted_chilren = NULL;
5370 Boolean *reuse = NULL;
5377 /* allocate widget arrays */
5378 *reuse_icons = (Widget *)XtMalloc((num_children + 1)*sizeof(Widget));
5379 *reuse_btns = (Widget *)XtMalloc((num_children + 1)*sizeof(Widget));
5380 icon_count = btn_count = 0;
5382 /* only figure things out if we already have children */
5383 if (num_children > 0) {
5384 /* create a sorted list of children */
5385 sorted_chilren = (Widget *)XtMalloc(num_children * sizeof(Widget));
5386 memcpy(sorted_chilren, children, num_children * sizeof(Widget));
5387 qsort(sorted_chilren, num_children, sizeof(Widget), (int (*)())WidgetCmp);
5389 /* create reuse flags; initially assume all children can be reused */
5390 reuse = (Boolean *)XtMalloc(num_children * sizeof(Boolean));
5391 for (i = 0; i < num_children; i++)
5394 /* reset reuse flag for all widgets found in order_list */
5396 n_old = n_filtered = del_icon = del_btn = 0;
5398 for (i = 0; i < order_count; i++)
5400 if (order_list[i]->filtered &&
5401 strcmp(order_list[i]->file_data->file_name, ".") != 0)
5403 /* don't reuse this widget later */
5406 if (order_list[i]->widget)
5408 if (order_list[i]->treebtn)
5411 order_list[i]->widget =
5412 order_list[i]->treebtn = NULL;
5416 if (order_list[i]->widget)
5418 p = bsearch(&order_list[i]->widget,
5419 sorted_chilren, num_children, sizeof(Widget),
5420 (int (*)())WidgetCmp);
5423 /* don't reuse this widget for any other file */
5424 reuse[p - sorted_chilren] = False;
5431 /* don't reuse this widget later */
5432 order_list[i]->widget = NULL;
5439 if (order_list[i]->treebtn)
5441 p = bsearch(&order_list[i]->treebtn,
5442 sorted_chilren, num_children, sizeof(Widget),
5443 (int (*)())WidgetCmp);
5446 /* don't reuse this widget for any other file */
5447 reuse[p - sorted_chilren] = False;
5451 /* don't reuse this widget later */
5452 order_list[i]->treebtn = NULL;
5461 /* copy reusable widgets into widget arrays */
5462 for (i = 0; i < num_children; i++)
5466 /* this widget can be reused for new files */
5467 w = sorted_chilren[i];
5468 if (XtClass(w) == dtIconGadgetClass)
5470 #ifndef DELAYED_UNREGISTER
5473 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
5474 XtRemoveAllCallbacks(w, XmNdropCallback);
5475 XtSetValues (w, args, 1);
5477 (*reuse_icons)[icon_count++] = w;
5479 else if (XtClass(w) == xmPushButtonGadgetClass)
5480 (*reuse_btns)[btn_count++] = w;
5485 /* null-terminate the arrays */
5486 (*reuse_icons)[icon_count] = NULL;
5487 (*reuse_btns)[btn_count] = NULL;
5490 XtFree((char *)sorted_chilren);
5491 XtFree((char *)reuse);
5493 DPRINTF(("MakeReuseList: count %d (%d new, %d old, %d filtered)\n",
5494 order_count, order_count - n_filtered - n_old, n_old, n_filtered));
5495 DPRINTF((" reuse %d + %d, del %d + %d\n",
5496 icon_count, btn_count, del_icon, del_btn));
5500 /*--------------------------------------------------------------------
5501 * UpdateOneIconLabel
5502 *------------------------------------------------------------------*/
5506 FileMgrData *file_mgr_data,
5507 FileViewData *file_view_data)
5512 /* Get the label and icon to be used for the widget */
5513 if (file_mgr_data->view != BY_ATTRIBUTES)
5515 if (strcmp(file_view_data->file_data->file_name, "..") == 0)
5517 /* label = ".. (go up)" */
5518 s = GetSharedMessage(UP_ONE_LEVEL_LABEL);
5519 label = (char *)XtMalloc(2 + strlen(s) + 1);
5520 strcpy(label, "..");
5523 else if (file_mgr_data->view == BY_NAME &&
5524 file_view_data->file_data->physical_type == DtDIRECTORY &&
5525 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
5527 /* label = "name/" */
5528 label = (char *)XtMalloc(
5529 strlen(file_view_data->file_data->file_name) + 2);
5530 strcpy(label, file_view_data->file_data->file_name);
5533 else if (file_mgr_data->view == BY_NAME &&
5534 file_view_data->file_data->physical_type == DtEXECUTABLE)
5536 /* label = "name*" */
5537 label = (char *)XtMalloc(
5538 strlen(file_view_data->file_data->file_name) + 2);
5539 strcpy(label, file_view_data->file_data->file_name);
5542 else if(file_view_data->file_data->action_name != NULL)
5543 /* label = action name */
5544 label = XtNewString(file_view_data->file_data->action_name);
5546 /* label = file name */
5547 label = XtNewString(file_view_data->file_data->file_name);
5549 else /* file_mgr_data->view == BY_ATTRIBUTES */
5551 /* label = file name + attributes */
5552 label = GetLongName(file_view_data->file_data);
5553 if (strcmp(file_view_data->file_data->file_name, "..") == 0)
5555 s = GetSharedMessage(UP_ONE_LEVEL_LABEL);
5556 label = (char *)XtRealloc(label, strlen(label) + strlen(s) + 1);
5561 /* store new label */
5562 XtFree(file_view_data->label);
5563 file_view_data->label = label;
5567 /*--------------------------------------------------------------------
5569 *------------------------------------------------------------------*/
5573 FileMgrRec *file_mgr_rec,
5574 FileMgrData *file_mgr_data,
5575 FileViewData *file_view_data)
5577 XmString icon_label;
5579 PixmapData *pixmapData;
5582 Boolean is_instance_icon;
5583 Boolean instance_icon_changed;
5589 XmManagerWidget file_window = (XmManagerWidget) file_mgr_rec->file_window;
5590 DirectorySet *directory_set = (DirectorySet *)file_view_data->directory_set;
5591 IconLayoutData *layout_data = (IconLayoutData *)file_mgr_data->layout_data;
5593 /* Get the label and icon to be used for the widget */
5594 if (!file_view_data->label)
5595 UpdateOneIconLabel(file_mgr_data, file_view_data);
5597 icon_label = XmStringCreateLocalized(file_view_data->label);
5599 /* Get the icon name based on the file type */
5601 logical_type = file_view_data->file_data->logical_type;
5603 if (file_mgr_data->view == BY_NAME)
5605 else if (openDirType == NEW &&
5606 file_view_data->file_data->physical_type == DtDIRECTORY)
5608 pixmapData = CheckForOpenDirectory(file_view_data,
5615 if (file_mgr_data->view == BY_NAME_AND_ICON)
5616 pixmapData = _DtRetrievePixmapData(
5618 file_view_data->file_data->file_name,
5619 directory_set->name,
5620 (Widget) file_window,
5623 pixmapData = _DtRetrievePixmapData(
5625 file_view_data->file_data->file_name,
5626 directory_set->name,
5627 (Widget) file_window,
5631 /* check if this is an instance icon */
5632 is_instance_icon = False;
5633 if (pixmapData != NULL)
5637 strcpy(tmp, directory_set->name);
5639 strcat(tmp, file_view_data->file_data->file_name);
5640 if (strcmp(pixmapData->iconFileName, tmp) == 0)
5641 is_instance_icon = True;
5644 /* check if instance icon was modified */
5645 instance_icon_changed = False;
5646 if (is_instance_icon)
5648 if (file_view_data->icon_mtime != file_view_data->file_data->stat.st_mtime)
5650 if (file_view_data->icon_mtime != 0)
5651 instance_icon_changed = True;
5652 file_view_data->icon_mtime = file_view_data->file_data->stat.st_mtime;
5656 file_view_data->icon_mtime = 0;
5658 /* Build the arg list for color resources. */
5660 XtSetArg (args[n], XmNarmColor, white_pixel); n++;
5662 if (layout_data->background == white_pixel)
5664 if (file_view_data->selected)
5666 XtSetArg (args[n], XmNbackground, black_pixel); n++;
5667 XtSetArg (args[n], XmNforeground, white_pixel); n++;
5671 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5672 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5674 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5675 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5677 else if (layout_data->background == black_pixel)
5679 if (file_view_data->selected)
5681 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5682 XtSetArg (args[n], XmNforeground, black_pixel); n++;
5686 XtSetArg (args[n], XmNbackground, black_pixel); n++;
5687 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5689 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5690 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5694 if (file_view_data->selected)
5696 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5697 XtSetArg (args[n], XmNforeground, black_pixel); n++;
5698 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5699 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5703 XtSetArg (args[n], XmNbackground, layout_data->background); n++;
5704 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5705 XtSetArg (args[n], XmNpixmapBackground, layout_data->pixmap_back); n++;
5706 XtSetArg (args[n], XmNpixmapForeground, layout_data->pixmap_fore); n++;
5712 /* Build the rest of the arg list and either create or reuse the widget. */
5714 XtSetArg (args[n], XmNstring, icon_label); n++;
5717 XtSetArg (args[n], XmNimageName, pixmapData->iconFileName);
5719 XtSetArg (args[n], XmNimageName, NULL);
5721 XtSetArg (args[n], XmNmaxPixmapWidth, layout_data->pixmap_width); n++;
5722 XtSetArg (args[n], XmNmaxPixmapHeight, layout_data->pixmap_height); n++;
5723 XtSetArg (args[n], XmNuserData, directory_set); n++;
5724 XtSetArg (args[n], XmNunderline, False); n++;
5725 XtSetArg (args[n], XmNfillMode, XmFILL_TRANSPARENT); n++;
5726 if (file_mgr_data->view == BY_NAME_AND_ICON &&
5727 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
5728 XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_TOP);
5730 XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_LEFT); n++;
5732 /* See if we can re-use the same or some other icon gadget */
5733 if (file_view_data->widget)
5734 icon_widget = file_view_data->widget;
5735 else if (*layout_data->next_icon_to_use)
5736 icon_widget = *layout_data->next_icon_to_use++;
5740 /* See if we found an available icon gadget */
5743 /* reuse the icon gadget */
5744 if (icon_widget != file_view_data->widget || file_mgr_data->newSize)
5746 XtSetArg (args[n], XmNdropSiteOperations, XmDROP_NOOP);n++;
5747 XtRemoveAllCallbacks(icon_widget, XmNdropCallback);
5748 file_view_data->registered = False;
5750 XtRemoveAllCallbacks (icon_widget, XmNcallback);
5752 /* if instance_icon_changed, force destroy of old pixmap */
5753 if (instance_icon_changed)
5754 XtSetArg (args[argi_imageName], XmNimageName, NULL);
5757 * Move the gadget off the visible area; this avoids unnecessary
5758 * redraw events at the old position when the gadget is moved to
5759 * the correct position once it is determined in LayoutFileIcons.
5761 icon_widget->core.x = -999;
5762 icon_widget->core.y = -999;
5763 XtSetValues (icon_widget, args, n);
5765 if (instance_icon_changed && pixmapData)
5767 XtSetArg (args[0], XmNimageName, pixmapData->iconFileName);
5768 XtSetValues (icon_widget, args, 1);
5773 /* create a new or duplicate an existing widget */
5774 XtSetArg (args[n], XmNshadowThickness, 2); n++;
5775 XtSetArg (args[n], XmNdropSiteOperations, XmDROP_NOOP);n++;
5776 XtSetArg (args[n], XmNfontList, user_font); n++;
5777 if( keybdFocusPolicy == XmEXPLICIT)
5779 XtSetArg (args[n], XmNtraversalOn, True); n++;
5783 XtSetArg (args[n], XmNtraversalOn, False); n++;
5784 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
5786 XtSetArg (args[n], XmNborderType, DtNON_RECTANGLE); n++;
5788 if (layout_data->dup_icon_widget == NULL)
5790 #ifdef HARDCODED_ICON_MARGINS
5791 XtSetArg (args[n], XmNmarginWidth, 0); n++;
5792 XtSetArg (args[n], XmNmarginHeight, 0); n++;
5794 XtSetArg (args[n], XmNx, -999); n++;
5795 XtSetArg (args[n], XmNy, -999); n++;
5796 icon_widget = layout_data->dup_icon_widget =
5797 _DtCreateIcon ((Widget)file_window, "icon", args, n);
5802 int i = n_color_args;
5804 icon_widget = _DtDuplicateIcon ((Widget)file_window,
5805 layout_data->dup_icon_widget,
5807 (pixmapData? pixmapData->iconFileName: NULL),
5808 (XtPointer)directory_set, /* userData */
5809 False); /* underline */
5810 g = (DtIconGadget)icon_widget;
5811 g->gadget.highlighted = False;
5812 g->gadget.highlight_drawn = False;
5815 * Move the gadget off the visible area; this avoids unnecessary
5816 * redraw events at the old position when the gadget is moved to
5817 * the correct position once it is determined in LayoutFileIcons.
5819 icon_widget->core.x = -999;
5820 icon_widget->core.y = -999;
5822 /* make sure colors, drop operations, and clipping are right */
5823 XtSetArg(args[i], XmNdropSiteOperations, XmDROP_NOOP); i++;
5824 XtSetArg(args[i], XmNmaxPixmapWidth, layout_data->pixmap_width); i++;
5825 XtSetArg(args[i], XmNmaxPixmapHeight, layout_data->pixmap_height); i++;
5826 XtSetValues (icon_widget, args, i);
5828 XtAddCallback(icon_widget, XmNhelpCallback,
5829 (XtCallbackProc)HelpRequestCB, NULL);
5830 file_view_data->registered = False;
5833 if (file_mgr_data->view != BY_NAME)
5834 _DtCheckAndFreePixmapData(logical_type,
5835 (Widget) file_window,
5836 (DtIconGadget) icon_widget,
5840 if (file_view_data->file_data->link != 0)
5842 XtSetArg (args[0], XmNforeground, layout_data->topshadow);
5843 XtSetValues (icon_widget, args, 1);
5848 * If viewing by attributes, adjust spacing between the icon pixmap and
5849 * the file name so that all file names are aligned.
5851 if (file_mgr_data->view != BY_NAME_AND_ICON ||
5852 file_mgr_data->show_type == MULTIPLE_DIRECTORY)
5854 Dimension pixmap_width = ((DtIconGadget)icon_widget)->icon.pixmap_width;
5856 if (pixmap_width < layout_data->pixmap_width)
5858 XtSetArg (args[0], XmNspacing,
5859 layout_data->spacing + layout_data->pixmap_width - pixmap_width);
5860 XtSetValues (icon_widget, args, 1);
5865 file_view_data->file_data->is_broken = False;
5866 file_view_data->widget = icon_widget;
5867 XtAddCallback (icon_widget, XmNcallback, (XtCallbackProc)IconCallback,
5870 XmStringFree (icon_label);
5872 /* Check if we need a button for tree branch expand */
5874 if (file_mgr_data->show_type != MULTIPLE_DIRECTORY ||
5875 !file_view_data->file_data->is_subdir)
5877 /* no tree branch expand button needed */
5878 file_view_data->treebtn = NULL;
5882 /* create a tree branch expand button */
5883 Pixmap px = GetTreebtnPixmap(file_mgr_data, file_view_data);
5886 XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
5887 XtSetArg(args[n], XmNlabelPixmap, px); n++;
5888 XtSetArg(args[n], XmNbackground, layout_data->background); n++;
5889 XtSetArg(args[n], XmNtraversalOn, False); n++;
5890 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
5891 XtSetArg(args[n], XmNshadowThickness, 0); n++;
5892 XtSetArg(args[n], XmNmarginWidth, 0); n++;
5893 XtSetArg(args[n], XmNmarginHeight, 0); n++;
5894 XtSetArg(args[n], XmNuserData, file_mgr_data); n++;
5895 XtSetArg(args[n], XmNx, -999); n++;
5896 XtSetArg(args[n], XmNy, -999); n++;
5898 /* See if we can re-use the same or some other button gadget */
5899 if (file_view_data->treebtn)
5900 btn_widget = file_view_data->treebtn;
5901 else if (*layout_data->next_btn_to_use)
5902 btn_widget = *(layout_data->next_btn_to_use)++;
5906 /* See if we found an available button gadget */
5908 XtRemoveAllCallbacks (btn_widget, XmNactivateCallback);
5909 XtSetValues (btn_widget, args, n);
5913 btn_widget = XmCreatePushButtonGadget((Widget)file_window,
5914 "tree_button", args, n);
5916 XtAddCallback(btn_widget, XmNactivateCallback,
5917 (XtCallbackProc)TreeBtnCallback, file_view_data);
5919 file_view_data->treebtn = btn_widget;
5922 /* this entry is now up-to-date */
5923 file_view_data->need_update = False;
5927 /*--------------------------------------------------------------------
5929 *------------------------------------------------------------------*/
5933 FileMgrRec *file_mgr_rec,
5934 FileMgrData *file_mgr_data,
5935 Boolean new_directory,
5936 DirectorySet * add_dir_set)
5938 XmManagerWidget file_window;
5939 FileViewData **order_list;
5943 IconLayoutData *layout_data;
5946 #ifdef DT_PERFORMANCE
5947 struct timeval update_time_s;
5948 struct timeval update_time_f;
5951 DPRINTF(("_UpdateFileIcons(\"%s\", new_dir %c, add_dir_set %p) ...\n",
5952 file_mgr_data->current_directory,
5953 new_directory? 'T': 'F', add_dir_set));
5955 /* Set the size of the file window BIG so that it does not */
5956 /* try to force positioning on its children. */
5957 file_window = (XmManagerWidget) file_mgr_rec->file_window;
5958 XtResizeWidget ((Widget)file_window, 32767, 32767, 0);
5960 /* Set the scrolled window and file window appropriately */
5961 /* to prevent a lot of gyrations. */
5963 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmSTATIC);
5964 XtSetValues (file_mgr_rec->scroll_window, args, 1);
5966 /* For faster updates, unmanage all the icons */
5967 if (XtIsManaged(file_mgr_rec->file_window))
5969 /* see if the focus is inside the file window */
5970 child = XmGetFocusWidget(file_mgr_rec->file_window);
5975 file_mgr_rec->focus_widget = file_mgr_rec->file_window;
5977 else if( XtParent(child) == file_mgr_rec->file_window )
5979 /* remember which widget had the focus */
5980 file_mgr_rec->focus_widget = child;
5984 DPRINTF((" focus_widget = %p (%s)\n",
5985 file_mgr_rec->focus_widget,
5986 file_mgr_rec->focus_widget?
5987 XtName(file_mgr_rec->focus_widget): "nil"));
5988 XtUnmanageChild(file_mgr_rec->file_window);
5991 XtUnmanageChildren(file_window->composite.children,
5992 file_window->composite.num_children);
5994 /* if this is a new directory, scroll to the top */
5997 XtSetArg (args[0], XmNx, 0);
5998 XtSetArg (args[1], XmNy, 0);
5999 XtSetValues ((Widget)file_window, args, 2);
6003 * Don't leave the view in a munged state for too long.
6004 * Only do if we are not creating a new view. This is because the
6005 * view is not yet in the 'view_list', and so the redisplay code
6006 * may not use the correct redisplay function.
6008 if (ReturnDesktopPtr(file_mgr_rec->file_window))
6010 UpdateHeaders(file_mgr_rec, file_mgr_data, False);
6011 XFlush (XtDisplay (file_window));
6012 XmUpdateDisplay ((Widget)file_window);
6015 /* free any old layout data */
6016 FreeLayoutData(file_mgr_data->layout_data);
6017 file_mgr_data->layout_data = NULL;
6019 /* if directory-read still in progress, don't do anything more now */
6020 if (file_mgr_data->busy_status != not_busy)
6022 DPRINTF(("done (busy)\n"));
6026 #ifdef DT_PERFORMANCE
6027 printf(" Beginning UpdateFileIcons\n");
6028 gettimeofday(&update_time_s, NULL);
6031 _DtPerfChkpntMsgSend("Begin Update Icons");
6035 /* set up new layout data */
6036 layout_data = (IconLayoutData *)XtCalloc(1, sizeof(IconLayoutData));
6037 file_mgr_data->layout_data = (XtPointer)layout_data;
6039 FlattenTree(file_mgr_data, &order_list, &order_count);
6040 layout_data->order_list = order_list;
6041 layout_data->order_count = order_count;
6043 MakeReuseList(file_window->composite.children,
6044 file_window->composite.num_children,
6045 order_list, order_count,
6046 &layout_data->reuse_icons,
6047 &layout_data->reuse_btns);
6048 layout_data->next_icon_to_use = layout_data->reuse_icons;
6049 layout_data->next_btn_to_use = layout_data->reuse_btns;
6051 layout_data->manage = (Widget *)XtMalloc(2*order_count*sizeof(Widget));
6052 layout_data->manage_count = 0;
6054 layout_data->i_do_next_vis = 0;
6055 layout_data->i_do_next_all = 0;
6058 * Iterate through the file list and mark all entries to be in
6059 * need of update. We also construct icon labels at this time,
6060 * since they are need by LayoutFileIcons to estimate icon gadget
6066 /* only need to iterate throught the new entries */;
6067 order_list = add_dir_set->order_list;
6068 order_count = add_dir_set->file_count;
6071 for (i = 0; i < order_count; i++)
6073 order_list[i]->need_update = True;
6074 order_list[i]->selected = False;
6075 UpdateOneIconLabel(file_mgr_data, order_list[i]);
6078 /* set selected flag on all files in selection_list */
6079 for (i = 0; i < file_mgr_data->selected_file_count; i++)
6080 file_mgr_data->selection_list[i]->selected = True;
6082 #ifdef DT_PERFORMANCE
6083 gettimeofday(&update_time_f, NULL);
6084 if (update_time_s.tv_usec > update_time_f.tv_usec) {
6085 update_time_f.tv_usec += 1000000;
6086 update_time_f.tv_sec--;
6088 printf(" done UpdateFileIcons, time: %ld.%ld\n\n", update_time_f.tv_sec - update_time_s.tv_sec, update_time_f.tv_usec - update_time_s.tv_usec);
6091 _DtPerfChkpntMsgSend("Done Update Icons");
6094 DPRINTF(("done\n"));
6100 /************************************************************************
6103 * Create icons for tree-branch-expand buttons.
6105 ************************************************************************/
6108 CreateTreeIcons(Widget w)
6111 Pixel background_color = 0;
6112 Pixel foreground_color = 0;
6116 unsigned int width, height, dummy;
6118 XtSetArg (args[0], XmNbackground, &background_color);
6119 XtSetArg (args[1], XmNforeground, &foreground_color);
6120 XtGetValues (w, args, 2);
6122 /* JET - 4/29/18, It seems for some reason that no matter what
6123 * background is specified for these pixmaps, it will always be
6124 * black when drawn. This seems like a Motif issue. The problem
6125 * arises when earlier on, depending on what Palette has been
6126 * selected for the user, the foreground can also be black. In
6127 * those cases, instead of seeing the pixmap, you see a black square
6128 * since both the fg and bg colors are black now. We "fix" this by
6129 * always forcing the foreground to be white. This is a
6130 * "workaround" - the real problem still needs to be located and
6133 foreground_color = 0x00ffffff;
6135 for (i = 0; i < 3; i++)
6139 for (j = 0; j < tpxN; j++)
6141 strcpy(pxname, TreePxTab[j].name);
6142 strcat(pxname, TreePxSuffix[i]);
6143 TreePxTab[j].px[i] = _DtGetPixmap(XtScreen(w), pxname,
6144 foreground_color, background_color);
6146 XGetGeometry(XtDisplay(w), TreePxTab[j].px[i],
6147 (Window *) &dummy, /* returned root window */
6148 (int *) &dummy, (int *) &dummy, /* x, y of pixmap */
6149 &width, &height, /* pixmap width, height */
6150 &dummy, &dummy); /* border width, depth */
6153 TreeNilWd[i] = width;
6154 TreeNilHt[i] = height;
6158 if (width > TreeBtnWd[i])
6159 TreeBtnWd[i] = width;
6160 if (height > TreeBtnHt[i])
6161 TreeBtnHt[i] = height;
6168 /************************************************************************
6171 * Get icon for tree-branch-expand buttons.
6173 ************************************************************************/
6175 Pixmap GetTreebtnPixmap(
6176 FileMgrData *file_mgr_data,
6177 FileViewData *file_view_data)
6179 TreePxId pxid = tpxNil;
6181 /* if not yet done, create tree button icons */
6182 /* @@@ do this earlier from main? */
6183 if (TreeBtnWd[0] == 0)
6184 CreateTreeIcons(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
6186 if (file_view_data->ts == tsNotRead)
6188 else if (file_view_data->ts == tsError)
6190 else if (file_view_data->ndir == 0 &&
6191 (file_view_data->nfile == 0 ||
6192 file_mgr_data->tree_files == TREE_FILES_NEVER)
6193 && (file_view_data->ts == tsNone || !showEmptySet))
6195 else if (file_view_data->ts == tsNone)
6197 else if (file_view_data->ts == tsDirs)
6198 pxid = (file_view_data->nfile == 0 ||
6199 file_mgr_data->tree_files == TREE_FILES_NEVER)? tpxLess:
6200 (file_view_data->ndir == 0)? tpxMore:
6202 else if (file_view_data->ts == tsAll)
6205 if (file_mgr_data->view == BY_NAME)
6206 return TreePxTab[pxid].px[0]; /* small pixmap */
6207 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6208 return TreePxTab[pxid].px[2]; /* large pixmap */
6210 return TreePxTab[pxid].px[1]; /* medium pixmap */
6214 /************************************************************************
6217 * Compute maximum icon size.
6219 ************************************************************************/
6223 FileMgrRec *file_mgr_rec,
6224 FileMgrData *file_mgr_data,
6227 DirectorySet *directory_set;
6229 FileViewData **file_list;
6233 Dimension shadowThickness;
6234 Dimension marginWidth;
6235 Dimension maxWidth = ld->pixmap_width;
6236 Dimension gadgetWidth;
6238 /* determine pixmap size */
6239 if (file_mgr_data->view == BY_NAME)
6242 ld->pixmap_width = 0;
6243 ld->pixmap_height = 0;
6245 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6248 ld->pixmap_width = largeIconWidth;
6249 ld->pixmap_height = largeIconHeight;
6254 ld->pixmap_width = smallIconWidth;
6255 ld->pixmap_height = smallIconHeight;
6258 /* find the icon gadget for "." */
6259 directory_set = file_mgr_data->directory_set[0];
6260 file_count = directory_set->file_count;
6261 file_list = directory_set->file_view_data;
6264 for (i = 0; i < file_count; i++)
6266 if (strcmp(file_list[i]->file_data->file_name, ".") == 0)
6268 g = (DtIconGadget)file_list[i]->widget;
6273 /* get layout parameters from "." */
6276 XtSetArg(args[0], XmNhighlightThickness, &ld->highlight);
6277 XtSetArg(args[1], XmNshadowThickness, &shadowThickness);
6278 XtSetArg(args[2], XmNmarginWidth, &marginWidth);
6279 XtSetArg(args[3], XmNspacing, &ld->spacing);
6280 XtSetArg(args[4], XmNalignment, &ld->alignment);
6281 XtSetArg(args[5], XmNpixmapPosition, &ld->pixmap_position);
6282 XtGetValues((Widget)g, args, 6);
6284 if (g->icon.pixmap_width < maxWidth)
6285 ld->spacing = ld->spacing - (maxWidth - g->icon.pixmap_width);
6287 ld->width = ((Widget)g)->core.width +
6288 ld->pixmap_width - g->icon.pixmap_width;
6289 ld->height = ((Widget)g)->core.height +
6290 ld->pixmap_height - g->icon.pixmap_height;
6292 ld->char_width = (g->icon.string_width)/strlen(file_list[i]->label);
6293 if (ld->pixmap_position != XmPIXMAP_TOP)
6294 ld->width -= g->icon.string_width;
6295 ld->margin = ld->highlight + shadowThickness + marginWidth;
6299 /* No icon gadget for "." found: strange! Guess some defaults. */
6301 ld->margin = 2 + 1 + 1;
6303 ld->highlight = (keybdFocusPolicy == XmEXPLICIT)? 2: 0;
6304 ld->alignment = XmALIGNMENT_END;
6305 if (file_mgr_data->view == BY_NAME_AND_ICON &&
6306 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6308 ld->pixmap_position = XmPIXMAP_TOP;
6309 ld->width = 2*ld->margin + ld->pixmap_width;
6310 ld->height = 2*ld->margin + ld->pixmap_height + ld->spacing + 14;
6314 ld->pixmap_position = XmPIXMAP_LEFT;
6315 ld->width = 2*ld->margin + ld->pixmap_width +
6316 ld->spacing + ld->char_width;
6317 ld->height = 2*ld->margin + ld->pixmap_height;
6321 /* determine which size tree buttons to use */
6322 if (file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6323 ld->treebtn_size = 0; /* no tree buttons needed */
6324 else if (file_mgr_data->view == BY_NAME)
6325 ld->treebtn_size = 0; /* small size */
6326 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6327 ld->treebtn_size = 2; /* large size */
6329 ld->treebtn_size = 1; /* medium size */
6335 FileMgrRec *file_mgr_rec,
6336 FileMgrData *file_mgr_data,
6337 IconLayoutData *layout_data,
6338 FileViewData *file_view_data,
6345 if (file_view_data == NULL) {
6348 label_len = DtCharCount(file_view_data->label == NULL ?
6349 file_view_data->file_data->file_name : file_view_data->label);
6352 if (layout_data->pixmap_position == XmPIXMAP_TOP)
6354 label_width = 2*layout_data->margin + label_len*layout_data->char_width;
6355 if ((Dimension)label_width > layout_data->width)
6356 *width = label_width;
6358 *width = layout_data->width;
6361 *width = layout_data->width + (label_len) * layout_data->char_width;
6362 *height = layout_data->height;
6366 /************************************************************************
6369 * Compute extra height for drawing nil symbol for empty tree branches.
6371 ************************************************************************/
6375 FileMgrData *file_mgr_data,
6376 FileViewData *file_view_data,
6380 file_view_data->file_data->is_subdir &&
6381 file_view_data->ts >= tsDirs &&
6382 file_view_data->ndir == 0 &&
6383 (file_view_data->nfile == 0 ||
6384 file_mgr_data->tree_files == TREE_FILES_NEVER))
6386 return YSPACING(file_mgr_data) + TreeNilHt[treebtn_size];
6393 /************************************************************************
6396 * Erase connecting lines in tree mode from a specified icon widget
6397 * on down; called when a tree branch is expanded or collapsed to
6398 * erase previous tree lines before drawing new icons and tree lines.
6400 ************************************************************************/
6404 FileMgrRec *file_mgr_rec,
6405 FileMgrData *file_mgr_data,
6406 FileViewData *file_view_data)
6408 XmManagerWidget file_window;
6409 Dimension fw_width, fw_height;
6412 file_window = (XmManagerWidget) file_mgr_rec->file_window;
6413 if (!XtIsManaged((Widget)file_window))
6416 /* get upper left corner of grid space for the icon widget */
6417 x = file_view_data->x;
6418 y = file_view_data->y - file_mgr_data->grid_height;
6420 /* Get file window width and height */
6421 fw_width = file_window->core.width;
6422 fw_height = file_window->core.height;
6424 DPRINTF2(("EraseTreeLines(\"%s\"): x/y %d/%d (widget %d/%d)\n",
6425 file_view_data->file_data->file_name, x, y,
6426 file_view_data->widget->core.x,
6427 file_view_data->widget->core.y));
6429 /* clear area from icon widget to bottom of file window */
6430 XClearArea(XtDisplay(file_window), XtWindow(file_window),
6431 x, y, fw_width - x, fw_height - y, False);
6434 * clear area to the right and above the icon widget
6435 * (necessary if there are multiple columns, which happens if
6436 * there are more icons than fit into a single column of
6437 * maximum height 32767)
6439 if (y > 0 && (Dimension)(x + file_mgr_data->grid_width) < fw_width)
6441 x += file_mgr_data->grid_width;
6442 XClearArea(XtDisplay(file_window), XtWindow(file_window),
6443 x, 0, fw_width - x, y, False);
6448 /************************************************************************
6451 * Redraw connecting lines in tree mode.
6453 ************************************************************************/
6458 int ex, int ey, int ewidth, int eheight, int ecount,
6459 FileMgrRec *file_mgr_rec,
6460 FileMgrData *file_mgr_data)
6462 static char *empty_msg = NULL;
6464 FileViewData *file_view_data;
6465 IconLayoutData *layout_data;
6466 Dimension grid_width, grid_height;
6467 Dimension extra_height, e_height;
6469 FileViewData **order_list;
6471 GC solid_gc, dash_gc;
6477 XFontSetExtents *extents;
6482 if (!XtIsManaged(w))
6485 /* get layout parameters */
6486 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
6487 order_list = layout_data->order_list;
6488 order_count = layout_data->order_count;
6489 grid_width = file_mgr_data->grid_width;
6490 grid_height = file_mgr_data->grid_height;
6491 sz = layout_data->treebtn_size;
6493 DPRINTF2(("RedrawTreeLines(x %d, y %d, wd %d, ht %d, count %d)\n",
6494 ex, ey, ewidth, eheight, ecount));
6496 if (grid_width == 0 || grid_height == 0)
6497 /* layout probably not yet done */
6500 /* if not yet done, create tree button icons */
6501 /* @@@ do this earlier from main? */
6502 if (TreeBtnWd[0] == 0)
6503 CreateTreeIcons(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
6505 /* select line styles */
6506 if (file_mgr_data->view == BY_NAME) {
6507 solid_gc = file_mgr_data->tree_solid_thin_gc;
6508 dash_gc = file_mgr_data->tree_dash_thin_gc;
6510 solid_gc = file_mgr_data->tree_solid_thick_gc;
6511 dash_gc = file_mgr_data->tree_dash_thick_gc;
6517 for (k = 0; k < order_count; k++)
6519 if (!order_list[k]->displayed)
6522 /* determine the height of this item */
6523 file_view_data = order_list[k];
6524 extra_height = GetExtraHeight(file_mgr_data, file_view_data, sz);
6525 GetLevel(file_view_data, &level);
6527 /* check if we need to go to the next column */
6528 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
6529 if (tmp + MARGIN > MAXWINSIZE)
6531 /* window would exceed height limit; go to the next column */
6532 x += grid_width + XSPACING;
6534 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
6537 /* check if current item intersects the exposed region */
6538 y0 = y - YSPACING(file_mgr_data)
6540 + (Dimension)(grid_height - TreeBtnHt[sz])/(Dimension)2
6542 y1 = y + grid_height + extra_height + YSPACING(file_mgr_data);
6543 if (x <= ex + ewidth && x + TreeWd(level, sz) > ex &&
6544 y0 <= ey + eheight && y1 > ey)
6546 GetAncestorInfo(file_mgr_data, file_view_data, NULL, NULL, more);
6548 /* draw vertical connecting lines for upper tree levels */
6549 for (i = 0; i < level; i++) {
6551 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6552 x + TreeLX(i, sz), y0,
6553 x + TreeLX(i, sz), y1);
6556 /* draw vertical connecting line for this tree level */
6557 xl = x + TreeLX(level, sz);
6559 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6561 xl, more[level]? y1: y + grid_height/2);
6563 if (file_view_data->file_data->is_subdir || !more[level]) {
6564 /* draw horizontal line */
6565 XDrawLine(XtDisplay(w), XtWindow(w),
6566 (file_view_data->file_data->is_subdir &&
6567 file_view_data->ts == tsNotRead)? dash_gc: solid_gc,
6568 xl, y + grid_height/2,
6569 xl + TreeOffset, y + grid_height/2);
6573 /* draw nil symbol for empty subdirs */
6576 xl += TreeOneWd(sz);
6577 y0 += grid_height + YSPACING(file_mgr_data);
6578 y1 = y + grid_height + YSPACING(file_mgr_data);
6579 e_height = extra_height - YSPACING(file_mgr_data);
6581 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6583 xl, y1 + e_height/2);
6585 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6586 xl, y1 + e_height/2,
6587 xl + TreeOffset, y1 + e_height/2);
6589 xl = x + TreeWd(level, sz) + TreeBtnWd[sz];
6590 XCopyArea(XtDisplay(w), TreePxTab[tpxNil].px[sz],
6591 XtWindow(w), solid_gc,
6592 0, 0, TreeNilWd[sz], TreeNilHt[sz],
6595 if (empty_msg == NULL)
6596 empty_msg = XtNewString("(empty)");
6598 if (file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET)
6600 extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
6601 font_yoffset = extents->max_logical_extent.y;
6602 font_height = extents->max_logical_extent.height;
6606 font_yoffset = file_mgr_data->cd_font->ascent;
6607 font_height = file_mgr_data->cd_font->ascent +
6608 file_mgr_data->cd_font->descent;
6611 XDrawImageString(XtDisplay(w), XtWindow(w), solid_gc,
6612 xl + TreeNilWd[sz] + 2,
6613 y1 + (TreeNilHt[sz] - font_height)/2 + font_yoffset,
6614 empty_msg, strlen(empty_msg));
6619 /* goto next item */
6625 /************************************************************************
6628 * Check if any incons or widgets in the area given by ex, ey, ewd,
6629 * and eht need to be updated.
6631 ************************************************************************/
6634 static int g_workCount1 = 0;
6635 static int g_workCount2 = 0;
6636 static int g_callCount = 0;
6641 IconLayoutData *layout_data,
6642 FileViewData *file_view_data)
6646 for (i = 0; i < layout_data->manage_count; i++)
6647 if (layout_data->manage[i] == file_view_data->widget)
6656 FileMgrRec *file_mgr_rec,
6657 FileMgrData *file_mgr_data,
6658 int ex, int ey, int ewd, int eht,
6662 #ifdef DT_PERFORMANCE
6663 struct timeval update_time_s;
6664 struct timeval update_time_f;
6666 XmManagerWidget file_window;
6667 FileViewData **order_list;
6670 Arg args_dso_get[1];
6671 Arg args_dso_set[1];
6672 IconLayoutData *layout_data;
6673 FileViewData **change;
6679 Dimension grid_width, grid_height;
6680 Dimension icon_width, icon_height;
6681 Dimension extra_height;
6684 FileViewData *file_view_data;
6689 unsigned char operations;
6691 ObjectPosition *position_data;
6692 XRectangle textExtent;
6694 /* Get a list of icon and button widgets we can re-use */
6695 file_window = (XmManagerWidget) file_mgr_rec->file_window;
6696 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
6697 order_list = layout_data->order_list;
6698 order_count = layout_data->order_count;
6699 manage = layout_data->manage + layout_data->manage_count;
6701 /* allocate storage for list of changed icons */
6702 change = (FileViewData **)XtMalloc(order_count * sizeof(FileViewData *));
6704 /* Find the maximum values for the icon heights and widths */
6705 grid_width = file_mgr_data->grid_width;
6706 grid_height = file_mgr_data->grid_height;
6709 #ifdef DT_PERFORMANCE
6710 printf(" Begin Part 1, DisplaySomeIcons (update icons)\n");
6711 gettimeofday(&update_time_s, NULL);
6714 _DtPerfChkpntMsgSend("Begin Display Icons");
6718 "DisplaySomeIcons(\"%s\", x/y %d/%d, wd/ht %d/%d, i %d:%d) ...\n",
6719 file_mgr_data->current_directory, ex, ey, ewd, eht,
6720 layout_data->i_do_next_vis,
6721 layout_data->i_do_next_all));
6723 /* set up args for querying/unregistering drop sites */
6724 XtSetArg (args_dso_get[0], XmNdropSiteOperations, &operations);
6725 XtSetArg (args_dso_set[0], XmNdropSiteOperations, XmDROP_NOOP);
6728 * Iterate through the list of files and create/update and position
6729 * all visible icon gadgets for which this work hasn't been done yet
6730 * (need_update flag set).
6738 k = layout_data->i_do_next_all;
6740 k = layout_data->i_do_next_vis;
6741 for ( ; k < order_count && workCount1 < workLimit; k++)
6744 * Process focus widget before everything else so that we can restore
6745 * the focus when we manage the file_window again. If a file was
6746 * being renamed, we do that one first.
6748 if (!layout_data->focus_done)
6750 /* search for focus widget in order_list and see if still displayed */
6751 file_view_data = NULL;
6752 if (file_mgr_rec->focus_widget != NULL)
6754 if (file_mgr_rec->focus_widget == file_mgr_rec->file_window)
6756 for (i = 0; i < order_count; i++)
6757 if (order_list[i]->displayed)
6759 file_view_data = order_list[i];
6765 for (i = 0; i < order_count; i++)
6766 if (order_list[i]->widget == file_mgr_rec->focus_widget)
6768 if (order_list[i]->displayed)
6769 file_view_data = order_list[i];
6775 /* if not found, focus could be on a rename text widget */
6776 if (file_view_data == NULL)
6777 file_view_data = file_mgr_data->renaming;
6779 layout_data->focus_done = True;
6784 /* decrement loop index, so that the entry that was supposed to be
6785 processed here will be looked at again in the next iteration
6792 /* ignore files that are filtered */
6793 file_view_data = order_list[k];
6794 if (file_view_data->filtered &&
6795 strcmp(file_view_data->file_data->file_name, ".") != 0)
6801 * If the file is not currenly displayed (collapsed tree branch) or
6802 * is currenly scrolled out of view, we don't need to do anything
6803 * at this time. Except ...
6805 if (!file_view_data->displayed ||
6806 ((int)file_view_data->x + (int)grid_width) < ex ||
6807 file_view_data->x >= ex + ewd ||
6808 file_view_data->y < ey ||
6809 ((int)file_view_data->y - (int)grid_height) >= (ey + eht))
6812 * ... if this file still has an old icon widget, AND if the
6813 * old icon position is visible, AND if the icon was registered
6814 * as a drop site, we will have a "ghost drop zone" showing up where
6815 * the icon used to be. The old icon gadget is unmanaged and will
6816 * remain unmanaged until later when we update it and move it to the
6817 * correct positon (happens only when the user scrolls to the new
6818 * position). In the meantime, even though the gadget is unmanged,
6819 * its old position still remains registered as a drop site,
6820 * so we have to either unregister it or move the gadget to
6821 * its new position now.
6823 child = file_view_data->widget;
6824 if (child != NULL &&
6825 (Position)(child->core.x + child->core.width) >= (Position)ex &&
6826 child->core.x < ex + ewd &&
6827 (Position)(child->core.y + child->core.height) >= (Position)ey &&
6828 child->core.y < ey + eht)
6830 if (!file_view_data->displayed)
6832 XtGetValues (child, args_dso_get, 1);
6833 if (operations != XmDROP_NOOP)
6835 XtSetValues (child, args_dso_set, 1);
6837 file_view_data->registered = False;
6848 * If not yet done, create/update the icon gadget for this file
6850 if (file_view_data->need_update)
6852 UpdateOneFileIcon(file_mgr_rec, file_mgr_data, file_view_data);
6853 child = file_view_data->widget;
6856 * We may need to adjust the icon position based on the difference
6857 * between estimated size and actual size.
6859 if (layout_data->alignment == XmALIGNMENT_CENTER &&
6860 file_mgr_data->view == BY_NAME_AND_ICON)
6862 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data,
6863 file_view_data, &icon_width, &icon_height);
6865 if (child->core.width != icon_width)
6867 file_view_data->x = file_view_data->x
6868 - (Dimension)(grid_width - icon_width)/(Dimension)2
6869 + (Dimension)(grid_width - child->core.width)/(Dimension)2;
6873 if (PositioningEnabledInView(file_mgr_data))
6875 position_data = file_view_data->position_info;
6876 if (position_data->late_bind)
6879 * When new objects are dropped on the random placement window,
6880 * they do not yet have a widget, so the drop_y could not be
6881 * adjusted to take into account the height of the icon;
6882 * this must be done now, after the object has an icon.
6885 position_data->y -= child->core.height/2;
6887 position_data->late_bind = False;
6888 file_view_data->y = position_data->y + child->core.height;
6890 else if (child->core.height != grid_height)
6893 * Not quite right: have to distinguish two cases:
6894 * (1) position_data->y read from .!xxx file
6895 * file_view_data->y computed by adding grid_height
6896 * (2) file_view_data->y from layout
6897 * position_data->y computed by subtracting grid_height
6898 * In case (1) have to recompute file_view_data->y; in case
6899 * (2) have to recompute position_data->y. Code below only
6900 * works for case (2).
6903 position_data->y = file_view_data->y - child->core.height;
6914 /* if focus is supposed to be in the file window, focus on this widget */
6915 if (file_mgr_rec->focus_widget == file_mgr_rec->file_window)
6916 file_mgr_rec->focus_widget = file_view_data->widget;
6919 /* determine desired icon postition */
6920 child = file_view_data->widget;
6922 if (PositioningEnabledInView(file_mgr_data))
6924 x = file_view_data->position_info->x;
6925 y = file_view_data->position_info->y;
6927 else if (file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6929 x = file_view_data->x;
6930 y = file_view_data->y - child->core.height;
6932 else /* file_mgr_data->show_type == MULTIPLE_DIRECTORY */
6934 GetLevel(file_view_data, &level);
6935 extra_height = GetExtraHeight(file_mgr_data, file_view_data,
6936 layout_data->treebtn_size);
6938 /* check position of tree button, if any */
6939 if (file_view_data->treebtn)
6941 child = file_view_data->treebtn;
6943 x = file_view_data->x
6944 + TreeLX(level, layout_data->treebtn_size) + TreeOffset;
6945 y = file_view_data->y
6947 + (Dimension)(grid_height - child->core.height)/(Dimension)2;
6949 if (child->core.x != x || child->core.y != y)
6950 XmeConfigureObject(child, x, y, child->core.width,
6951 child->core.height, child->core.border_width);
6953 child = file_view_data->widget;
6956 if (child->core.height < grid_height)
6958 x = file_view_data->x + TreeWd(level, layout_data->treebtn_size);
6959 y = file_view_data->y
6961 +(Dimension)(grid_height - child->core.height)/(Dimension)2;
6965 x = file_view_data->x + TreeWd(level, layout_data->treebtn_size);
6966 y = file_view_data->y - grid_height;
6970 if (child->core.x != x || child->core.y != y)
6972 XmeConfigureObject(child, x, y, child->core.width,
6973 child->core.height, child->core.border_width);
6977 /* make sure the icon gadget and tree button, if any, are managed */
6978 if (!XtIsManaged(child) && !ToBeManaged(layout_data, file_view_data))
6980 manage[manageCount++] = child;
6981 if (file_view_data->treebtn)
6982 manage[manageCount++] = file_view_data->treebtn;
6988 /* remember which icons were changed */
6989 change[changeCount++] = file_view_data;
6993 * If the icon we just changed was being renamed, make sure
6994 * the corresponding text widget is positioned correctly.
6996 if (file_view_data == file_mgr_data->renaming)
6998 for (i = 0; i < file_window->composite.num_children; i++)
7000 child = file_window->composite.children[i];
7001 if (XmIsTextField(child))
7003 /* Check if the text field is still needed */
7004 if (!child->core.being_destroyed)
7006 /* move to the correct position */
7007 _DtIconGetTextExtent_r(file_view_data->widget,
7011 (Dimension)(child->core.height - textExtent.height)/(Dimension)2;
7012 XmeConfigureObject(child, x, y, child->core.width,
7014 child->core.border_width);
7017 manage[manageCount++] = child;
7026 /* remember where we left off ... */
7028 layout_data->i_do_next_all = k;
7030 layout_data->i_do_next_vis = k;
7032 #ifdef DT_PERFORMANCE
7033 gettimeofday(&update_time_f, NULL);
7034 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7035 update_time_f.tv_usec += 1000000;
7036 update_time_f.tv_sec--;
7038 printf(" done Part 1, DisplaySomeIcons, time: %ld.%ld\n\n",
7039 update_time_f.tv_sec - update_time_s.tv_sec,
7040 update_time_f.tv_usec - update_time_s.tv_usec);
7042 /* the following message send call added by Rafi */
7043 _DtPerfChkpntMsgSend("Done Display Icons");
7046 #ifdef DT_PERFORMANCE
7047 printf(" Begin Part 2, DisplaySomeIcons (register drop sites)\n");
7048 gettimeofday(&update_time_s, NULL);
7051 _DtPerfChkpntMsgSend("Begin Register drop sites");
7054 /* unregister drop sites of unused icon gadgets */
7056 #ifdef DELAYED_UNREGISTER
7057 for (wp = layout_data->next_icon_to_use;
7058 (child = *wp) != NULL;
7061 if ((Position)(child->core.x + child->core.width) >= (Position)ex &&
7062 child->core.x < ex + ewd &&
7063 (Position)(child->core.y + child->core.height) >= (Position)ey &&
7064 child->core.y < ey + eht)
7066 XtGetValues (child, args_dso_get, 1);
7067 if (operations != XmDROP_NOOP)
7069 XtSetValues (child, args_dso_set, 1);
7072 if (workCount2/2 >= workLimit)
7080 * Register drop sites
7082 * Note: in "as placed" mode, we defer this work and do it in
7083 * CommitWorkProcUpdates instead. Reason: need to re-register
7084 * all drop sites in top-to-bottom stacking order at that time.
7086 if (! PositioningEnabledInView(file_mgr_data) &&
7087 file_mgr_data != trashFileMgrData)
7089 for (k = 0; k < changeCount; k++)
7091 SetHotRects(change[k],
7092 (XtCallbackProc) DropOnObject,
7093 (XtPointer) change[k]);
7098 XtFree((char *)change);
7101 /* update count of children to be managed */
7102 layout_data->manage_count += manageCount;
7105 #ifdef DT_PERFORMANCE
7106 gettimeofday(&update_time_f, NULL);
7107 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7108 update_time_f.tv_usec += 1000000;
7109 update_time_f.tv_sec--;
7111 printf(" done Part 2 DisplaySomeIcons, time: %ld.%ld\n\n",
7112 update_time_f.tv_sec - update_time_s.tv_sec,
7113 update_time_f.tv_usec - update_time_s.tv_usec);
7115 /* the following message send call added by Rafi */
7116 _DtPerfChkpntMsgSend("Done Register drop sites");
7119 DPRINTF2((" ... %d+%d changed (%d managed)\n",
7120 workCount1, workCount2, manageCount));
7123 g_workCount1 += workCount1;
7124 g_workCount2 += workCount2;
7128 return (workCount1 >= workCount2)? workCount1: workCount2;
7132 /************************************************************************
7134 * Display work procedure
7136 ************************************************************************/
7139 CommitWorkProcUpdates(
7140 FileMgrRec *file_mgr_rec,
7141 FileMgrData * file_mgr_data,
7144 XmManagerWidget file_window;
7145 IconLayoutData *layout_data;
7149 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7150 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7152 if (layout_data == NULL)
7156 "CommitWorkProcUpdates: %d+%d updates (m %d, n %d, i %d:%d, reset %d)\n",
7159 layout_data->manage_count,
7161 layout_data->i_do_next_vis,
7162 layout_data->i_do_next_all,
7173 layout_data->i_do_next_vis = 0;
7174 layout_data->i_do_next_all = 0;
7177 /* if work proc no longer active, everything should already be commited */
7178 if (layout_data->work_id == 0)
7181 /* manage new children */
7182 if (layout_data->manage_count > 0)
7184 if (PositioningEnabledInView(file_mgr_data))
7185 OrderChildrenList(file_mgr_data);
7186 XtManageChildren(layout_data->manage, layout_data->manage_count);
7190 * In "as placed" mode, need to register drop sites now.
7191 * (If not "as placed" mode, this was already done in DisplaySomeIcons.)
7193 if (PositioningEnabledInView(file_mgr_data))
7194 RegisterDesktopHotspots(file_mgr_data, file_mgr_rec);
7196 /* commit drop site updates */
7197 XmDropSiteEndUpdate(layout_data->drop_site_w);
7199 /* If not managed yet, manage the file window again */
7200 if (!XtIsManaged((Widget)file_window))
7205 XtManageChild ((Widget)file_window);
7206 XtVaGetValues(file_mgr_rec->vertical_scroll_bar,XmNuserData,&incr,NULL);
7207 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7208 file_mgr_rec->scroll_window)
7211 XtSetArg (args[0], XmNincrement,incr);
7212 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 1);
7214 XmUpdateDisplay ((Widget)file_window);
7217 /* Try to preserve the focus */
7218 if (file_mgr_rec->focus_widget)
7220 /* see if the widget that previously had the focus was just managed */
7222 for (i = 0; i < layout_data->manage_count; i++)
7224 if (layout_data->manage[i] == file_mgr_rec->focus_widget)
7226 w = file_mgr_rec->focus_widget;
7231 /* if focus widget not found, set focus on file_window */
7233 w = (Widget)file_window;
7235 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
7237 file_mgr_rec->focus_widget = NULL;
7240 layout_data->manage_count = 0;
7242 /* start new update */
7243 XmDropSiteStartUpdate(layout_data->drop_site_w);
7249 XtPointer client_data)
7251 FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
7252 DialogData * dialog_data;
7253 FileMgrData * file_mgr_data;
7254 XmManagerWidget file_window;
7255 IconLayoutData *layout_data;
7256 int ex, ey, ewd, eht;
7257 ObjectPosition *bottom;
7260 Boolean commit_updates = False;
7265 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
7266 if (dialog_data == NULL)
7269 file_mgr_data = (FileMgrData *) dialog_data->data;
7270 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7271 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7273 /* get the position and size of the currently visible area */
7274 ex = -file_window->core.x;
7275 ey = -file_window->core.y;
7276 ewd = XtParent(file_window)->core.width;
7277 eht = XtParent(file_window)->core.height;
7279 /* check if the window scrolled */
7280 if (ex != layout_data->ex || ey != layout_data->ey)
7282 layout_data->i_do_next_vis = layout_data->i_do_next_all;
7283 layout_data->visible_done = False;
7286 /* first work on icons in the currently visible area */
7287 if (layout_data->visible_done)
7291 n = DisplaySomeIcons(file_mgr_rec, file_mgr_data, ex, ey, ewd, eht, n1, False);
7294 /* we just finished updating all visible icons */
7295 DPRINTF(("DisplayWorkProc: visible done.\n"));
7296 layout_data->visible_done = True;
7297 commit_updates = True;
7301 /* if we still have some time left, work on other icons */
7302 if (layout_data->visible_done && n < n2)
7304 n = DisplaySomeIcons(file_mgr_rec, file_mgr_data,
7305 0, 0, 32767, 32767, n2 - n, True);
7307 /* check if we are done */
7310 layout_data->all_done = True;
7311 commit_updates = True;
7313 else if (layout_data->manage_count >= 100)
7314 commit_updates = True;
7319 /* manage new children and commit drop site updates */
7320 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, False);
7323 * In "as placed" mode, icons may overlap.
7324 * Force redraw in bottom to top stacking order.
7326 if (PositioningEnabledInView(file_mgr_data))
7328 for (bottom = GetBottomOfStack(file_mgr_data);
7330 bottom = (ObjectPosition *)bottom->prev)
7332 if (bottom->file_view_data != NULL &&
7333 bottom->file_view_data->displayed &&
7334 !bottom->file_view_data->need_update)
7336 child = bottom->file_view_data->widget;
7337 if ((Position)(child->core.x + child->core.width) >= (Position)ex &&
7338 child->core.x < ex + ewd &&
7339 (Position)(child->core.y + child->core.height) >= (Position)ey &&
7340 child->core.y < ey + eht)
7342 RedrawOneGadget(child, NULL, NULL);
7349 if (layout_data->all_done)
7351 /* all work is done; all icons are up-to-date */
7352 file_mgr_data->newSize = False;
7353 layout_data->work_id = 0;
7354 XmDropSiteEndUpdate(layout_data->drop_site_w);
7356 DPRINTF(("DisplayWorkProc: all done.\n"));
7358 /* returning True will end the work proc */
7363 /* remember current scroll position */
7364 layout_data->ex = ex;
7365 layout_data->ey = ey;
7371 /************************************************************************
7374 * Position and size the full set of icons for the file mgr data.
7376 ************************************************************************/
7380 FileMgrRec *file_mgr_rec,
7381 FileMgrData *file_mgr_data,
7382 Boolean update_scrolling_position,
7383 Boolean turn_off_hourglass )
7385 #ifdef DT_PERFORMANCE
7386 struct timeval update_time_s;
7387 struct timeval update_time_f;
7389 XmManagerWidget file_window;
7390 FileViewData ** order_list;
7392 int total_icon_count;
7393 IconLayoutData *layout_data;
7394 Dimension file_window_width, file_window_height;
7395 Dimension scrolled_window_width, scrolled_window_height;
7396 Dimension vert_scrollbar_width, horiz_scrollbar_height;
7397 Dimension grid_width, grid_height;
7398 Dimension icon_width, icon_height;
7399 Dimension extra_height;
7400 Dimension sw_shadow_thickness, sb_highlight_thickness, space;
7402 int level, max_level;
7403 FileViewData *file_view_data;
7404 Boolean overflow = False;
7413 unsigned char operations = 0L;
7414 static XtCallbackRec dropCB[] = { {DropOnFileWindow, NULL}, {NULL, NULL} };
7417 /* if directory-read still in progress, don't do anything now */
7418 if (file_mgr_data->busy_status != not_busy)
7421 DPRINTF(("LayoutFileIcons(\"%s\", u_s_p %c, t_o_h %c) ...\n",
7422 file_mgr_data->current_directory,
7423 update_scrolling_position? 'T': 'F',
7424 turn_off_hourglass? 'T': 'F'));
7426 #ifdef DT_PERFORMANCE
7427 printf(" Begin LayoutFileIcons\n");
7428 gettimeofday(&update_time_s, NULL);
7431 _DtPerfChkpntMsgSend("Begin Layout Icons");
7435 * Just in case a previous update work proc is still active,
7436 * we commit pending updates made by the work proc before we
7437 * start making changes.
7439 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, True);
7441 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7442 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7444 fileType = GetDirectoryLogicalType(file_mgr_data,
7445 file_mgr_data->current_directory);
7446 operations = TypeToDropOperations(fileType);
7448 if (!file_mgr_data->dropSite)
7450 dropCB[0].closure = (XtPointer)file_mgr_data;
7452 DtDndVaDropRegister((Widget)file_mgr_rec->file_window,
7453 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
7456 DtNdropAnimateCallback, dropCB,
7457 DtNregisterChildren, True,
7458 DtNtextIsBuffer, True,
7459 XmNanimationStyle, XmDRAG_UNDER_SHADOW_IN,
7461 file_mgr_data->dropSite = True;
7465 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
7466 XmDropSiteUpdate((Widget)file_mgr_rec->file_window, args, 1);
7472 XtSetArg (args[0], XmNdropSiteOperations, operations);
7474 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
7475 XmDropSiteUpdate((Widget)file_mgr_rec->file_window, args, 1);
7478 /* Get the count of the total icon to be displayed. */
7479 order_list = layout_data->order_list;
7480 order_count = layout_data->order_count;
7481 total_icon_count = 0;
7482 for (i = 0; i < order_count; i++)
7484 if (order_list[i]->displayed)
7488 /* Get the colors to be used for drawing the icons */
7489 XtSetArg (args[0], XmNbackground, &layout_data->background);
7490 XtSetArg (args[1], XmNforeground, &layout_data->foreground);
7492 XtSetArg (args[2], XmNtopShadowColor, &layout_data->topshadow);
7493 XtGetValues (file_mgr_rec->file_window, args, 3);
7495 XtGetValues (file_mgr_rec->file_window, args, 2);
7497 XtSetArg (args[0], XmNtopShadowColor, &layout_data->pixmap_back);
7498 XtSetArg (args[1], XmNbottomShadowColor, &layout_data->pixmap_fore);
7499 XtGetValues (file_mgr_rec->main, args, 2);
7502 * Create/update icon gadget for ".".
7503 * This gadget may not actually be displayed (depends of filter settings;
7504 * by default it is filtered out), but we need at least one gadget
7505 * created here so we can figure out fonts and margins used by icon
7506 * gadgets. This is necessary to compute the grid spacing.
7508 for (i = 0; i < order_count; i++)
7509 if (strcmp(order_list[i]->file_data->file_name, ".") == 0)
7511 UpdateOneFileIcon(file_mgr_rec, file_mgr_data, order_list[i]);
7512 order_list[i]->need_update = True;
7516 /* Find the icon with the longest label */
7518 file_view_data = NULL;
7519 for (i = 0; i < order_count; i++)
7521 if (!order_list[i]->filtered &&
7522 (len = strlen(order_list[i]->label)) > max_len)
7524 file_view_data = order_list[i];
7529 /* get the size of the icon with the longest label */
7530 GetIconLayoutParms(file_mgr_rec, file_mgr_data, layout_data);
7531 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data, file_view_data,
7532 &grid_width, &grid_height);
7534 /* for tree view add space for tree lines and buttons */
7536 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
7538 for (i = 0; i < order_count; i++)
7540 if (order_list[i]->displayed)
7542 GetLevel(order_list[i], &level);
7543 if (level > max_level)
7547 grid_width += TreeWd(max_level, layout_data->treebtn_size);
7550 file_mgr_data->grid_height = grid_height;
7551 file_mgr_data->grid_width = grid_width;
7554 * If positioning is enabled in this view, then we need to use the other
7555 * layout function, which is capable of handling overlapping icons and
7558 if (PositioningEnabledInView(file_mgr_data))
7560 if (file_mgr_data->object_positions)
7562 LayoutDesktopIcons(file_mgr_rec, file_mgr_data,
7563 order_list, order_count, turn_off_hourglass);
7564 /* RepairFileWindow(file_mgr_data); *OBSOLETE* */
7570 * Position and size the icons according to the show and view types.
7573 scrolled_window_width = file_mgr_rec->scroll_window->core.width;
7574 scrolled_window_height = file_mgr_rec->scroll_window->core.height;
7575 vert_scrollbar_width = file_mgr_rec->vertical_scroll_bar->core.width;
7576 horiz_scrollbar_height = file_mgr_rec->horizontal_scroll_bar->core.height;
7578 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
7580 /* if not yet done, create tree button icons */
7581 if (TreeBtnWd[0] == 0)
7582 CreateTreeIcons(file_mgr_rec->file_window);
7584 /* layout for tree mode */
7587 file_window_width = MARGIN + grid_width - TreeOffset + XSPACING;
7589 for (k = 0; k < order_count; k++)
7591 if (!order_list[k]->displayed)
7594 /* make sure window height won't exceed limit */
7595 extra_height = GetExtraHeight(file_mgr_data, order_list[k],
7596 layout_data->treebtn_size);
7597 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
7598 if (tmp + MARGIN > MAXWINSIZE)
7600 /* window would exceed height limit; start a new column */
7601 x += grid_width + XSPACING;
7603 file_window_width += grid_width + XSPACING;
7604 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
7608 order_list[k]->x = x;
7609 order_list[k]->y = y + grid_height;
7616 file_window_height = MAXWINSIZE;
7618 file_window_height = y + MARGIN;
7620 else if (file_mgr_data->view == BY_ATTRIBUTES)
7622 /* layout for details view, no tree mode */
7625 file_window_width = 2*MARGIN + grid_width;
7627 for (k = 0; k < order_count; k++)
7629 if (!order_list[k]->displayed)
7632 /* make sure window height won't exceed limit */
7633 tmp = (int)y + grid_height + YSPACING(file_mgr_data);
7634 if (tmp + MARGIN > MAXWINSIZE)
7636 /* window would exceed height limit; start a new column */
7637 x += grid_width + XSPACING;
7639 file_window_width += grid_width + XSPACING;
7640 tmp = (int)y + grid_height + YSPACING(file_mgr_data);
7644 order_list[k]->x = x;
7645 order_list[k]->y = y + grid_height;
7652 file_window_height = MAXWINSIZE;
7654 file_window_height = y + MARGIN;
7656 else /* show_type == SINGLE_DIRECTORY, view != BY_ATTRIBUTES */
7658 /* layout for "normal" views (no tree mode, no details) */
7660 /* calculate how many columns fit in the window width */
7661 column_count = ((int)scrolled_window_width - 4 - 2*MARGIN + XSPACING) /
7662 ((int)grid_width + XSPACING);
7663 if (column_count == 0)
7664 column_count = 1; /* need at least one column */
7667 * Calculate the window height. Need to do calculation in int's
7668 * rather than short (Dimension) because of possible overflow.
7670 row_count = (total_icon_count + column_count - 1) / column_count;
7671 tmp = 2*MARGIN - YSPACING(file_mgr_data) +
7672 row_count * ((int)grid_height + YSPACING(file_mgr_data));
7674 /* check if the height is larger than the scrolled window */
7675 if (tmp >= (int)scrolled_window_height - 2*MARGIN)
7677 /* need to recompute everything because of space for vert scrollbar */
7678 column_count = ((int)scrolled_window_width - 4 - 2*MARGIN + XSPACING
7679 - (int)vert_scrollbar_width)
7680 / ((int)grid_width + XSPACING);
7681 if (column_count == 0)
7683 row_count = (total_icon_count + column_count - 1) / column_count;
7684 tmp = 2*MARGIN - YSPACING(file_mgr_data) +
7685 row_count * ((int)grid_height + YSPACING(file_mgr_data));
7688 /* check if the window height is within the limit */
7689 if (tmp <= MAXWINSIZE)
7690 file_window_height = (Dimension)tmp;
7693 /* window height too large; use more columns */
7695 row_count = (int)(MAXWINSIZE - 2*MARGIN + YSPACING(file_mgr_data)) /
7696 (int)((int)grid_height + YSPACING(file_mgr_data));
7697 column_count = (total_icon_count + row_count - 1) / row_count;
7698 row_count = (total_icon_count + column_count - 1) / column_count;
7699 file_window_height = (Dimension) (2*MARGIN - YSPACING(file_mgr_data) +
7700 row_count * ((int)grid_height + YSPACING(file_mgr_data)));
7703 DPRINTF((" %d columns, %d rows (scroll_window width %d)\n",
7704 column_count, row_count,
7705 scrolled_window_width));
7707 /* assign positions to all icons */
7709 file_window_width = (Dimension)
7710 (2*MARGIN - XSPACING + column_count*((int)grid_width + XSPACING));
7713 for (i = 0; i < row_count; i++)
7717 for (j = 0; j < column_count && k < order_count;)
7719 /* find the next icon to display */
7720 while (k < order_count && !order_list[k]->displayed)
7722 if (k == order_count)
7725 if (layout_data->alignment == XmALIGNMENT_CENTER &&
7726 file_mgr_data->view == BY_NAME_AND_ICON)
7728 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data,
7729 order_list[k], &icon_width, &icon_height);
7730 order_list[k]->x = x +
7731 (Dimension)(grid_width - icon_width)/(Dimension)2;
7734 order_list[k]->x = x;
7735 order_list[k]->y = y + grid_height;
7737 x += grid_width + XSPACING;
7742 y += grid_height + YSPACING(file_mgr_data);
7746 DPRINTF((" file_window size: width %d, height %d\n",
7747 file_window_width, file_window_height));
7749 /* Manage/unmanage the scrollbars as needed. */
7751 XtSetArg (args[0], XmNwidth, file_window_width);
7752 XtSetArg (args[1], XmNheight, file_window_height);
7753 XtSetValues ((Widget)file_window, args, 2);
7755 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
7756 XtSetValues (file_mgr_rec->scroll_window, args, 1);
7759 /* Unmanage the horizontal scrollbar if it is not needed */
7760 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7761 file_mgr_rec->scroll_window))
7763 if (file_window_width >= (Dimension)(scrolled_window_width - 4 -
7764 vert_scrollbar_width))
7765 XtManageChild (file_mgr_rec->horizontal_scroll_bar);
7768 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
7769 XtSetArg (args[0], XmNx, 0);
7770 XtSetValues ((Widget)file_window, args, 1);
7773 else if (file_window_width >= (Dimension)(scrolled_window_width - 4))
7774 XtManageChild (file_mgr_rec->horizontal_scroll_bar);
7777 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
7778 XtSetArg (args[0], XmNx, 0);
7779 XtSetValues ((Widget)file_window, args, 1);
7782 XSync (XtDisplay (file_window), False);
7784 /* Set the file window width and height to be at least */
7785 /* the size of the scrolled window. */
7787 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7788 file_mgr_rec->scroll_window))
7790 if(file_window_width <= (Dimension)(scrolled_window_width -
7791 (vert_scrollbar_width + 4)))
7793 file_window_width = scrolled_window_width -
7794 (vert_scrollbar_width + 4);
7798 if(file_window_width < (Dimension)(scrolled_window_width - 4))
7799 file_window_width = scrolled_window_width - 4;
7802 if (HorizontalScrollbarIsVisible(file_mgr_rec->horizontal_scroll_bar,
7803 file_mgr_rec->scroll_window))
7807 XtSetArg (args[0], XmNhighlightThickness, &sb_highlight_thickness);
7808 XtGetValues ((Widget)file_mgr_rec->horizontal_scroll_bar, args, 1);
7810 XtSetArg (args[0], XmNshadowThickness, &sw_shadow_thickness);
7811 XtSetArg (args[1], XmNspacing, &space);
7812 XtGetValues ((Widget)file_mgr_rec->scroll_window, args, 2);
7814 pad = (int)(((sb_highlight_thickness + sw_shadow_thickness) * 2) + space);
7816 if(file_window_height < (Dimension)(scrolled_window_height -
7817 (horiz_scrollbar_height + pad)))
7818 file_window_height = scrolled_window_height -
7819 (horiz_scrollbar_height + pad);
7823 if (file_window_height < (Dimension)(scrolled_window_height - 4))
7824 file_window_height = scrolled_window_height - 4;
7828 XtSetArg (args[0], XmNwidth, file_window_width);
7829 XtSetArg (args[1], XmNheight, file_window_height);
7830 XtSetValues ((Widget)file_window, args, 2);
7832 if( file_mgr_data->scrollToThisFile == NULL )
7834 if (update_scrolling_position)
7836 XtSetArg (args[0], XmNx, 0);
7837 XtSetArg (args[1], XmNy, 0);
7838 XtSetValues ((Widget)file_window, args, 2);
7841 /* Set the vertical scrollbar's increment to icon height */
7842 XtSetArg (args[0], XmNincrement, grid_height + YSPACING(file_mgr_data));
7843 XtSetArg (args[1], XmNuserData, grid_height + YSPACING(file_mgr_data));
7844 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 2);
7847 if (PositioningEnabledInView(file_mgr_data))
7849 BuildObjectPositions(file_mgr_data);
7850 /* RepairFileWindow(file_mgr_data); *OBSOLETE* */
7854 * Don't keep up the hourglass; this helps the user to get the impression
7855 * that all of the work is done.
7857 if (turn_off_hourglass && !overflow)
7858 _DtTurnOffHourGlass(file_mgr_rec->shell);
7865 * Start up a work proc that will update the display.
7867 layout_data->visible_done = False;
7868 layout_data->all_done = False;
7869 if (layout_data->work_id == 0)
7871 XtAppContext app_context =
7872 XtWidgetToApplicationContext(file_mgr_rec->shell);
7874 DPRINTF(("LayoutFileIcons: starting workproc\n"));
7875 layout_data->drop_site_w = (Widget)file_mgr_rec->shell;
7876 XmDropSiteStartUpdate(layout_data->drop_site_w);
7878 layout_data->work_id =
7879 XtAppAddWorkProc(app_context, DisplayWorkProc, file_mgr_rec);
7883 if( file_mgr_data->scrollToThisFile )
7886 DirectorySet * directory_set = NULL;
7888 file_view_data = NULL;
7890 for( i = 0; i < file_mgr_data->directory_count; ++i)
7892 if( strcmp( ((DirectorySet *)file_mgr_data->directory_set[i])->name, file_mgr_data->scrollToThisDirectory ) == 0 )
7894 directory_set = (DirectorySet *)file_mgr_data->directory_set[i];
7901 for( i = 0; i < directory_set->file_count; ++i )
7903 if( strcmp( directory_set->order_list[i]->file_data->file_name,
7904 file_mgr_data->scrollToThisFile ) == 0 )
7906 file_view_data = directory_set->order_list[i];
7913 && file_view_data->filtered == False )
7915 FileMgrRec * file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
7917 DeselectAllFiles( file_mgr_data );
7918 SelectFile( file_mgr_data, file_view_data );
7919 ActivateSingleSelect( file_mgr_rec,
7920 file_mgr_data->selection_list[0]->file_data->logical_type );
7922 PositionFileView(file_view_data, file_mgr_data);
7926 if (update_scrolling_position)
7928 XtSetArg (args[0], XmNx, 0);
7929 XtSetArg (args[1], XmNy, 0);
7930 XtSetValues ((Widget)file_window, args, 2);
7933 /* Set the vertical scrollbar's increment to icon height */
7934 XtSetArg (args[0], XmNincrement, grid_height + YSPACING(file_mgr_data));
7935 XtSetArg (args[1], XmNuserData, grid_height + YSPACING(file_mgr_data));
7936 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 2);
7939 XtFree( file_mgr_data->scrollToThisFile );
7940 file_mgr_data->scrollToThisFile = NULL;
7941 XtFree( file_mgr_data->scrollToThisDirectory );
7942 file_mgr_data->scrollToThisDirectory = NULL;
7945 #ifdef DT_PERFORMANCE
7946 gettimeofday(&update_time_f, NULL);
7947 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7948 update_time_f.tv_usec += 1000000;
7949 update_time_f.tv_sec--;
7951 printf(" done LayoutFileIcons, time: %ld.%ld\n\n",
7952 update_time_f.tv_sec - update_time_s.tv_sec,
7953 update_time_f.tv_usec - update_time_s.tv_usec);
7955 /* the following message send call added by Rafi */
7956 _DtPerfChkpntMsgSend("Done LayoutFileIcons");
7959 DPRINTF(("... done\n"));
7964 /************************************************************************
7967 * Callback function invoked upon clicking the tree-branch-expand button.
7969 ************************************************************************/
7974 XtPointer clientData,
7975 XmAnyCallbackStruct *callData )
7977 FileMgrRec *file_mgr_rec;
7978 FileMgrData *file_mgr_data;
7979 FileViewData *file_view_data = (FileViewData *)clientData;
7983 /* check which mouse button was pressed */
7984 if ((callData->event->type == ButtonPress ||
7985 callData->event->type == ButtonRelease) &&
7986 ((XButtonEvent *)callData->event)->button != Button1)
7992 /* get file mgr data and record */
7993 XtSetArg (args[0], XmNuserData, &file_mgr_data);
7994 XtGetValues (w, args, 1);
7995 file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
7997 XmDropSiteStartUpdate(file_mgr_rec->file_window);
7998 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, True);
7999 DirTreeExpand(file_mgr_data, file_view_data, expand);
8000 DrawCurrentDirectory (file_mgr_rec->current_directory,
8001 file_mgr_rec, file_mgr_data);
8002 LayoutFileIcons(file_mgr_rec, file_mgr_data, False, True);
8003 XmDropSiteEndUpdate(file_mgr_rec->file_window);
8004 RedrawTreeLines(file_mgr_rec->file_window,
8005 -file_mgr_rec->file_window->core.x,
8006 -file_mgr_rec->file_window->core.y,
8007 XtParent(file_mgr_rec->file_window)->core.width,
8008 XtParent(file_mgr_rec->file_window)->core.height,
8009 0, file_mgr_rec, file_mgr_data);
8014 * When a drop occurs on a File Manger window, which now
8015 * support random placement, what is dropped may not ultimately be what
8016 * is displayed. Since the dissolve transition effect has been disabled
8017 * for drops on the desktop, we can sometimes end up with garbage left on
8018 * the desktop. This function will attempt to clear up the leftover garbage,
8019 * by resetting all areas of the desktop which are not covered by an icon
8020 * to the background color for the file window.
8022 * This function is OBSOLETE (?).
8027 FileMgrData * file_mgr_data)
8030 FileMgrRec * file_mgr_rec;
8033 Region redrawRegion;
8038 XmManagerWidget file_window;
8043 file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
8044 file_window = (XmManagerWidget)file_mgr_rec->file_window;
8046 /* Initialize the clip region to that of the file window */
8049 rect.height = file_window->core.height;
8050 rect.width = file_window->core.width;
8051 clipList = XCreateRegion();
8052 XUnionRectWithRegion(&rect, clipList, clipList);
8054 /* Subtract out the hotspots associated with each icon */
8055 num_children = file_window->composite.num_children;
8056 children = file_window->composite.children;
8057 hotspot = XCreateRegion();
8059 for (i = 0; i < num_children; i++)
8061 if (XtIsManaged(children[i]) &&
8062 XtIsSubclass(children[i], dtIconGadgetClass))
8064 WidgetRectToRegion(file_mgr_data, children[i], hotspot);
8065 XSubtractRegion(clipList, hotspot, clipList);
8069 /* Create a GC for doing our drawing */
8070 mask = GCForeground;
8071 values.foreground = file_window->core.background_pixel;
8072 gc = XCreateGC(XtDisplay(file_window), XtWindow(file_window), mask, &values);
8073 XSetRegion(XtDisplay(file_window), gc, clipList);
8075 /* Restore the window */
8076 XFillRectangle(XtDisplay(file_window), XtWindow(file_window), gc, 0, 0,
8077 file_window->core.width, file_window->core.height);
8080 * Force all icons to redraw, since we are only able to repair the
8081 * areas where icons are not; the drop image may have extended onto
8082 * some of the icons.
8086 rect.height = file_window->core.height;
8087 rect.width = file_window->core.width;
8088 redrawRegion = XCreateRegion();
8089 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
8090 (*file_window->core.widget_class->core_class.expose)
8091 ((Widget)file_window, NULL, redrawRegion);
8094 XFreeGC(XtDisplay(file_window), gc);
8095 XDestroyRegion(clipList);
8096 XDestroyRegion(hotspot);
8097 XDestroyRegion(redrawRegion);
8104 * Compress the stacking order values, anytime an item is removed.
8108 CompressObjectList (
8109 ObjectPosition ** object_positions,
8115 for (i = 0; i < num_objects; i++)
8117 if (object_positions[i]->stacking_order > starting_index)
8118 object_positions[i]->stacking_order--;
8124 /************************************************************************
8126 * LayoutDesktopIcons
8127 * Position and size the full set of icons for the file mgr data.
8129 ************************************************************************/
8132 LayoutDesktopIcons (
8133 FileMgrRec * file_mgr_rec,
8134 FileMgrData * file_mgr_data,
8135 FileViewData ** order_list,
8137 Boolean turn_off_hourglass )
8140 XmManagerWidget file_window;
8141 int directory_count, largest_x, largest_y;
8142 int value = 0, size, increment, page;
8143 Dimension current_wd;
8144 Dimension current_ht;
8145 Dimension file_window_width;
8146 Dimension grid_height;
8147 Dimension grid_width;
8148 FileViewData * object;
8149 ObjectPosition * position_data;
8150 ObjectPosition * bottom;
8153 Boolean set_size = False;
8159 /* Get the grid block size */
8160 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8161 grid_height = file_mgr_data->grid_height;
8162 grid_width = file_mgr_data->grid_width;
8164 file_window_width = file_mgr_rec->scroll_window->core.width - 4;
8165 current_ht = file_mgr_rec->file_window->core.height;
8166 current_wd = file_mgr_rec->file_window->core.width;
8169 /* Before positioning, mark all position entries as 'not used' */
8170 for (i = 0; i < file_mgr_data->num_objects; i++)
8172 file_mgr_data->object_positions[i]->in_use = False;
8173 file_mgr_data->object_positions[i]->file_view_data = NULL;
8177 * Before attempting to place new icons, we need to make sure that
8178 * all of the existing object_positions entries have had their
8179 * file_view_data field filled in. This is so that during placement,
8180 * we can get the height and width of the associated icons, to help
8183 for (i = 0; i < order_count; i++)
8185 object = order_list[i];
8186 if (object->displayed)
8188 if (position_data = GetPositionalData(file_mgr_data, object, 0, False))
8190 /* Save; used later during redraw */
8191 position_data->file_view_data = object;
8192 object->position_info = (ObjectPtr)position_data;
8195 else if (position_data = GetPositionalData(file_mgr_data, object, 0,
8199 * If an object has position information, but is currently
8200 * filtered, don't discard its position info; mark it as in-use.
8202 position_data->file_view_data = object;
8203 object->position_info = (ObjectPtr)position_data;
8207 /* Remove any unused position data entries */
8208 for (i = 0; i < file_mgr_data->num_objects; )
8210 if (!file_mgr_data->object_positions[i]->in_use)
8212 /* If this object had a text field, delete it */
8213 for (k = 0; k < file_window->composite.num_children; k++)
8215 if (XmIsTextField(file_window->composite.children[k]) &&
8216 !file_window->composite.children[k]->core.being_destroyed)
8218 XtSetArg(args[0], XmNuserData, &edit_name);
8219 XtGetValues(file_window->composite.children[k], args, 1);
8220 if (strcmp(edit_name,file_mgr_data->object_positions[i]->name)
8224 XtUnmanageChild(file_window->composite.children[k]);
8225 XtDestroyWidget(file_window->composite.children[k]);
8231 /* Free up the entry; bump up the other array entries */
8232 /* Update the linked list */
8233 if (file_mgr_data->object_positions[i]->prev)
8235 file_mgr_data->object_positions[i]->prev->next = (ObjectPtr)
8236 file_mgr_data->object_positions[i]->next;
8238 if (file_mgr_data->object_positions[i]->next)
8240 file_mgr_data->object_positions[i]->next->prev = (ObjectPtr)
8241 file_mgr_data->object_positions[i]->prev;
8243 sorder = file_mgr_data->object_positions[i]->stacking_order;
8244 XtFree(file_mgr_data->object_positions[i]->name);
8245 file_mgr_data->object_positions[i]->name = NULL;
8246 XtFree((char *)file_mgr_data->object_positions[i]);
8247 file_mgr_data->object_positions[i] = NULL;
8248 for (j = i; j < file_mgr_data->num_objects - 1; j++)
8250 file_mgr_data->object_positions[j] =
8251 file_mgr_data->object_positions[j+1];
8253 file_mgr_data->num_objects--;
8254 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8255 (char *)file_mgr_data->object_positions,
8256 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8257 CompressObjectList(file_mgr_data->object_positions,
8258 file_mgr_data->num_objects, sorder);
8264 /* Now, it is safe to position any unplaced objects */
8265 for (i = 0; i < order_count; i++)
8267 object = order_list[i];
8268 if (object->displayed)
8270 position_data = GetPositionalData(file_mgr_data, object,
8271 file_window_width, True);
8273 /* Save; used later during redraw */
8274 position_data->file_view_data = object;
8275 object->position_info = (ObjectPtr)position_data;
8277 /* record position of bottom left corner for DisplaySomeIcons */
8278 object->x = position_data->x;
8279 object->y = position_data->y +
8280 (object->need_update? grid_height: object->widget->core.height);
8284 /* Get largest x value */
8287 bottom = GetBottomOfStack(file_mgr_data);
8290 if (bottom->file_view_data != NULL && bottom->file_view_data->displayed)
8292 if (bottom->file_view_data->position_info->x > largest_x)
8293 largest_x = bottom->file_view_data->position_info->x;
8294 if (bottom->file_view_data->position_info->y > largest_y)
8295 largest_y = bottom->file_view_data->position_info->y;
8297 bottom = (ObjectPosition *)bottom->prev;
8299 largest_x += grid_width;
8300 largest_y += grid_height;
8302 /* if necessary, shrink the width & height to what we need */
8303 if (current_wd == 32767)
8305 current_wd = largest_x;
8309 if (current_ht == 32767)
8311 current_ht = largest_y;
8315 /* Get the horizontal and vertical scrollbars. */
8316 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
8317 XtSetValues (file_mgr_rec->scroll_window, args, 1);
8320 * Typically, dtfile does everything possible to prevent a horizontal
8321 * scrollbar from being displayed. However, when random placement is
8322 * enabled, we don't mind having a horizontal scrollbar, when needed.
8323 * We need to manually manage this, since the normal dtfile layout
8324 * code may have forcably unmanaged the scrollbar earlier.
8326 if (XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8328 /* get scroll bar values */
8329 (void)XmScrollBarGetValues(file_mgr_rec->horizontal_scroll_bar,
8330 &value, &size, &increment, &page);
8333 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
8334 file_mgr_rec->scroll_window))
8336 if ((Dimension)largest_x >= (Dimension)(file_mgr_rec->scroll_window->core.width -
8337 (file_mgr_rec->vertical_scroll_bar->core.width + 4)))
8339 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8343 /* set scroll bar values changing its position */
8344 if(value != 0 && XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8345 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8348 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
8349 XtSetArg (args[0], XmNx, 0);
8350 XtSetValues ((Widget)file_window, args, 1);
8354 else if ((Dimension)largest_x >= (Dimension)(file_mgr_rec->scroll_window->core.width - 4))
8355 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8358 /* set scroll bar values changing its position */
8359 if(value != 0 && XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8360 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8363 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
8364 XtSetArg (args[0], XmNx, 0);
8365 XtSetValues ((Widget)file_window, args, 1);
8369 /* Set the file window width and height to be at least */
8370 /* the size of the scrolled window. */
8371 if ((Dimension)(current_wd) < (Dimension)(file_mgr_rec->scroll_window->core.width - 4))
8373 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
8374 file_mgr_rec->scroll_window))
8375 current_wd = file_mgr_rec->scroll_window->core.width -
8376 (file_mgr_rec->vertical_scroll_bar->core.width + 4);
8378 current_wd = file_mgr_rec->scroll_window->core.width - 4;
8382 if ((Dimension)(current_ht) < (Dimension)(file_mgr_rec->scroll_window->core.height - 4))
8384 current_ht = file_mgr_rec->scroll_window->core.height - 4;
8390 XtSetArg (args[0], XmNwidth, current_wd);
8391 XtSetArg (args[1], XmNheight, current_ht);
8392 XtSetValues (file_mgr_rec->file_window, args, 2);
8395 /* Set the vertical scrollbar's increment to icon height */
8396 XtSetArg (args[0], XmNincrement, file_mgr_data->grid_height + 2);
8397 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 1);
8400 * Don't keep up the hourglass; this helps the user to get the impression
8401 * that all of the work is done.
8403 if (turn_off_hourglass)
8404 _DtTurnOffHourGlass(file_mgr_rec->shell);
8408 /***************************************************
8410 * Given a desktop object, see if it has already been assigned a position;
8411 * if not, then try to fit it into the next available grid position.
8413 **************************************************/
8427 int srcABot, srcBBot;
8428 int srcARight, srcBRight;
8432 srcABot = y1 + h1 - 1;
8433 srcBBot = y2 + h2 - 1;
8434 srcARight = x1 + w1 - 1;
8435 srcBRight = x2 + w2 - 1;
8447 if (srcARight >= srcBRight)
8448 dw = srcBRight - dx + 1;
8450 dw = srcARight - dx + 1;
8452 if (srcABot > srcBBot)
8453 dh = srcBBot - dy + 1;
8455 dh = srcABot - dy + 1;
8457 if (dw <= 0 || dh <= 0)
8463 static ObjectPosition *
8465 FileMgrData * file_mgr_data,
8466 FileViewData * object,
8467 Dimension max_width,
8472 ObjectPosition *entry, *top;
8475 Dimension grid_height;
8476 Dimension grid_width;
8478 ObjectPosition * oP;
8479 Dimension objWidth, objHeight;
8480 Dimension oWidth, oHeight;
8482 /* If object already has positional data, then use it */
8483 for (i = 0; i < file_mgr_data->num_objects; i++)
8485 if (strcmp(object->file_data->file_name,
8486 file_mgr_data->object_positions[i]->name) == 0)
8489 file_mgr_data->object_positions[i]->in_use = True;
8490 return(file_mgr_data->object_positions[i]);
8497 /* Create a new entry, and place into the grid on the top of the stack */
8498 entry = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8499 entry->name = XtNewString(object->file_data->file_name);
8500 entry->in_use = True;
8501 entry->late_bind = False;
8502 entry->stacking_order = 2;
8505 entry->file_view_data = NULL;
8507 if(file_mgr_data->num_objects == 1)
8509 top = file_mgr_data->object_positions[0];
8510 top->next = (ObjectPtr)entry;
8511 entry->prev = (ObjectPtr)top;
8516 /* Push all other objects down in the stack */
8517 for (i = 0; i < file_mgr_data->num_objects; i++)
8519 /* Find the previous top of the stack */
8520 if (file_mgr_data->object_positions[i]->stacking_order == 1)
8522 top = file_mgr_data->object_positions[i];
8525 else if (file_mgr_data->object_positions[i]->stacking_order == 2)
8528 top = GetTopOfStack(file_mgr_data);
8529 top->next = (ObjectPtr)entry;
8530 entry->next = (ObjectPtr)file_mgr_data->object_positions[i];
8531 entry->prev = (ObjectPtr)top;
8532 file_mgr_data->object_positions[i]->prev = (ObjectPtr)entry;
8534 file_mgr_data->object_positions[i]->stacking_order++;
8538 grid_height = file_mgr_data->grid_height;
8539 grid_width = file_mgr_data->grid_width;
8543 if (object->widget && !object->need_update)
8545 objWidth = object->widget->core.width;
8546 objHeight = object->widget->core.height;
8550 objWidth = grid_width;
8551 objHeight = grid_height;
8554 /* Find the first open spot, which will not cause any overlap */
8559 for (i = 0; i < file_mgr_data->num_objects; i++)
8561 oP = file_mgr_data->object_positions[i];
8562 if (oP->file_view_data->widget && !oP->file_view_data->need_update)
8564 oWidth = oP->file_view_data->widget->core.width;
8565 oHeight = oP->file_view_data->widget->core.height;
8569 oWidth = grid_width;
8570 oHeight = grid_height;
8572 if (oP->file_view_data->displayed &&
8573 IntersectRects(x, y, objWidth, objHeight,
8574 oP->x, oP->y, oWidth, oHeight))
8576 /* Try next grid spot */
8577 x += grid_width + XSPACING;
8579 if ((Dimension)(x + objWidth) >= max_width)
8581 /* Go to next row */
8582 y += grid_height + YSPACING(file_mgr_data);
8591 /* Add to the end of the list */
8594 file_mgr_data->num_objects++;
8595 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8596 (char *)file_mgr_data->object_positions,
8597 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8599 /* Force the ordered list to be maintained */
8600 for (i = 0; i < file_mgr_data->num_objects - 1; i++)
8602 if ((entry->y < file_mgr_data->object_positions[i]->y) ||
8603 ((entry->y == file_mgr_data->object_positions[i]->y) &&
8604 (entry->x < file_mgr_data->object_positions[i]->x)))
8606 /* Fits here; slide later entries down */
8607 for (k = file_mgr_data->num_objects - 1; k > i; k--)
8609 file_mgr_data->object_positions[k] =
8610 file_mgr_data->object_positions[k-1];
8617 file_mgr_data->object_positions[i] = entry;
8618 return(file_mgr_data->object_positions[i]);
8622 /*******************************************************************
8624 * BuildObjectPositons - builds up the object positions for directories
8625 * which have now object position information.
8627 *********************************************************************/
8629 BuildObjectPositions(
8630 FileMgrData *file_mgr_data)
8633 FileViewData * file_view_data;
8634 ObjectPosition * ptr;
8636 file_mgr_data->object_positions = (ObjectPosition **)XtMalloc(
8637 sizeof(ObjectPosition *) *
8638 file_mgr_data->directory_set[0]->file_count);
8640 for (i = 0, j = 0; i < file_mgr_data->directory_set[0]->file_count; i++)
8642 file_view_data = file_mgr_data->directory_set[0]->order_list[i];
8644 if (file_view_data->filtered)
8647 ptr = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8648 ptr->name = XtNewString(file_view_data->file_data->file_name);
8649 ptr->x = file_view_data->x;
8650 ptr->y = file_view_data->y -
8651 (file_view_data->need_update? file_mgr_data->grid_height:
8652 file_view_data->widget->core.height);
8654 ptr->late_bind = False;
8655 ptr->stacking_order = j+1;
8656 ptr->file_view_data = file_view_data;
8657 file_view_data->position_info = (ObjectPtr)ptr;
8661 /* Sort according to left-to-right, top-to-bottom */
8662 for (k = 0; k < j; k++)
8664 if ((ptr->y < file_mgr_data->object_positions[k]->y) ||
8665 ((ptr->y == file_mgr_data->object_positions[k]->y) &&
8666 (ptr->x < file_mgr_data->object_positions[k]->x)))
8668 /* Shift others down, to open up a spot */
8669 for (l = j; l > k; l--)
8671 file_mgr_data->object_positions[l] =
8672 file_mgr_data->object_positions[l - 1];
8677 file_mgr_data->object_positions[k] = ptr;
8681 file_mgr_data->num_objects = j;
8683 /* Repair all of the next and prev pointers */
8684 RepairStackingPointers(file_mgr_data);
8685 OrderChildrenList(file_mgr_data);
8689 /***********************************
8691 * When items are dragged around on a random placement window, they will be
8692 * repositioned at the point where they were dropped. Multiple drop items
8693 * will be positioned 'around' where the drop occurred.
8695 **********************************/
8699 FileMgrData * file_mgr_data,
8704 Boolean late_binding_needed)
8713 ObjectPosition * save_object;
8715 FileMgrRec * file_mgr_rec;
8716 XmManagerWidget file_window;
8721 int newEntryCount = 0;
8722 char dot_dir[3] = ".";
8723 char dotdot_dir[3] = "..";
8725 /* if random placement is not enabled, positioning doesn't matter */
8726 if(file_mgr_data->positionEnabled == RANDOM_OFF)
8729 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
8732 * For directory views, no positional data may be present if positioning
8733 * was disabled for this view. So ... we must create some now.
8735 if ((file_mgr_data->num_objects == 0) &&
8736 (file_mgr_data->directory_set[0]->file_count > 0))
8738 BuildObjectPositions(file_mgr_data);
8742 * Update to the new position.
8743 * The position needs to be adjusted so that the icon actually ends
8744 * up where the user dropped it. This is because the drag icon includes
8745 * margins and shadow area, but not the highlight area of the icon gadget
8746 * that was dragged. Coordinates drop_x, drop_y are the upper left corner
8747 * of the drag icon when it was dropped. To convert to icon gadget
8748 * coordinates we need to subtract the highlight thickness.
8750 if (file_mgr_data->layout_data != NULL)
8751 adj = ((IconLayoutData *)file_mgr_data->layout_data)->highlight;
8756 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8758 /* Process each of the dropped files */
8759 /* Go from bottom to top, to retain stacking order */
8760 for (i = file_count - 1; i >= 0; i--)
8765 * The names typically come in as complete paths; we only want
8766 * the filename portion.
8767 * fdt: this check will break for root (/)
8769 if( strcmp(file_mgr_data->current_directory, file_list[i]) == 0)
8771 else if(strncmp(file_mgr_data->current_directory, file_list[i], strlen(file_list[i]) ) == 0 )
8775 if ((name = strrchr(file_list[i], '/')) == NULL)
8776 name = file_list[i];
8781 /* Try to gracefully handle root (/) */
8789 /* Find the positional data for this object, if any */
8790 for (j = 0; j < file_mgr_data->num_objects; j++)
8792 if (strcmp(name, file_mgr_data->object_positions[j]->name) == 0)
8794 /* Find the associated widget */
8795 for (k = 0; strcmp(name,
8796 file_mgr_data->directory_set[0]->file_view_data[k]->file_data-> file_name); k++);
8800 /* If this object has a text field, then move it also */
8801 for (l = 0; l < file_window->composite.num_children; l++)
8803 if (XmIsTextField(file_window->composite.children[l]) &&
8804 !file_window->composite.children[l]->core.being_destroyed)
8806 XtSetArg(args[0], XmNuserData, &edit_name);
8807 XtGetValues(file_window->composite.children[l], args, 1);
8808 if (strcmp(edit_name, name) == 0)
8810 textWidget = file_window->composite.children[l];
8821 ObjectPosition * data;
8823 /* Create positional data at the top of the ordered array */
8826 data = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8827 data->name = XtNewString(name);
8830 data->in_use = True;
8831 data->late_bind = True;
8832 data->stacking_order = 1;
8833 data->file_view_data = NULL;
8837 /* Push all other objects down in the stack */
8838 for (i2 = 0; i2 < file_mgr_data->num_objects; i2++)
8840 /* Find the previous top of the stack */
8841 if (file_mgr_data->object_positions[i2]->stacking_order == 1)
8843 data->next = (ObjectPtr)file_mgr_data->object_positions[i2];
8844 file_mgr_data->object_positions[i2]->prev = (ObjectPtr)data;
8846 file_mgr_data->object_positions[i2]->stacking_order++;
8849 file_mgr_data->num_objects++;
8850 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8851 (char *)file_mgr_data->object_positions,
8852 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8854 /* Add entry to the top of the ordered array */
8855 for (j = file_mgr_data->num_objects - 1; j > 0; j--)
8857 file_mgr_data->object_positions[j] =
8858 file_mgr_data->object_positions[j - 1];
8861 file_mgr_data->object_positions[0] = data;
8865 /* Move item upto top of the stack */
8866 RepositionUpInStack(file_mgr_data,
8867 file_mgr_data->object_positions[j]->stacking_order, 1);
8870 orig_x = file_mgr_data->object_positions[j]->x;
8871 orig_y = file_mgr_data->object_positions[j]->y;
8872 file_mgr_data->object_positions[j]->x = x;
8873 file_mgr_data->object_positions[j]->y = y;
8874 save_object = file_mgr_data->object_positions[j];
8876 /* Move the object */
8879 /* We need to force a geometry request */
8880 XtSetArg(args[0], XmNx, x);
8881 XtSetArg(args[1], XmNy, y);
8882 XtSetValues(file_mgr_data->directory_set[0]->file_view_data[k]->widget,
8885 /* Move associated text widget, if there is one */
8890 t_x = textWidget->core.x + x - orig_x;
8891 t_y = textWidget->core.y + y - orig_y;
8893 /* We need to force a geometry request */
8894 XtSetArg(args[0], XmNx, t_x);
8895 XtSetArg(args[1], XmNy, t_y);
8896 XtSetValues(textWidget, args, 2);
8901 * Reorder the positional array, so that it remains ordered.
8902 * Bubble down toward the end of the list if the object has moved
8903 * farther from the origin; bubble up if it has moved closer to
8906 if ((y > orig_y) || ((y == orig_y) && (x > orig_x)))
8909 for (k = j + 1; k < file_mgr_data->num_objects; k++)
8911 if ((y < file_mgr_data->object_positions[k]->y) ||
8912 ((y == file_mgr_data->object_positions[k]->y) &&
8913 (x < file_mgr_data->object_positions[k]->x)))
8915 /* We fit right here */
8916 file_mgr_data->object_positions[k - 1] = save_object;
8922 file_mgr_data->object_positions[k - 1] =
8923 file_mgr_data->object_positions[k];
8927 /* See if it goes at the end */
8928 if (k == file_mgr_data->num_objects)
8929 file_mgr_data->object_positions[k - 1] = save_object;
8934 for (k = j - 1; k >= 0; k--)
8936 if ((y > file_mgr_data->object_positions[k]->y) ||
8937 ((y == file_mgr_data->object_positions[k]->y) &&
8938 (x > file_mgr_data->object_positions[k]->x)))
8940 /* We fit right here */
8941 file_mgr_data->object_positions[k + 1] = save_object;
8947 file_mgr_data->object_positions[k + 1] =
8948 file_mgr_data->object_positions[k];
8952 /* See if it goes at the end */
8954 file_mgr_data->object_positions[0] = save_object;
8957 /* Create position for the next file to be processed */
8962 * Reregister the desktop hotspots.
8963 * Even if the caller told us that late binding was needed, if no new
8964 * objects were specified, then we need to register hotspots now, because
8965 * the layout function will never be called because the directory never
8966 * really changed. This situation can occur when an icon is dropped on
8967 * the desktop from a regular dtfile view, but that icon is already on
8968 * the desktop (it thus is just a reposition).
8970 if (!late_binding_needed ||
8971 (late_binding_needed && (newEntryCount == 0)))
8973 RegisterDesktopHotspots(file_mgr_data, file_mgr_rec);
8978 RegisterDesktopHotspots (
8979 FileMgrData * file_mgr_data,
8980 FileMgrRec * file_mgr_rec)
8982 XmManagerWidget file_window;
8983 FileViewData * file_view_data;
8984 int ex, ey, ewd, eht;
8989 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8990 ex = -file_window->core.x;
8991 ey = -file_window->core.y;
8992 ewd = XtParent(file_window)->core.width;
8993 eht = XtParent(file_window)->core.height;
8995 /* Set up the icon location information with the drag handler */
8996 /* Register in top to bottom stacking order */
8997 top = GetTopOfStack(file_mgr_data);
9001 file_view_data = top->file_view_data;
9003 if (file_view_data != NULL &&
9004 file_view_data->displayed &&
9005 !file_view_data->need_update)
9007 icon = file_view_data->widget;
9008 if ((Position)(icon->core.x + icon->core.width) >= (Position)ex &&
9009 icon->core.x < ex + ewd &&
9010 (Position)(icon->core.y + icon->core.height) >= (Position)ey &&
9011 icon->core.y < ey + eht)
9013 SetHotRects(file_view_data,
9014 (XtCallbackProc) DropOnObject,
9015 (XtPointer) file_view_data);
9025 * Dtfile used to try to determine if the vertical scrollbar was visible
9026 * by checking to see if it was managed; the assumption here was that the
9027 * scrolled window widget unmanaged the scrollbar, when it was not needed.
9028 * Unfortunately, it turns out that instead of unmanaging the scrollbar,
9029 * the scrolled window simply moves the scrollbar out of sight; it is moved
9030 * such that the X for the scrollbar is the same as the width of the
9031 * scrolled window. So ... in order for us to really determine if the
9032 * scrollbar is visible, we need to see whether or not its X falls within
9033 * the visible area of the scrolled window.
9037 VerticalScrollbarIsVisible(
9042 if (vertSB && XtIsManaged(vertSB) &&
9043 (vertSB->core.x < (Position)scrolledWin->core.width))
9052 HorizontalScrollbarIsVisible(
9057 if (hortSB && XtIsManaged(hortSB) &&
9058 (hortSB->core.y <= (Position)scrolledWin->core.height))