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 librararies 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,
285 register XEvent *event,
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;
906 register int i, j, k;
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 occuring 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 occured 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;
2335 register Widget widget;
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;
2784 register int i, j, k;
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;
3147 #endif /* MULTIBYTE */
3154 while ((len = mblen(tmp, MB_CUR_MAX)) > 0)
3155 #else /* MULTIBYTE */
3156 for( tmp = name + 1, i = 0;
3159 #endif /* MULTIBYTE */
3165 #endif /* MULTIBYTE */
3169 string = XmStringCreateLocalized( name );
3170 stringWidth = XmStringWidth( fontList, string );
3171 XmStringFree( string );
3173 if( stringWidth > width )
3178 #endif /* MULTIBYTE */
3185 CreateNameChangeDialog (
3187 FileViewData *file_view_data,
3188 XtPointer client_data,
3191 XRectangle textExtent;
3192 FileMgrData * file_mgr_data;
3193 DesktopRec * desktopWindow;
3194 Widget parent = XtParent(w);
3199 Widget frame, shell;
3200 Dimension fHeight, sHeight;
3202 Dimension tWidth, tHeight;
3205 XtTranslations trans_table;
3206 XmFontList fontList;
3207 Dimension stringWidth;
3208 XmString fileNameString;
3209 char tmpBuf[MAX_PATH];
3211 _DtIconGetTextExtent_r(w, &textExtent);
3215 char buf[MAXPATHLEN];
3217 desktopWindow = (DesktopRec *)client_data;
3218 if(desktopWindow->text != NULL)
3221 sprintf( buf, "%s:%s", home_host_name, root_title );
3224 * If the object is on the DESKTOP and its name is root_title, then
3225 * the user can't rename it.
3227 if( strcmp( buf, desktopWindow->title ) == 0
3228 && strcmp( desktopWindow->dir_linked_to, "/" ) == 0
3229 && strcmp( desktopWindow->file_name, "." ) == 0 )
3233 file_mgr_data = (FileMgrData *)client_data;
3235 /* if the object is in the trash, can't rename it */
3237 && file_mgr_data == trashFileMgrData )
3240 /* if the object is an action, can't rename it */
3241 if( DtDtsDataTypeIsAction( file_view_data->file_data->logical_type ) )
3243 char *tmpStr, *title, *msg;
3245 tmpStr = GETMESSAGE(10, 39, "Rename error");
3246 title = XtNewString(tmpStr);
3247 tmpStr = GETMESSAGE(10, 40, "This object is an Action.\nAction icon labels cannot be directly renamed." );
3248 msg = XtNewString(tmpStr);
3250 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
3255 else if(file_view_data->file_data->action_name)
3257 char *tmpStr, *title, *msg;
3259 tmpStr = GETMESSAGE(10, 39, "Rename error");
3260 title = XtNewString(tmpStr);
3261 tmpStr = GETMESSAGE(11, 32, "Cannot rename %s");
3262 msg = XtMalloc(strlen(tmpStr)+strlen(file_view_data->file_data->
3264 sprintf(msg,tmpStr,file_view_data->file_data->action_name);
3266 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
3273 * The selected objects name is attached as 'userData' to text field,
3274 * to aid us in mapping back to the original object later.
3276 if( type == DESKTOP &&
3277 ( (strcmp(".", file_view_data->file_data->file_name) == 0)
3278 || strcmp("..", file_view_data->file_data->file_name) == 0) )
3280 name = XtNewString(desktopWindow->file_name);
3282 else if ( strcmp(".", file_view_data->file_data->file_name) == 0 ||
3283 strcmp("..", file_view_data->file_data->file_name) == 0 )
3288 name = XtNewString(file_view_data->file_data->file_name);
3290 /* set up translations in main edit widget */
3291 trans_table = XtParseTranslationTable(translations_escape);
3293 /* We need to set the width of the text widget.
3294 Can't use XmNcolumns because of the double-byte.
3297 XtSetArg( args[0], XmNfontList, &fontList );
3298 XtGetValues( file_view_data->widget, args, 1 );
3300 sprintf( tmpBuf, "%s ", file_view_data->file_data->file_name );
3301 fileNameString = XmStringCreateLocalized( tmpBuf );
3302 stringWidth = XmStringWidth( fontList, fileNameString );
3303 XmStringFree( fileNameString );
3306 XtSetArg(args[n], XmNuserData, name); n++;
3307 XtSetArg(args[n], XmNmarginHeight, 0); n++;
3308 XtSetArg(args[n], XmNmarginWidth, 0); n++;
3309 XtSetArg(args[n], XmNvalue, name); n++;
3310 XtSetArg(args[n], XmNwidth, stringWidth); n++;
3315 text = XmCreateTextField(parent, "nameChangeT_DT", args, n);
3316 XtAddCallback (text, XmNactivateCallback, ChangeIconNameDT,
3317 (XtPointer)desktopWindow);
3318 XtAddCallback(text, XmNhelpCallback, (XtCallbackProc)DTHelpRequestCB,
3319 HELP_NAMECHANGE_DIALOG_STR);
3320 desktopWindow->text = text;
3322 frame = XtParent(parent);
3323 shell = XtParent(frame);
3324 XtSetArg(args[0], XmNheight, &fHeight);
3325 XtGetValues(frame, args, 1);
3326 XtSetArg(args[0], XmNheight, &sHeight);
3327 XtGetValues(shell, args, 1);
3331 text = XmCreateTextField(parent, "nameChangeT", args, n);
3332 file_mgr_data->renaming = file_view_data;
3333 XtAddCallback (text, XmNmotionVerifyCallback,
3334 (XtCallbackProc)ChangeIconName,
3335 (XtPointer)file_mgr_data);
3336 XtAddCallback (text, XmNmodifyVerifyCallback,
3337 (XtCallbackProc)ChangeIconName,
3338 (XtPointer)file_mgr_data);
3339 XtAddCallback (text, XmNactivateCallback,
3340 (XtCallbackProc)ChangeIconName,
3341 (XtPointer)file_mgr_data);
3342 XtAddCallback(text, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
3343 HELP_NAMECHANGE_DIALOG_STR);
3346 XtAddCallback (text, XmNdestroyCallback, DestroyIconName, (XtPointer)NULL);
3348 /* set up translations in main edit widget */
3349 XtOverrideTranslations(text, trans_table);
3351 if(type == DESKTOP && sHeight > fHeight) {
3352 /* status area has been attached in multi-byte case */
3358 y = textExtent.y - (Dimension)(text->core.height - textExtent.height);
3362 Window rootWindow, childWindow;
3363 int pX, pY, rootX, rootY, insertPosition;
3366 XQueryPointer( XtDisplay( parent ), XtWindow( file_view_data->widget ),
3367 &rootWindow, &childWindow, &rootX, &rootY, &pX, &pY,
3370 insertPosition = strlen( name );
3373 if( type != DESKTOP )
3375 if( pX > (int) x && pX < (int) x + (int) stringWidth )
3376 insertPosition = GetInsertPosition( x, pX, fontList, name );
3378 insertPosition = strlen( name );
3381 insertPosition = GetInsertPosition( x, x + pX, fontList, name );
3384 XtSetArg( args[n], XmNcursorPosition, insertPosition); n++;
3385 XtSetArg( args[n], XmNx, x); n++;
3386 XtSetArg( args[n], XmNy, y); n++;
3387 XtSetValues (text, args, n);
3394 Dimension shadowThickness;
3396 unsigned char flags;
3398 XtSetArg (args[0], XmNwidth, &tWidth);
3399 XtSetArg (args[1], XmNheight, &tHeight);
3400 XtGetValues (text, args, 2);
3402 XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
3403 XtGetValues (desktopWindow->iconGadget, args, 1);
3405 _DtIconGetIconRects((DtIconGadget)desktopWindow->iconGadget,
3406 &flags, &rect[0], &rect[1]);
3410 rect[0].width += 2*shadowThickness;
3411 rect[0].height += 2*shadowThickness;
3414 if(type == DESKTOP && sHeight > fHeight) {
3415 /* status area has been attached in multi-byte case */
3418 rect[1].width = 2*shadowThickness + tWidth;
3419 rect[1].height = sHeight - y - 1;
3424 rect[1].width = shadowThickness + tWidth;
3425 rect[1].height = tHeight;
3428 if(rect[0].width > rect[1].width)
3429 rect[1].width = rect[0].width;
3431 XShapeCombineRectangles(XtDisplay(desktopWindow->shell),
3432 XtWindow(desktopWindow->shell),
3433 ShapeBounding, 0, 0, &rect[0], 2,
3434 ShapeSet, Unsorted);
3437 XtManageChild(text);
3438 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
3442 FileMgrRec *file_mgr_rec;
3444 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3445 file_mgr_rec->menuStates &= ~RENAME;
3449 /************************************************************************
3451 * SavePositionalData
3452 * Save the desktop icon positional data.
3454 ************************************************************************/
3457 SavePositionalData (
3459 FileMgrData * file_mgr_data,
3464 FILE * fd_stream = fdopen(fd, "w");
3465 ObjectPosition * ptr;
3468 if(file_mgr_data->positionEnabled == RANDOM_ON &&
3469 file_mgr_data->object_positions &&
3470 file_mgr_data->show_type == SINGLE_DIRECTORY &&
3471 file_mgr_data->host != NULL)
3473 /* Number of object positions */
3474 fprintf(fd_stream, "*%s.%s.%s.%s: %d\n#\n", name_list[0], name_list[1],
3475 name, "num_positions", file_mgr_data->num_objects);
3477 for (i = 0; i < file_mgr_data->num_objects; i++)
3479 ptr = file_mgr_data->object_positions[i];
3480 fprintf(fd_stream, "*%s.%s.%s.%s%d: %s %d %d %d\n",
3481 name_list[0], name_list[1], name, "object", i,
3485 ptr->stacking_order);
3490 /* Number of object positions */
3491 fprintf(fd_stream, "*%s.%s.%s.%s: %d\n#\n", name_list[0], name_list[1],
3492 name, "num_positions", 0);
3500 /************************************************************************
3502 * RestorePositionalData
3503 * Restore the desktop icon positional data.
3505 ************************************************************************/
3508 RestorePositionalData (
3511 FileMgrData * file_mgr_data,
3514 XrmName xrm_name[10];
3517 char objectName[20];
3518 XrmRepresentation rep_type;
3523 ObjectPosition * ptr;
3527 while (name_list[i])
3529 xrm_name[i] = XrmStringToQuark(name_list[i]);
3532 xrm_name[i++] = XrmStringToQuark(name);
3533 xrm_name[i] = XrmStringToQuark("num_positions");
3534 xrm_name[i+1] = '\0';
3536 /* Find out how many objects there are to be loaded */
3537 file_mgr_data->object_positions = NULL;
3539 if (XrmQGetResource (db, xrm_name, NULL, &rep_type, &value))
3541 if ((num_objects = atoi (value.addr)) <= 0)
3545 file_mgr_data->object_positions = (ObjectPosition **)XtMalloc(
3546 sizeof(ObjectPosition *) * num_objects);
3550 file_mgr_data->num_objects = num_objects;
3552 for (j = 0; j < num_objects; j++)
3554 sprintf(objectName, "object%d", j);
3555 xrm_name[i] = XrmStringToQuark(objectName);
3556 ptr = file_mgr_data->object_positions[j] = (ObjectPosition *)
3557 XtMalloc(sizeof(ObjectPosition));
3559 XrmQGetResource (db, xrm_name, NULL, &rep_type, &value);
3560 str = (char *)value.addr;
3561 obj_name = XtMalloc(strlen(str) + 1);
3562 sscanf((char *)value.addr, "%s %d %d %d", obj_name, &x, &y, &s_order);
3563 ptr->name = obj_name;
3566 ptr->stacking_order = s_order;
3567 ptr->in_use = False;
3568 ptr->late_bind = False;
3569 ptr->file_view_data = NULL;
3574 /* Repair all of the next and prev pointers */
3575 RepairStackingPointers(file_mgr_data);
3581 FileMgrData * file_mgr_data)
3584 XmManagerWidget file_window;
3586 FileMgrRec * file_mgr_rec;
3588 file_mgr_data->renaming = NULL;
3590 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3591 file_window = (XmManagerWidget) file_mgr_rec->file_window;
3592 for (i = 0; i < file_window->composite.num_children; i++)
3594 if (XmIsTextField(file_window->composite.children[i]) &&
3595 !file_window->composite.children[i]->core.being_destroyed)
3597 XtUnmanageChild(file_window->composite.children[i]);
3598 XtDestroyWidget(file_window->composite.children[i]);
3607 FileMgrData * file_mgr_data)
3610 FileMgrRec * file_mgr_rec;
3613 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3615 XtSetArg (args[0], XmNallowShellResize, False);
3616 XtSetValues(file_mgr_rec->shell, args, 1);
3618 XtUnmanageChild(file_mgr_rec->current_directory_text);
3620 XtSetArg (args[0], XmNallowShellResize, True);
3621 XtSetValues(file_mgr_rec->shell, args, 1);
3623 file_mgr_data->fast_cd_enabled = False;
3628 * Function to force a redraw of a single gadget.
3638 if (child->core.widget_class->core_class.expose)
3639 (*(child->core.widget_class->core_class.expose))(child, event, region);
3644 * Given a region describing the area to be repainted, repaint all icons,
3645 * in bottom to top order, which fall into this region.
3650 FileMgrData * file_mgr_data,
3656 ObjectPosition * bottom = GetBottomOfStack(file_mgr_data);
3658 /* Redraw all affected gadgets */
3661 if (!bottom->late_bind)
3663 if (bottom->file_view_data != NULL &&
3664 !bottom->file_view_data->need_update)
3666 child = bottom->file_view_data->widget;
3667 if (XRectInRegion(region, child->core.x, child->core.y,
3668 child->core.width, child->core.height))
3670 RedrawOneGadget(child, event, region);
3675 bottom = bottom->prev;
3681 * This function will extract all exposure events intended for this file
3682 * window, combine them into a single region, and then determine which of
3683 * the file icons need to be redrawn. It is a two step process, as
3684 * described by the comments in the code.
3688 RedisplayUsingStackingOrder (
3689 FileMgrData * file_mgr_data,
3691 register XEvent *event,
3695 register Widget child;
3696 FileViewData * file_view_data;
3697 ObjectPosition * bottom;
3698 ObjectPosition * top;
3699 Region redrawRegion = XCreateRegion();
3702 int numChildren = 0;
3703 Widget * children = NULL;
3704 Region widget_region;
3707 /* Get the initial region to redraw */
3709 XUnionRegion(redrawRegion, region, redrawRegion);
3712 rect.x = event->xexpose.x;
3713 rect.y = event->xexpose.y;
3714 rect.height = event->xexpose.height;
3715 rect.width = event->xexpose.width;
3717 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
3721 * Capture and encompass any other exposure events which are destined for
3722 * us, but are waiting in the wings.
3724 while (XCheckWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask, &expEvent))
3726 rect.x = expEvent.xexpose.x;
3727 rect.y = expEvent.xexpose.y;
3728 rect.height = expEvent.xexpose.height;
3729 rect.width = expEvent.xexpose.width;
3731 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
3734 /* Nothing to do if the redraw region is empty */
3735 if (XEmptyRegion(redrawRegion))
3737 XDestroyRegion(redrawRegion);
3742 * Starting at the top of the stack, find any items which fall into
3743 * the redraw region. As items are found which need to be redrawn,
3744 * subtract them from the redraw region, so that any items lower on the
3745 * stack which might be under these gadgets, but are within the region,
3748 * The second phase is to start at the bottom of the stack, and start
3749 * redrawing the gadgets which fell into the region, along with any
3750 * other gadgets on top of these (since they too now need to be redrawn.
3752 top = GetTopOfStack(file_mgr_data);
3758 if (!top->late_bind)
3760 file_view_data = top->file_view_data;
3761 if(file_view_data != NULL)
3763 child = file_view_data->widget;
3765 if (child && XmIsGadget(child) && XtIsManaged(child))
3767 widget_region = XCreateRegion();
3768 WidgetRectToRegion(file_mgr_data, child, widget_region);
3769 XIntersectRegion(redrawRegion, widget_region, widget_region);
3770 if (!XEmptyRegion(widget_region))
3772 XSubtractRegion(redrawRegion, widget_region, redrawRegion);
3773 children = (Widget *)XtRealloc((char *)children,
3774 (numChildren + 1) * sizeof(Widget));
3775 children[numChildren] = child;
3778 XDestroyRegion(widget_region);
3782 top = (ObjectPosition *)top->next;
3785 /* Now, start redrawing, in bottom to top order */
3786 bottom = GetBottomOfStack(file_mgr_data);
3790 if (!bottom->late_bind)
3792 file_view_data = bottom->file_view_data;
3793 if(file_view_data != NULL)
3795 child = file_view_data->widget;
3797 if (child && XmIsGadget(child) && XtIsManaged(child))
3799 widget_region = XCreateRegion();
3800 WidgetRectToRegion(file_mgr_data, child, widget_region);
3801 if ((numChildren >= 0) && (children[numChildren] == child))
3803 XUnionRegion(redrawRegion, widget_region, redrawRegion);
3804 RedrawOneGadget(child, event, redrawRegion);
3809 /* Do we overlap something which was previously redrawn? */
3810 tmp_region = XCreateRegion();
3811 XIntersectRegion(redrawRegion, widget_region, tmp_region);
3812 if (!XEmptyRegion(tmp_region))
3814 XUnionRegion(redrawRegion, widget_region, redrawRegion);
3815 RedrawOneGadget(child, event, redrawRegion);
3817 XDestroyRegion(tmp_region);
3819 XDestroyRegion(widget_region);
3823 bottom = (ObjectPosition *)bottom->prev;
3826 XDestroyRegion(redrawRegion);
3827 XtFree((char *)children);
3833 * This is the function which we use to override the class expose function
3834 * for the drawing area widget. It allows us to catch exposure events
3835 * intended for the desktop, so that we can force the redrawing of the
3836 * gadgets to occur occording to the stacking order.
3840 DrawingAreaRedisplay (
3846 XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid;
3847 XmDrawingAreaCallbackStruct cb;
3848 FileMgrData * file_mgr_data;
3850 cb.reason = XmCR_EXPOSE;
3852 cb.window = XtWindow (da);
3854 DPRINTF2(("DrawingAreaRedisplay: event %d, x/y %d/%d, wd/ht %d/%d\n",
3856 event->xexpose.x, event->xexpose.y,
3857 event->xexpose.width, event->xexpose.height));
3859 file_mgr_data = ReturnDesktopPtr(wid);
3861 if (file_mgr_data && PositioningEnabledInView(file_mgr_data))
3862 RedisplayUsingStackingOrder(file_mgr_data, (Widget)da, event, region);
3864 XmeRedisplayGadgets((Widget)da, event, region);
3866 XtCallCallbackList ((Widget)da, da->drawing_area.expose_callback, &cb);
3871 * Return the bottom of the stacking order list.
3876 FileMgrData * file_mgr_data)
3882 for (i = 0, bottom = NULL; i < file_mgr_data->num_objects; i++)
3884 if (file_mgr_data->object_positions[i]->next == NULL)
3886 bottom = file_mgr_data->object_positions[i];
3896 * Return the top of the stacking order list.
3901 FileMgrData * file_mgr_data)
3906 for (i = 0, top = NULL; i < file_mgr_data->num_objects; i++)
3908 if (file_mgr_data->object_positions[i]->prev == NULL)
3910 top = file_mgr_data->object_positions[i];
3920 * Move an object up in the stacking order. Will not work for moving an
3921 * object further down in the stacking order, but we currently have no
3922 * need for doing that.
3924 * NOTE: The top of the stack is '1', not '0'!!
3928 RepositionUpInStack (
3929 FileMgrData * file_mgr_data,
3934 ObjectPtr ptr, ptr2, savePtr;
3936 XmManagerWidget file_window;
3938 if (oldPos == newPos)
3941 ptr = GetTopOfStack(file_mgr_data);
3943 /* Find where item is to be inserted */
3944 while (ptr->stacking_order != newPos)
3947 /* Find where item currently is */
3949 while (ptr2->stacking_order != oldPos)
3954 if(savePtr->file_view_data == NULL)
3957 /* Remove from its current location */
3959 ptr2->prev->next = ptr2->next;
3961 ptr2->next->prev = ptr2->prev;
3963 /* Link into new position */
3964 ptr2->prev = ptr->prev;
3967 ptr2->prev->next = ptr2;
3970 /* Update the stacking order value */
3971 for (i = newPos; i <= oldPos; i++)
3973 ptr2->stacking_order = i;
3977 /* Update the children's list for the file window */
3978 file_window = (XmManagerWidget)
3979 (((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
3981 /* Find the affect child */
3982 for (i = 0; (i < file_window->composite.num_children) &&
3983 (file_window->composite.children[i] != savePtr->file_view_data->widget);
3986 /* Push intervening entries down */
3987 for (j = i; j >= newPos; j--)
3988 file_window->composite.children[j] = file_window->composite.children[j-1];
3990 /* Insert into new position in children list */
3991 file_window->composite.children[newPos-1] = savePtr->file_view_data->widget;
3996 * Reorder the file window's children list so that it matches the stacking
4001 ReorderChildrenList (
4002 XmManagerWidget file_window,
4009 Widget * children = file_window->composite.children;
4012 for (i = 0; i < manageCount; i++)
4013 children[i] = manage[i];
4015 for (j = 0; j < unmanageCount; j++)
4016 children[i++] = unmanage[j];
4021 * If positional information is available for the indicated file, then
4022 * return it; if not, then return NULL.
4026 FindCurrentPosition (
4027 FileMgrData * file_mgr_data,
4033 for (i = 0; i < file_mgr_data->num_objects; i++)
4035 if (strcmp(file_name, file_mgr_data->object_positions[i]->name) == 0)
4038 file_mgr_data->object_positions[i]->in_use = True;
4039 return(file_mgr_data->object_positions[i]);
4048 RepairStackingPointers (
4049 FileMgrData * file_mgr_data)
4054 ObjectPosition * ptr;
4055 ObjectPosition * prev;
4057 for (i = 1, prev = NULL; i <= file_mgr_data->num_objects; i++)
4059 for (j = 0; j < file_mgr_data->num_objects; j++)
4061 ptr = file_mgr_data->object_positions[j];
4062 if (ptr->stacking_order == i)
4077 * Reorder the children's list for the file_window, so that it matches
4078 * the stacking order. Also, set up all next and previous pointers.
4083 FileMgrData * file_mgr_data)
4086 FileMgrRec * file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
4087 XmManagerWidget file_window;
4092 ObjectPosition * top;
4095 file_window = (XmManagerWidget) file_mgr_rec->file_window;
4096 managed = (Widget *)XtMalloc(sizeof(Widget *) *
4097 file_window->composite.num_children);
4098 unmanaged = (Widget *)XtMalloc(sizeof(Widget *) *
4099 file_window->composite.num_children);
4100 num_managed = num_unmanaged = 0;
4102 top = GetTopOfStack(file_mgr_data);
4105 if (top->file_view_data != NULL && top->file_view_data->widget != NULL)
4106 managed[num_managed++] = top->file_view_data->widget;
4110 /* All the rest get put at the end of the children's list */
4111 for (i = 0; i < file_window->composite.num_children; i++)
4113 for (j = 0; j < num_managed; j++)
4115 if (managed[j] == file_window->composite.children[i])
4119 if (j >= num_managed)
4120 unmanaged[num_unmanaged++] = file_window->composite.children[i];
4123 ReorderChildrenList(file_window, managed, num_managed, unmanaged,
4125 XtFree( (char *)managed );
4126 XtFree( (char *)unmanaged );
4136 FileViewData * file_view_data,
4137 XtCallbackProc callback,
4138 XtPointer callback_data)
4143 if (file_view_data->displayed)
4145 /*************************/
4146 /* icon gadget displayed */
4147 /*************************/
4148 DtIconGadget g = (DtIconGadget) file_view_data->widget;
4149 unsigned char operations;
4151 /* find defined operations (M/C/L) for file type */
4152 operations = TypeToDropOperations(
4153 file_view_data->file_data->logical_type);
4155 /* if icon gadget not yet registered as a drop site, do so now */
4156 if (!file_view_data->registered)
4158 /* register drop site for MCL but make drop site inactive */
4159 XtSetArg (args[0], XmNdropSiteOperations,
4160 XmDROP_COPY | XmDROP_MOVE | XmDROP_LINK);
4161 XtSetValues (file_view_data->widget, args, 1);
4163 file_view_data->registered = True;
4168 /***********************************/
4169 /* file has associated MCL actions */
4170 /***********************************/
4171 XRectangle rects[2];
4172 unsigned char flags;
4175 Dimension s_t, adj_xy, adj_size;
4177 /* ensure drop site operations and drop area are correct */
4178 _DtIconGetIconRects(g, &flags, &rects[0], &rects[1]);
4181 * Compute adjustments to the drop area:
4183 * - Add shadowThickness to the drop area:
4184 * The icon gadget leaves space of width shadowThickness around
4185 * the pixmap and label; use this space to make the drop zone
4188 * - Compensate for bug in drop zone registration/drawing:
4189 * For some reason the drop zone displayed on the screen is
4190 * actually smaller than the rectangle we register:
4191 * The drag&drop library seems to reduce the size of the drop
4192 * area by the value of highlightThickness at the top and left
4193 * border and by highlightThickness-1 at the bottom and right.
4194 * Is this a Motif drag&drop bug?
4195 * We compensate by registering a larger rectangle.
4197 s_t = G_ShadowThickness(g);
4198 adj_xy = s_t + G_HighlightThickness(g);
4199 adj_size = adj_xy + s_t + G_HighlightThickness(g) - 1;
4201 if (flags & XmPIXMAP_RECT)
4203 rects[0].x -= g->rectangle.x + adj_xy;
4204 rects[0].y -= g->rectangle.y + adj_xy;
4205 rects[0].width += adj_size;
4206 rects[0].height += adj_size;
4210 if (flags & XmLABEL_RECT)
4212 rects[1].x -= g->rectangle.x + adj_xy;
4213 rects[1].y -= g->rectangle.y + adj_xy;
4214 rects[1].width += adj_size;
4215 rects[1].height += adj_size;
4216 if (!numRects) rects[0] = rects[1];
4222 XtSetArg(args[n], XmNdropRectangles, rects); n++;
4223 XtSetArg(args[n], XmNnumDropRectangles, numRects); n++;
4225 XtSetArg (args[n], XmNdropSiteOperations, operations); n++;
4227 XmDropSiteUpdate (file_view_data->widget, args, n);
4228 g->icon.operations = operations;
4230 /* add client data */
4231 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4232 XtAddCallback(file_view_data->widget, XmNdropCallback,
4233 callback, callback_data);
4237 /*********************************************/
4238 /* file does not have associated MCL actions */
4239 /*********************************************/
4240 /* make drop site inactive */
4241 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
4242 XmDropSiteUpdate (file_view_data->widget, args, 1);
4243 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4248 /*****************************/
4249 /* icon gadget not displayed */
4250 /*****************************/
4251 if (file_view_data->registered)
4253 /***************************************/
4254 /* icon gadget registered as drop site */
4255 /***************************************/
4256 /* make drop site inactive */
4257 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
4258 XmDropSiteUpdate (file_view_data->widget, args, 1);
4259 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4267 * TypeToDropOperations
4271 TypeToDropOperations (
4275 unsigned char operations = 0L;
4278 /* does object have MOVE, COPY, and/or LINK actions */
4279 /* -- or no actions at all */
4280 if (action = DtDtsDataTypeToAttributeValue(file_type,
4281 DtDTS_DA_MOVE_TO_ACTION,
4284 operations = operations | XmDROP_MOVE;
4285 DtDtsFreeAttributeValue(action);
4287 if (action = DtDtsDataTypeToAttributeValue(file_type,
4288 DtDTS_DA_COPY_TO_ACTION,
4291 operations = operations | XmDROP_COPY;
4292 DtDtsFreeAttributeValue(action);
4294 if (action = DtDtsDataTypeToAttributeValue(file_type,
4295 DtDTS_DA_LINK_TO_ACTION,
4298 operations = operations | XmDROP_LINK;
4299 DtDtsFreeAttributeValue(action);
4312 unsigned char dropOperation,
4313 char * logical_type)
4317 /* retrieve action from database based on dropOperation */
4318 switch(dropOperation)
4321 action = DtDtsDataTypeToAttributeValue(logical_type,
4322 DtDTS_DA_MOVE_TO_ACTION,
4326 action = DtDtsDataTypeToAttributeValue(logical_type,
4327 DtDTS_DA_COPY_TO_ACTION,
4331 action = DtDtsDataTypeToAttributeValue(logical_type,
4332 DtDTS_DA_LINK_TO_ACTION,
4345 * Given a fileViewData pointer, determine if it is part of a FileMgrData,
4346 * or a DesktopRec; return the appropriate pointer.
4352 FileViewData * fileViewData,
4353 FileMgrData ** fileMgrData,
4354 DesktopRec ** desktopRec)
4359 *fileMgrData = NULL;
4361 for (i = 0; i < desktop_data->numIconsUsed; i++)
4363 if (desktop_data->desktopWindows[i]->file_view_data == fileViewData)
4365 *desktopRec = desktop_data->desktopWindows[i];
4370 *fileMgrData = (FileMgrData *)
4371 ((DirectorySet *)fileViewData->directory_set)->file_mgr_data;
4376 /******************************************************************
4378 * PositionFileView -
4379 * Given a particular file, position the file view that file
4380 * is in on that particular file.
4382 ********************************************************************/
4385 FileViewData *file_view_data,
4386 FileMgrData *file_mgr_data)
4390 int value, size, increment, page, max;
4391 FileMgrRec * file_mgr_rec = (FileMgrRec *)(file_mgr_data->file_mgr_rec);
4394 /* if the file is filtered we can't highlight it! */
4395 if(!file_view_data->displayed)
4398 /* Get the y location of the icon_gadget */
4399 y = file_view_data->y - file_mgr_data->grid_height;
4403 * 1) not sure exactly how slow this is, but there seems to be no other
4404 * way to do this. (CDExc23427)
4405 * 2) XmScrollVisible does not work if the work window is not managed...
4406 * so, we call it, and then get the appropriate x,y back from the
4407 * scroll bars and set them (CDExc23428) */
4408 p = XtVaCreateManagedWidget("positionicon", xmGadgetClass,
4409 file_mgr_rec->file_window,
4410 XmNmappedWhenManaged, False,
4411 XmNx, file_view_data->x,
4413 XmNwidth, file_mgr_data->grid_width,
4414 XmNheight, file_mgr_data->grid_height,
4417 XmScrollVisible(file_mgr_rec->scroll_window, p,
4418 XSPACING, YSPACING(file_mgr_data));
4422 XmScrollBarGetValues(file_mgr_rec->horizontal_scroll_bar,
4423 &value, &size, &increment, &page);
4424 x = -((Position) value);
4426 XmScrollBarGetValues(file_mgr_rec->vertical_scroll_bar,
4427 &value, &size, &increment, &page);
4428 y = -((Position) value);
4430 XtVaSetValues(file_mgr_rec->file_window, XmNx, x, XmNy, y, NULL);
4435 InMultipleObjectRegion (FileMgrData * file_mgr_data, FileViewData * fileViewData)
4438 for( i = 0; i < file_mgr_data->selected_file_count; ++i )
4439 if( strcmp( file_mgr_data->selection_list[i]->file_data->file_name, fileViewData->file_data->file_name ) == 0 )
4447 XtPointer client_data,
4449 FileMgrData *file_mgr_data)
4451 FileMgrRec *file_mgr_rec;
4453 FileViewData *fileViewData = NULL;
4454 int i, num_of_children, obj_btns;
4455 XmManagerWidget action_pane;
4456 XmString label_string;
4459 /* set number of popup children based on annotation */
4460 num_of_children = FM_POPUP_CHILDREN_NA;
4461 obj_btns = OBJ_BTNS_NA;
4463 /* attach the popup widget info to the menu */
4464 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
4465 XtSetArg(args[0], XmNuserData, file_mgr_rec);
4466 XtSetValues(fileMgrPopup.menu, args, 1);
4469 file_mgr_data->popup_menu_icon = NULL;
4471 /* we are dealing with a white space popup */
4473 && (client_data == NULL)
4475 && (file_mgr_data->selected_file_count == 0)
4479 DirectorySet *directory_set;
4481 /* retrieve the fileViewData for the current directory */
4482 directory_set = file_mgr_data->directory_set[0];
4483 for (i = 0; i < directory_set->file_count; i++)
4485 if(strcmp(directory_set->order_list[i]->file_data->file_name, ".")
4488 fileViewData = directory_set->order_list[i];
4493 /* manage the white space buttons and unmanage the object buttons */
4494 XtManageChildren(fileMgrPopup.wsPopup, WS_BTNS);
4495 XtUnmanageChildren(fileMgrPopup.objPopup, obj_btns);
4496 XtUnmanageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4498 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_UNSELECTALL]);
4500 if(file_mgr_data == trashFileMgrData)
4502 /* Set popup menu label */
4503 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 2, "Current Folder")));
4504 XtSetArg (args[0], XmNlabelString, label_string);
4505 XtSetValues (fileMgrPopup.title, args, 1);
4506 XtManageChild(fileMgrPopup.title);
4507 XmStringFree (label_string);
4509 /* trash white space popup -- unmanage the properties and show */
4510 /* hidden files buttons */
4511 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4512 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_FIND]);
4513 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN]);
4515 /* align the remaining buttons */
4516 XtSetArg(args[0], XmNmarginLeft, 0);
4517 if( PositioningEnabledInView( file_mgr_data ) )
4519 file_mgr_rec->menuStates |= CLEAN_UP;
4520 XtSetValues(fileMgrPopup.wsPopup[BTN_CLEANUP], args, 1);
4524 file_mgr_rec->menuStates &= ~(CLEAN_UP);
4525 XtUnmanageChild( fileMgrPopup.wsPopup[BTN_CLEANUP] );
4527 XtSetValues(fileMgrPopup.wsPopup[BTN_SELECTALL], args, 1);
4529 /* unmanage the action portion of the popup menu */
4530 XtUnmanageChild(fileMgrPopup.action_separator);
4532 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4533 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4534 XtUnmanageChild(action_pane->composite.children[i]);
4540 /* manage the properties and show hidden files buttons */
4541 if( file_mgr_data->toolbox )
4542 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4544 XtManageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4545 XtManageChild(fileMgrPopup.wsPopup[BTN_FIND]);
4546 XtManageChild(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN]);
4548 /* Set popup menu label */
4549 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 2, "Current Folder")));
4550 XtSetArg (args[0], XmNlabelString, label_string);
4551 XtSetValues (fileMgrPopup.title, args, 1);
4552 XtManageChild(fileMgrPopup.title);
4553 XmStringFree (label_string);
4555 /* align the menu buttons */
4556 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4557 XtSetArg(args[0], XmNmarginLeft, &margin);
4558 XtGetValues(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], args, 1);
4559 XtSetArg(args[0], XmNmarginLeft, margin);
4561 if( PositioningEnabledInView( file_mgr_data ) )
4563 file_mgr_rec->menuStates |= CLEAN_UP;
4564 XtSetValues(fileMgrPopup.wsPopup[BTN_CLEANUP], args, 1);
4568 file_mgr_rec->menuStates &= ~(CLEAN_UP);
4569 XtUnmanageChild( fileMgrPopup.wsPopup[BTN_CLEANUP] );
4572 XtSetValues(fileMgrPopup.wsPopup[BTN_SELECTALL], args, 1);
4576 if (file_mgr_data->show_hid_enabled)
4577 XmToggleButtonGadgetSetState(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], True, False);
4579 XmToggleButtonGadgetSetState(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], False, False);
4582 /* ensure that there was fileViewData for the current directory */
4583 if(fileViewData != NULL)
4585 /* attach the current fileViewData to the 'Properties' button */
4586 if( ! file_mgr_data->toolbox )
4588 XtRemoveAllCallbacks(fileMgrPopup.wsPopup[BTN_PROPERTIES],
4589 XmNactivateCallback);
4590 XtAddCallback (fileMgrPopup.wsPopup[BTN_PROPERTIES],
4591 XmNactivateCallback,
4592 ShowModAttrDialog, (XtPointer) fileViewData);
4594 /* sensitize the 'Properties' option */
4595 XtSetSensitive(fileMgrPopup.wsPopup[BTN_PROPERTIES], True);
4597 /* update the actions portion of the popup menu */
4598 XtManageChild(fileMgrPopup.action_separator);
4600 XtFree(fileMgrPopup.action_pane_file_type);
4601 fileMgrPopup.action_pane_file_type =
4602 XtNewString(fileViewData->file_data->logical_type);
4604 UpdateActionMenuPane ((XtPointer)fileViewData, file_mgr_rec,
4605 fileViewData->file_data->logical_type,
4606 FM_POPUP, num_of_children,
4608 fileViewData->file_data->physical_type);
4610 /* align actions portion of the popup menu */
4611 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4612 XtSetValues(action_pane->composite.children[i], args, 1);
4616 if( ! file_mgr_data->toolbox )
4618 /* remove callback from 'Properties' button */
4619 XtRemoveAllCallbacks(fileMgrPopup.wsPopup[BTN_PROPERTIES],
4620 XmNactivateCallback);
4622 /* desensitize the 'Properties' button */
4623 XtSetSensitive(fileMgrPopup.wsPopup[BTN_PROPERTIES], False);
4626 /* unmanage the action portion of the popup menu */
4627 XtUnmanageChild(fileMgrPopup.action_separator);
4629 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4630 XtUnmanageChild(action_pane->composite.children[i]);
4635 /* we are dealing with an object popup */
4638 char label[MAX_PATH];
4640 /* retrieve the fileViewData for the selected icon */
4642 fileViewData = (FileViewData *) client_data;
4643 else if (file_mgr_data->selected_file_count != 0)
4644 fileViewData = file_mgr_data->selection_list[0];
4647 /* unmanage the white space buttons */
4648 XtUnmanageChildren(fileMgrPopup.wsPopup, WS_BTNS);
4650 if(file_mgr_data == trashFileMgrData)
4652 file_mgr_data->popup_menu_icon = fileViewData;
4654 /* Set popup menu label */
4655 if( file_mgr_data->selected_file_count > 1
4656 && InMultipleObjectRegion(file_mgr_data, fileViewData))
4659 label_string = XmStringCreateLocalized ((GETMESSAGE(33,1, "Multiple Objects")));
4665 if (fileViewData->file_data->action_name)
4666 tmp_label = fileViewData->file_data->action_name;
4668 tmp_label = fileViewData->file_data->file_name;
4670 if( strlen( tmp_label ) > 20 )
4671 sprintf( label, "%-20.20s...", tmp_label );
4673 sprintf( label, "%s", tmp_label );
4675 label_string = XmStringCreateLocalized (label);
4677 XtSetArg (args[0], XmNlabelString, label_string);
4678 XtSetValues (fileMgrPopup.title, args, 1);
4679 XtManageChild(fileMgrPopup.title);
4680 XmStringFree (label_string);
4682 /* trash popup--unmanage the non-trash buttons, manage the trash */
4683 XtUnmanageChildren(fileMgrPopup.objPopup, obj_btns);
4684 XtManageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4686 /* adjust callbacks */
4687 XtRemoveAllCallbacks(fileMgrPopup.trash_objPopup[BTN_RESTORE],
4688 XmNactivateCallback);
4689 XtAddCallback(fileMgrPopup.trash_objPopup[BTN_RESTORE],
4690 XmNactivateCallback, Restore, (XtPointer) fileViewData);
4692 XtRemoveAllCallbacks(fileMgrPopup.trash_objPopup[BTN_REMOVE],
4693 XmNactivateCallback);
4694 XtAddCallback(fileMgrPopup.trash_objPopup[BTN_REMOVE],
4695 XmNactivateCallback, ConfirmRemove,
4696 (XtPointer) fileViewData);
4698 /* unmanage the action portion of the popup menu */
4699 XtUnmanageChild(fileMgrPopup.action_separator);
4701 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4702 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4703 XtUnmanageChild(action_pane->composite.children[i]);
4707 /* non-trash popup--manage the non-trash buttons, unmanage the trash */
4708 XtManageChildren(fileMgrPopup.objPopup, obj_btns);
4709 XtUnmanageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4710 if( file_mgr_data->toolbox )
4711 XtUnmanageChild(fileMgrPopup.objPopup[BTN_PROPERTIES]);
4713 if(file_mgr_data->selected_file_count > 1
4714 && InMultipleObjectRegion(file_mgr_data, fileViewData))
4716 /* we have many files selected; remove callbacks from the */
4717 /* 'Properties', 'Put on Desktop', and 'Review' buttons */
4718 /* and attach the selection list to the remaining buttons; */
4719 /* desensitize the 3 buttons listed above; unmanage the */
4720 /* actions part of the popup menu */
4722 /* adjust callbacks */
4723 if( ! file_mgr_data->toolbox )
4724 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PROPERTIES],
4725 XmNactivateCallback);
4727 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PUTON],
4728 XmNactivateCallback);
4729 XtAddCallback(fileMgrPopup.objPopup[BTN_PUTON], XmNactivateCallback,
4730 PutOnDTCB, (XtPointer) fileViewData);
4732 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_TRASH],
4733 XmNactivateCallback);
4734 XtAddCallback(fileMgrPopup.objPopup[BTN_TRASH], XmNactivateCallback,
4735 TrashFiles, (XtPointer) fileViewData);
4737 if( file_mgr_data->toolbox && geteuid() != root_user &&
4738 access(file_mgr_data->current_directory,W_OK|X_OK) != 0)
4739 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], False);
4742 /* sensitize buttons */
4743 if( !file_mgr_data->toolbox )
4744 XtSetSensitive(fileMgrPopup.objPopup[BTN_PROPERTIES], False);
4746 XtSetSensitive(fileMgrPopup.objPopup[BTN_HELP], False);
4748 /* Set popup menu label */
4749 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 1, "Multiple Objects")));
4750 XtSetArg (args[0], XmNlabelString, label_string);
4751 XtSetValues (fileMgrPopup.title, args, 1);
4752 XtManageChild(fileMgrPopup.title);
4753 XmStringFree (label_string);
4756 /* unmanage actions */
4757 XtUnmanageChild(fileMgrPopup.action_separator);
4758 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4759 for(i = num_of_children;
4760 i < action_pane->composite.num_children;
4762 XtUnmanageChild(action_pane->composite.children[i]);
4768 /* we have one file selected; attach fileViewData to buttons; */
4769 /* sensitize any desensitized buttons; update the actions */
4770 /* part of the popup menu */
4772 /* adjust callbacks */
4773 if( ! file_mgr_data->toolbox )
4775 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PROPERTIES],
4776 XmNactivateCallback);
4777 XtAddCallback(fileMgrPopup.objPopup[BTN_PROPERTIES],
4778 XmNactivateCallback, ShowModAttrDialog, (XtPointer) fileViewData);
4781 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PUTON],
4782 XmNactivateCallback);
4783 XtAddCallback(fileMgrPopup.objPopup[BTN_PUTON],
4784 XmNactivateCallback, PutOnDTCB, (XtPointer) fileViewData);
4786 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_TRASH],
4787 XmNactivateCallback);
4788 XtAddCallback(fileMgrPopup.objPopup[BTN_TRASH],
4789 XmNactivateCallback, TrashFiles, (XtPointer) fileViewData);
4791 if ( file_mgr_data->toolbox && geteuid() != root_user &&
4792 access(file_mgr_data->current_directory,W_OK|X_OK) != 0 )
4793 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], False);
4795 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], True);
4798 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_HELP],
4799 XmNactivateCallback);
4800 XtAddCallback(fileMgrPopup.objPopup[BTN_HELP],
4801 XmNactivateCallback, ObjectHelp, (XtPointer) fileViewData->widget);
4803 /* sensitize buttons */
4804 if( ! file_mgr_data->toolbox )
4805 XtSetSensitive(fileMgrPopup.objPopup[BTN_PROPERTIES], True);
4807 XtSetSensitive(fileMgrPopup.objPopup[BTN_PUTON], True);
4808 XtSetSensitive(fileMgrPopup.objPopup[BTN_HELP], True);
4810 if (fileViewData->file_data->action_name)
4811 tmp_label = fileViewData->file_data->action_name;
4813 tmp_label = fileViewData->file_data->file_name;
4815 if( strlen( tmp_label ) > 20 )
4816 sprintf( label, "%-20.20s...", tmp_label );
4818 sprintf( label, "%s", tmp_label );
4820 /* Set popup menu label */
4821 label_string = XmStringCreateLocalized (label);
4822 XtSetArg (args[0], XmNlabelString, label_string);
4823 XtSetValues (fileMgrPopup.title, args, 1);
4824 XtManageChild(fileMgrPopup.title);
4825 XmStringFree (label_string);
4828 /* update actions */
4829 XtManageChild(fileMgrPopup.action_separator);
4831 XtFree(fileMgrPopup.action_pane_file_type);
4832 fileMgrPopup.action_pane_file_type =
4833 XtNewString(fileViewData->file_data->logical_type);
4835 UpdateActionMenuPane ((XtPointer)fileViewData, file_mgr_rec,
4836 fileViewData->file_data->logical_type,
4837 FM_POPUP, num_of_children,
4839 fileViewData->file_data->physical_type);
4842 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4843 XtSetArg(args[0], XmNmarginLeft, 0);
4844 for(i = num_of_children; i < action_pane->composite.num_children; i++)
4845 XtSetValues(action_pane->composite.children[i], args, 1);
4851 /* position and manage popup menu */
4855 Dimension width, height;
4856 Dimension gWidth, gHeight;
4857 int displayWidth, displayHeight;
4858 DtIconGadget g = (DtIconGadget)w;
4860 XtSetArg (args[0], XmNwidth, &width);
4861 XtSetArg (args[1], XmNheight, &height);
4862 XtGetValues(XtParent(fileMgrPopup.menu), args, 2);
4864 gWidth = g->icon.pixmap_width;
4865 gHeight = g->icon.pixmap_height;
4867 displayWidth = DisplayWidth(XtDisplay(w), DefaultScreen(XtDisplay(w)));
4868 displayHeight =DisplayHeight(XtDisplay(w), DefaultScreen(XtDisplay(w)));
4870 x = file_mgr_rec->shell->core.x +
4871 file_mgr_rec->scroll_window->core.x +
4872 w->core.x + gWidth/2;;
4874 y = file_mgr_rec->shell->core.y +
4875 file_mgr_rec->header_frame->core.y +
4876 file_mgr_rec->header_frame->core.height +
4877 file_mgr_rec->scroll_window->core.y +
4878 w->core.y + gHeight/2;;
4880 if((Dimension)(x + width) > (Dimension)displayWidth)
4881 x = displayWidth - width - 4;
4882 if((Dimension)(y + height) > (Dimension)displayHeight)
4883 y = displayHeight - height - 4;
4885 XtSetArg (args[0], XmNx, x);
4886 XtSetArg (args[1], XmNy, y);
4887 XtSetValues(XtParent(fileMgrPopup.menu), args, 2);
4891 if(( event->type == ButtonPress || event->type == ButtonRelease) ||
4892 ( ( event->type == KeyPress || event->type == KeyRelease) &&
4893 _XmIsEventUnique(event) ) )
4895 XmMenuPosition(fileMgrPopup.menu, (XButtonPressedEvent *)event);
4899 XtManageChild(fileMgrPopup.menu);
4901 if( event->type == KeyPress || event->type == KeyRelease )
4903 /* Specify that the focus is being moved by key, NOT mouse
4905 _XmSetInDragMode(fileMgrPopup.menu,False);
4907 XmProcessTraversal(fileMgrPopup.menu,XmTRAVERSE_CURRENT);
4909 /* This function is being called twice.
4910 Record this event so the above check _XmIsEventUnique will work
4912 _XmRecordEvent(event);
4920 XtPointer client_data,
4921 XtPointer call_data)
4923 DtDndDropCallbackStruct *fileList = (DtDndDropCallbackStruct *)call_data;
4925 char ** file_set = NULL;
4926 char ** host_set = NULL;
4927 FileMgrRec * file_mgr_rec;
4928 FileMgrData * file_mgr_data;
4936 int effScreenHeight;
4937 int start_x = 0, start_y = 0;
4939 int step = 0, dstep = 0;
4941 /* Check the protocol, set to failure if not the */
4942 /* File Transfer protocol */
4943 if (fileList->dropData->protocol != DtDND_FILENAME_TRANSFER)
4945 fileList->status = DtDND_FAILURE;
4950 numFiles = fileList->dropData->numItems;
4952 DPRINTF (("DropOnRoot: Number of files dropped are %d\n", numFiles));
4954 if(fileList->reason != DtCR_DND_DROP_ANIMATE)
4956 /* set the complete move flag to False since it is not required to be called */
4957 /* In case when the drag is from non File manager client */
4959 initiating_view = NULL;
4961 fileList->completeMove = False;
4963 _DtSetDroppedFileInfo(fileList, &file_set, &host_set);
4965 if(initiating_view != NULL)
4967 file_mgr_rec = (FileMgrRec *)
4968 (((FileMgrData *) initiating_view)->file_mgr_rec);
4969 file_mgr_data = (FileMgrData *) initiating_view;
4972 file_mgr_data = NULL;
4974 /* get the correct position for the desktop icon shell */
4975 PositionDesktopIcon(fileList->x, fileList->y, &root_x, &root_y);
4980 * We will place the icons by marching down a diagonal starting
4981 * at the drop point. But we don't want to march off-screen
4982 * if there are too many icons. So ...
4983 * - We choose a step width of 20, 10, 5, or 2 depending
4984 * on the number of icons dropped.
4985 * - When we run into the edge of the screen, we start a new
4986 * diagonal shifted one step to the right.
4987 * - If all icons still won't fit, we move the starting point
4988 * closer to the top left corner of the screen.
4991 /* compute effective screen size (largest x,y where an icon
4992 * can be placed without going off-screen) */
4993 effScreenWidth = WidthOfScreen(XtScreen(w)) - (4 + 4+48+4 + 5);
4994 effScreenHeight = HeightOfScreen(XtScreen(w)) - (4 + 4+48+3+15+4 + 5);
4996 /* chosee step depending on number of icons */
4997 if (numFiles <= 200)
4999 else if (numFiles <= 400)
5001 else if (numFiles <= 1000)
5005 dstep = 40 + 4+48+4 + 5;
5007 /* choose starting point so at least two icons will fit */
5008 if (root_x <= effScreenWidth - step)
5011 start_x = effScreenWidth - step;
5013 if (root_y <= effScreenWidth - step)
5016 start_y = effScreenWidth - step;
5018 DPRINTF(("DropOnRootCB: numFiles %d, root_x %d, root_y %d, step %d\n",
5019 numFiles, root_x, root_y, step));
5021 /* check if all icons will fit */
5024 /* cacluclate how many will fit (add up icons on all diagonals) */
5026 for (root_x = start_x; root_x <= effScreenWidth; root_x += dstep)
5028 int nx = (effScreenWidth - root_x)/step + 1;
5029 int ny = (effScreenHeight - start_y)/step + 1;
5030 n += (nx <= ny)? nx: ny;
5034 DPRINTF(("start_x %d, start_y %d, nd %d, n %d\n",
5035 start_x, start_y, nd, n));
5037 /* if everything fits - great! */
5041 /* move the start point closer to the top left corner */
5042 if (effScreenWidth - start_x < effScreenHeight - start_y &&
5045 /* move left so more icons will fit */
5048 else if (effScreenWidth - start_x > effScreenHeight - start_y &&
5051 /* move up so one more icon will fit in each diagonal */
5054 else if (start_x > 0 || start_y > 0)
5056 /* move left and up */
5057 if (start_x >= step)
5061 if (start_y >= step)
5067 /* ran out of space - too bad! */
5074 /* the icon that was dropped on the root window was an
5075 icon that was already on the root window */
5076 if (file_mgr_data == NULL)
5078 DPRINTF(("DropOnRoot: Object already on Desktop\n"));
5080 /* loop through the existing desktop icons to determine which
5081 ones are being dragged, then change their location */
5082 for(i=0; i < desktop_data->numIconsUsed; i++)
5084 if((Widget)desktop_data->desktopWindows[i]->iconGadget ==
5085 (Widget)widget_dragged)
5087 if (DTFileIsSelected(desktop_data->desktopWindows[i],
5088 desktop_data->desktopWindows[i]->file_view_data))
5090 for(j=0;j< desktop_data->numWorkspaces;j++)
5091 if(desktop_data->workspaceData[j]->number ==
5092 desktop_data->desktopWindows[i]->workspace_num)
5096 j < desktop_data->workspaceData[wsNum]->files_selected;
5099 RelocateDesktopIcon(desktop_data->workspaceData[wsNum]->
5100 selectedDTWindows[j],
5104 if (root_x > effScreenWidth || root_y > effScreenHeight)
5107 if (start_x > effScreenWidth)
5116 RelocateDesktopIcon(desktop_data->desktopWindows[i],
5123 else if( file_mgr_data == trashFileMgrData )
5125 /* if the file manager data is the trash, we want to tell the
5126 user that they can't drop trash on the desktop
5131 DPRINTF(("DropOnRoot: Attempting to Drag Trash Object to Desktop\n"));
5132 file_mgr_rec = (FileMgrRec *)trashFileMgrData->file_mgr_rec;
5133 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."));
5134 msg = XtNewString(tmpStr);
5135 FileOperationError (file_mgr_rec->main, msg, NULL);
5139 else /* it was dropped on the root window so lets process it */
5141 int EndIndex = desktop_data->numIconsUsed;
5143 for(i = 0; i < numFiles; i++)
5145 ptr = strrchr(file_set[i], '/');
5146 if( strcmp(file_mgr_data->current_directory, file_set[i]) == 0)
5148 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5149 file_mgr_data, file_mgr_rec,
5150 ".", host_set[i], file_set[i],
5154 else if(strncmp(file_mgr_data->current_directory, file_set[i], strlen(file_set[i]) ) == 0 )
5156 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5157 file_mgr_data, file_mgr_rec,
5158 "..", host_set[i],file_mgr_data->current_directory,
5165 if(*(file_set[i]) == 0)
5167 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5168 file_mgr_data, file_mgr_rec,
5169 ptr + 1, host_set[i], "/",
5175 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5176 file_mgr_data, file_mgr_rec,
5177 ptr + 1, host_set[i], file_set[i],
5184 if (root_x > effScreenWidth || root_y > effScreenHeight)
5187 if (start_x > effScreenWidth)
5193 initiating_view = (XtPointer)NULL;
5196 _DtFreeDroppedFileInfo(numFiles, file_set, host_set);
5202 /************************************************************************
5206 ************************************************************************/
5209 FreeLayoutData(XtPointer p)
5211 IconLayoutData *layout_data;
5216 layout_data = (IconLayoutData *)p;
5218 if (layout_data->work_id != 0)
5220 DPRINTF(("FreeLayoutData: removing workproc\n"));
5221 XtRemoveWorkProc(layout_data->work_id);
5222 XmDropSiteEndUpdate(layout_data->drop_site_w);
5225 XtFree((char *)layout_data->order_list);
5226 layout_data->order_list = NULL;
5227 XtFree((char *)layout_data->reuse_icons);
5228 layout_data->reuse_icons = NULL;
5229 XtFree((char *)layout_data->reuse_btns);
5230 layout_data->reuse_btns = NULL;
5231 XtFree((char *)layout_data->manage);
5232 layout_data->manage = NULL;
5234 XtFree((char *)layout_data);
5238 /************************************************************************
5241 * Unmanage a subset of the file icons.
5243 ************************************************************************/
5245 void UnmanageFileIcons(
5246 FileMgrRec *file_mgr_rec,
5247 FileMgrData *file_mgr_data,
5248 FileViewData *file_view_data)
5250 XmManagerWidget file_window;
5251 FileViewData **order_list;
5259 /* Set the size of the file window BIG so that it does not */
5260 /* try to force positioning on its children. */
5262 file_window = (XmManagerWidget) file_mgr_rec->file_window;
5263 XtResizeWidget ((Widget)file_window, 32767, 32767, 0);
5266 /* Set the scrolled window and file window appropriately */
5267 /* to prevent a lot of gyrations. */
5269 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmSTATIC);
5270 XtSetValues (file_mgr_rec->scroll_window, args, 1);
5272 order_list = ((IconLayoutData *)file_mgr_data->layout_data)->order_list;
5273 order_count = ((IconLayoutData *)file_mgr_data->layout_data)->order_count;
5275 unmanage = (Widget *)XtMalloc(2*order_count*sizeof(Widget));
5277 for (i = 0; i < order_count; i++)
5279 if (order_list[i]->filtered)
5282 if ((n > 0 || order_list[i] == file_view_data) &&
5283 !order_list[i]->need_update)
5285 unmanage[n++] = order_list[i]->widget;
5286 if (order_list[i]->treebtn)
5287 unmanage[n++] = order_list[i]->treebtn;
5291 /* remember which icon currently has the focus */
5292 if (XtIsManaged(file_mgr_rec->file_window))
5294 /* see if the focus is inside the file window */
5295 child = XmGetFocusWidget(file_mgr_rec->file_window);
5296 if (child != NULL && XtParent(child) == file_mgr_rec->file_window)
5297 file_mgr_rec->focus_widget = child;
5300 /* unmanage the selected children */
5302 XtUnmanageChildren(unmanage, n);
5304 XtFree((char *)unmanage);
5308 /************************************************************************
5311 * Create or reuse a set of file icons used to get the files
5312 * displayed. This is never called for the desktop.
5314 ************************************************************************/
5318 FileMgrRec *file_mgr_rec,
5319 FileMgrData *file_mgr_data,
5320 Boolean new_directory)
5322 _UpdateFileIcons(file_mgr_rec, file_mgr_data, new_directory, NULL);
5327 FileMgrRec *file_mgr_rec,
5328 FileMgrData *file_mgr_data,
5329 DirectorySet * add_dir_set)
5331 _UpdateFileIcons(file_mgr_rec, file_mgr_data, False, add_dir_set);
5335 /*--------------------------------------------------------------------
5338 * Background information:
5339 * After a refresh on a directory we want to reuse old icon and tree
5340 * button widgets instead of destroying the old widgets and creating
5341 * new ones. Fourthermore, we want to reuse the same widgets for the
5342 * same files, so that if the icon and/or label didn't change, less
5343 * work needs to be done in _UpdateFileIcons().
5344 * For this reason, after a refresh the GetFileData() routine copies
5345 * Widgets from the old FileViewData list to the new FileViewData list
5346 * for files that are both on the old and new list (i.e., files that
5347 * already existed before the refresh and are still there after the
5348 * refresh). This allows _UpdateFileIcons() to reuse the old
5351 * The purpose of MakeReuseList() is to find widgets that are no
5352 * longer found in the new FileViewData list. These are widgets
5353 * from files that disappeared after the refresh (either because the
5354 * file was deleted or because file is now filtered out). These
5355 * widgets can then be reused by _UpdateFileIcons()for new files that
5356 * just appeared after the refresh.
5358 *------------------------------------------------------------------*/
5360 /* compare function for qsort and bsearch */
5362 WidgetCmp(Widget *w1, Widget *w2)
5371 FileViewData **order_list,
5373 Widget **reuse_icons,
5374 Widget **reuse_btns)
5377 int n_old, n_filtered, del_icon, del_btn;
5379 Widget *sorted_chilren = NULL;
5380 Boolean *reuse = NULL;
5387 /* allocate widget arrays */
5388 *reuse_icons = (Widget *)XtMalloc((num_children + 1)*sizeof(Widget));
5389 *reuse_btns = (Widget *)XtMalloc((num_children + 1)*sizeof(Widget));
5390 icon_count = btn_count = 0;
5392 /* only figure things out if we already have children */
5393 if (num_children > 0) {
5394 /* create a sorted list of children */
5395 sorted_chilren = (Widget *)XtMalloc(num_children * sizeof(Widget));
5396 memcpy(sorted_chilren, children, num_children * sizeof(Widget));
5397 qsort(sorted_chilren, num_children, sizeof(Widget), (int (*)())WidgetCmp);
5399 /* create reuse flags; initially assume all children can be reused */
5400 reuse = (Boolean *)XtMalloc(num_children * sizeof(Boolean));
5401 for (i = 0; i < num_children; i++)
5404 /* reset reuse flag for all widgets found in order_list */
5406 n_old = n_filtered = del_icon = del_btn = 0;
5408 for (i = 0; i < order_count; i++)
5410 if (order_list[i]->filtered &&
5411 strcmp(order_list[i]->file_data->file_name, ".") != 0)
5413 /* don't reuse this widget later */
5416 if (order_list[i]->widget)
5418 if (order_list[i]->treebtn)
5421 order_list[i]->widget =
5422 order_list[i]->treebtn = NULL;
5426 if (order_list[i]->widget)
5428 p = bsearch(&order_list[i]->widget,
5429 sorted_chilren, num_children, sizeof(Widget),
5430 (int (*)())WidgetCmp);
5433 /* don't reuse this widget for any other file */
5434 reuse[p - sorted_chilren] = False;
5441 /* don't reuse this widget later */
5442 order_list[i]->widget = NULL;
5449 if (order_list[i]->treebtn)
5451 p = bsearch(&order_list[i]->treebtn,
5452 sorted_chilren, num_children, sizeof(Widget),
5453 (int (*)())WidgetCmp);
5456 /* don't reuse this widget for any other file */
5457 reuse[p - sorted_chilren] = False;
5461 /* don't reuse this widget later */
5462 order_list[i]->treebtn = NULL;
5471 /* copy reusable widgets into widget arrays */
5472 for (i = 0; i < num_children; i++)
5476 /* this widget can be reused for new files */
5477 w = sorted_chilren[i];
5478 if (XtClass(w) == dtIconGadgetClass)
5480 #ifndef DELAYED_UNREGISTER
5483 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
5484 XtRemoveAllCallbacks(w, XmNdropCallback);
5485 XtSetValues (w, args, 1);
5487 (*reuse_icons)[icon_count++] = w;
5489 else if (XtClass(w) == xmPushButtonGadgetClass)
5490 (*reuse_btns)[btn_count++] = w;
5495 /* null-terminate the arrays */
5496 (*reuse_icons)[icon_count] = NULL;
5497 (*reuse_btns)[btn_count] = NULL;
5500 XtFree((char *)sorted_chilren);
5501 XtFree((char *)reuse);
5503 DPRINTF(("MakeReuseList: count %d (%d new, %d old, %d filtered)\n",
5504 order_count, order_count - n_filtered - n_old, n_old, n_filtered));
5505 DPRINTF((" reuse %d + %d, del %d + %d\n",
5506 icon_count, btn_count, del_icon, del_btn));
5510 /*--------------------------------------------------------------------
5511 * UpdateOneIconLabel
5512 *------------------------------------------------------------------*/
5516 FileMgrData *file_mgr_data,
5517 FileViewData *file_view_data)
5522 /* Get the label and icon to be used for the widget */
5523 if (file_mgr_data->view != BY_ATTRIBUTES)
5525 if (strcmp(file_view_data->file_data->file_name, "..") == 0)
5527 /* label = ".. (go up)" */
5528 s = GetSharedMessage(UP_ONE_LEVEL_LABEL);
5529 label = (char *)XtMalloc(2 + strlen(s) + 1);
5530 strcpy(label, "..");
5533 else if (file_mgr_data->view == BY_NAME &&
5534 file_view_data->file_data->physical_type == DtDIRECTORY &&
5535 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
5537 /* label = "name/" */
5538 label = (char *)XtMalloc(
5539 strlen(file_view_data->file_data->file_name) + 2);
5540 strcpy(label, file_view_data->file_data->file_name);
5543 else if (file_mgr_data->view == BY_NAME &&
5544 file_view_data->file_data->physical_type == DtEXECUTABLE)
5546 /* label = "name*" */
5547 label = (char *)XtMalloc(
5548 strlen(file_view_data->file_data->file_name) + 2);
5549 strcpy(label, file_view_data->file_data->file_name);
5552 else if(file_view_data->file_data->action_name != NULL)
5553 /* label = action name */
5554 label = XtNewString(file_view_data->file_data->action_name);
5556 /* label = file name */
5557 label = XtNewString(file_view_data->file_data->file_name);
5559 else /* file_mgr_data->view == BY_ATTRIBUTES */
5561 /* label = file name + attributes */
5562 label = GetLongName(file_view_data->file_data);
5563 if (strcmp(file_view_data->file_data->file_name, "..") == 0)
5565 s = GetSharedMessage(UP_ONE_LEVEL_LABEL);
5566 label = (char *)XtRealloc(label, strlen(label) + strlen(s) + 1);
5571 /* store new label */
5572 XtFree(file_view_data->label);
5573 file_view_data->label = label;
5577 /*--------------------------------------------------------------------
5579 *------------------------------------------------------------------*/
5583 FileMgrRec *file_mgr_rec,
5584 FileMgrData *file_mgr_data,
5585 FileViewData *file_view_data)
5587 XmString icon_label;
5589 PixmapData *pixmapData;
5592 Boolean is_instance_icon;
5593 Boolean instance_icon_changed;
5599 XmManagerWidget file_window = (XmManagerWidget) file_mgr_rec->file_window;
5600 DirectorySet *directory_set = (DirectorySet *)file_view_data->directory_set;
5601 IconLayoutData *layout_data = (IconLayoutData *)file_mgr_data->layout_data;
5603 /* Get the label and icon to be used for the widget */
5604 if (!file_view_data->label)
5605 UpdateOneIconLabel(file_mgr_data, file_view_data);
5607 icon_label = XmStringCreateLocalized(file_view_data->label);
5609 /* Get the icon name based on the file type */
5611 logical_type = file_view_data->file_data->logical_type;
5613 if (file_mgr_data->view == BY_NAME)
5615 else if (openDirType == NEW &&
5616 file_view_data->file_data->physical_type == DtDIRECTORY)
5618 pixmapData = CheckForOpenDirectory(file_view_data,
5625 if (file_mgr_data->view == BY_NAME_AND_ICON)
5626 pixmapData = _DtRetrievePixmapData(
5628 file_view_data->file_data->file_name,
5629 directory_set->name,
5630 (Widget) file_window,
5633 pixmapData = _DtRetrievePixmapData(
5635 file_view_data->file_data->file_name,
5636 directory_set->name,
5637 (Widget) file_window,
5641 /* check if this is an instance icon */
5642 is_instance_icon = False;
5643 if (pixmapData != NULL)
5647 strcpy(tmp, directory_set->name);
5649 strcat(tmp, file_view_data->file_data->file_name);
5650 if (strcmp(pixmapData->iconFileName, tmp) == 0)
5651 is_instance_icon = True;
5654 /* check if instance icon was modified */
5655 instance_icon_changed = False;
5656 if (is_instance_icon)
5658 if (file_view_data->icon_mtime != file_view_data->file_data->stat.st_mtime)
5660 if (file_view_data->icon_mtime != 0)
5661 instance_icon_changed = True;
5662 file_view_data->icon_mtime = file_view_data->file_data->stat.st_mtime;
5666 file_view_data->icon_mtime = 0;
5668 /* Build the arg list for color resources. */
5670 XtSetArg (args[n], XmNarmColor, white_pixel); n++;
5672 if (layout_data->background == white_pixel)
5674 if (file_view_data->selected)
5676 XtSetArg (args[n], XmNbackground, black_pixel); n++;
5677 XtSetArg (args[n], XmNforeground, white_pixel); n++;
5681 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5682 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5684 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5685 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5687 else if (layout_data->background == black_pixel)
5689 if (file_view_data->selected)
5691 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5692 XtSetArg (args[n], XmNforeground, black_pixel); n++;
5696 XtSetArg (args[n], XmNbackground, black_pixel); n++;
5697 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5699 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5700 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5704 if (file_view_data->selected)
5706 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5707 XtSetArg (args[n], XmNforeground, black_pixel); n++;
5708 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5709 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5713 XtSetArg (args[n], XmNbackground, layout_data->background); n++;
5714 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5715 XtSetArg (args[n], XmNpixmapBackground, layout_data->pixmap_back); n++;
5716 XtSetArg (args[n], XmNpixmapForeground, layout_data->pixmap_fore); n++;
5722 /* Build the rest of the arg list and either create or reuse the widget. */
5724 XtSetArg (args[n], XmNstring, icon_label); n++;
5727 XtSetArg (args[n], XmNimageName, pixmapData->iconFileName);
5729 XtSetArg (args[n], XmNimageName, NULL);
5731 XtSetArg (args[n], XmNmaxPixmapWidth, layout_data->pixmap_width); n++;
5732 XtSetArg (args[n], XmNmaxPixmapHeight, layout_data->pixmap_height); n++;
5733 XtSetArg (args[n], XmNuserData, directory_set); n++;
5734 XtSetArg (args[n], XmNunderline, False); n++;
5735 XtSetArg (args[n], XmNfillMode, XmFILL_TRANSPARENT); n++;
5736 if (file_mgr_data->view == BY_NAME_AND_ICON &&
5737 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
5738 XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_TOP);
5740 XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_LEFT); n++;
5742 /* See if we can re-use the same or some other icon gadget */
5743 if (file_view_data->widget)
5744 icon_widget = file_view_data->widget;
5745 else if (*layout_data->next_icon_to_use)
5746 icon_widget = *layout_data->next_icon_to_use++;
5750 /* See if we found an available icon gadget */
5753 /* reuse the icon gadget */
5754 if (icon_widget != file_view_data->widget || file_mgr_data->newSize)
5756 XtSetArg (args[n], XmNdropSiteOperations, XmDROP_NOOP);n++;
5757 XtRemoveAllCallbacks(icon_widget, XmNdropCallback);
5758 file_view_data->registered = False;
5760 XtRemoveAllCallbacks (icon_widget, XmNcallback);
5762 /* if instance_icon_changed, force destroy of old pixmap */
5763 if (instance_icon_changed)
5764 XtSetArg (args[argi_imageName], XmNimageName, NULL);
5767 * Move the gadget off the visible area; this avoids unnecessary
5768 * redraw events at the old position when the gadget is moved to
5769 * the correct position once it is determined in LayoutFileIcons.
5771 icon_widget->core.x = -999;
5772 icon_widget->core.y = -999;
5773 XtSetValues (icon_widget, args, n);
5775 if (instance_icon_changed && pixmapData)
5777 XtSetArg (args[0], XmNimageName, pixmapData->iconFileName);
5778 XtSetValues (icon_widget, args, 1);
5783 /* create a new or duplicate an existing widget */
5784 XtSetArg (args[n], XmNshadowThickness, 2); n++;
5785 XtSetArg (args[n], XmNdropSiteOperations, XmDROP_NOOP);n++;
5786 XtSetArg (args[n], XmNfontList, user_font); n++;
5787 if( keybdFocusPolicy == XmEXPLICIT)
5789 XtSetArg (args[n], XmNtraversalOn, True); n++;
5793 XtSetArg (args[n], XmNtraversalOn, False); n++;
5794 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
5796 XtSetArg (args[n], XmNborderType, DtNON_RECTANGLE); n++;
5798 if (layout_data->dup_icon_widget == NULL)
5800 #ifdef HARDCODED_ICON_MARGINS
5801 XtSetArg (args[n], XmNmarginWidth, 0); n++;
5802 XtSetArg (args[n], XmNmarginHeight, 0); n++;
5804 XtSetArg (args[n], XmNx, -999); n++;
5805 XtSetArg (args[n], XmNy, -999); n++;
5806 icon_widget = layout_data->dup_icon_widget =
5807 _DtCreateIcon ((Widget)file_window, "icon", args, n);
5812 int i = n_color_args;
5814 icon_widget = _DtDuplicateIcon ((Widget)file_window,
5815 layout_data->dup_icon_widget,
5817 (pixmapData? pixmapData->iconFileName: NULL),
5818 (XtPointer)directory_set, /* userData */
5819 False); /* underline */
5820 g = (DtIconGadget)icon_widget;
5821 g->gadget.highlighted = False;
5822 g->gadget.highlight_drawn = False;
5825 * Move the gadget off the visible area; this avoids unnecessary
5826 * redraw events at the old position when the gadget is moved to
5827 * the correct position once it is determined in LayoutFileIcons.
5829 icon_widget->core.x = -999;
5830 icon_widget->core.y = -999;
5832 /* make sure colors, drop operations, and clipping are right */
5833 XtSetArg(args[i], XmNdropSiteOperations, XmDROP_NOOP); i++;
5834 XtSetArg(args[i], XmNmaxPixmapWidth, layout_data->pixmap_width); i++;
5835 XtSetArg(args[i], XmNmaxPixmapHeight, layout_data->pixmap_height); i++;
5836 XtSetValues (icon_widget, args, i);
5838 XtAddCallback(icon_widget, XmNhelpCallback,
5839 (XtCallbackProc)HelpRequestCB, NULL);
5840 file_view_data->registered = False;
5843 if (file_mgr_data->view != BY_NAME)
5844 _DtCheckAndFreePixmapData(logical_type,
5845 (Widget) file_window,
5846 (DtIconGadget) icon_widget,
5850 if (file_view_data->file_data->link != 0)
5852 XtSetArg (args[0], XmNforeground, layout_data->topshadow);
5853 XtSetValues (icon_widget, args, 1);
5858 * If viewing by attributes, adjust spacing between the icon pixmap and
5859 * the file name so that all file names are aligned.
5861 if (file_mgr_data->view != BY_NAME_AND_ICON ||
5862 file_mgr_data->show_type == MULTIPLE_DIRECTORY)
5864 Dimension pixmap_width = ((DtIconGadget)icon_widget)->icon.pixmap_width;
5866 if (pixmap_width < layout_data->pixmap_width)
5868 XtSetArg (args[0], XmNspacing,
5869 layout_data->spacing + layout_data->pixmap_width - pixmap_width);
5870 XtSetValues (icon_widget, args, 1);
5875 file_view_data->file_data->is_broken = False;
5876 file_view_data->widget = icon_widget;
5877 XtAddCallback (icon_widget, XmNcallback, (XtCallbackProc)IconCallback,
5880 XmStringFree (icon_label);
5882 /* Check if we need a button for tree branch expand */
5884 if (file_mgr_data->show_type != MULTIPLE_DIRECTORY ||
5885 !file_view_data->file_data->is_subdir)
5887 /* no tree branch expand button needed */
5888 file_view_data->treebtn = NULL;
5892 /* create a tree branch expand button */
5893 Pixmap px = GetTreebtnPixmap(file_mgr_data, file_view_data);
5896 XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
5897 XtSetArg(args[n], XmNlabelPixmap, px); n++;
5898 XtSetArg(args[n], XmNbackground, layout_data->background); n++;
5899 XtSetArg(args[n], XmNtraversalOn, False); n++;
5900 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
5901 XtSetArg(args[n], XmNshadowThickness, 0); n++;
5902 XtSetArg(args[n], XmNmarginWidth, 0); n++;
5903 XtSetArg(args[n], XmNmarginHeight, 0); n++;
5904 XtSetArg(args[n], XmNuserData, file_mgr_data); n++;
5905 XtSetArg(args[n], XmNx, -999); n++;
5906 XtSetArg(args[n], XmNy, -999); n++;
5908 /* See if we can re-use the same or some other button gadget */
5909 if (file_view_data->treebtn)
5910 btn_widget = file_view_data->treebtn;
5911 else if (*layout_data->next_btn_to_use)
5912 btn_widget = *(layout_data->next_btn_to_use)++;
5916 /* See if we found an available button gadget */
5918 XtRemoveAllCallbacks (btn_widget, XmNactivateCallback);
5919 XtSetValues (btn_widget, args, n);
5923 btn_widget = XmCreatePushButtonGadget((Widget)file_window,
5924 "tree_button", args, n);
5926 XtAddCallback(btn_widget, XmNactivateCallback,
5927 (XtCallbackProc)TreeBtnCallback, file_view_data);
5929 file_view_data->treebtn = btn_widget;
5932 /* this entry is now up-to-date */
5933 file_view_data->need_update = False;
5937 /*--------------------------------------------------------------------
5939 *------------------------------------------------------------------*/
5943 FileMgrRec *file_mgr_rec,
5944 FileMgrData *file_mgr_data,
5945 Boolean new_directory,
5946 DirectorySet * add_dir_set)
5948 XmManagerWidget file_window;
5949 FileViewData **order_list;
5953 IconLayoutData *layout_data;
5956 #ifdef DT_PERFORMANCE
5957 struct timeval update_time_s;
5958 struct timeval update_time_f;
5961 DPRINTF(("_UpdateFileIcons(\"%s\", new_dir %c, add_dir_set %p) ...\n",
5962 file_mgr_data->current_directory,
5963 new_directory? 'T': 'F', add_dir_set));
5965 /* Set the size of the file window BIG so that it does not */
5966 /* try to force positioning on its children. */
5967 file_window = (XmManagerWidget) file_mgr_rec->file_window;
5968 XtResizeWidget ((Widget)file_window, 32767, 32767, 0);
5970 /* Set the scrolled window and file window appropriately */
5971 /* to prevent a lot of gyrations. */
5973 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmSTATIC);
5974 XtSetValues (file_mgr_rec->scroll_window, args, 1);
5976 /* For faster updates, unmanage all the icons */
5977 if (XtIsManaged(file_mgr_rec->file_window))
5979 /* see if the focus is inside the file window */
5980 child = XmGetFocusWidget(file_mgr_rec->file_window);
5985 file_mgr_rec->focus_widget = file_mgr_rec->file_window;
5987 else if( XtParent(child) == file_mgr_rec->file_window )
5989 /* remember which widget had the focus */
5990 file_mgr_rec->focus_widget = child;
5994 DPRINTF((" focus_widget = %p (%s)\n",
5995 file_mgr_rec->focus_widget,
5996 file_mgr_rec->focus_widget?
5997 XtName(file_mgr_rec->focus_widget): "nil"));
5998 XtUnmanageChild(file_mgr_rec->file_window);
6001 XtUnmanageChildren(file_window->composite.children,
6002 file_window->composite.num_children);
6004 /* if this is a new directory, scroll to the top */
6007 XtSetArg (args[0], XmNx, 0);
6008 XtSetArg (args[1], XmNy, 0);
6009 XtSetValues ((Widget)file_window, args, 2);
6013 * Don't leave the view in a munged state for too long.
6014 * Only do if we are not creating a new view. This is because the
6015 * view is not yet in the 'view_list', and so the redisplay code
6016 * may not use the correct redisplay function.
6018 if (ReturnDesktopPtr(file_mgr_rec->file_window))
6020 UpdateHeaders(file_mgr_rec, file_mgr_data, False);
6021 XFlush (XtDisplay (file_window));
6022 XmUpdateDisplay ((Widget)file_window);
6025 /* free any old layout data */
6026 FreeLayoutData(file_mgr_data->layout_data);
6027 file_mgr_data->layout_data = NULL;
6029 /* if directory-read still in progress, don't do anything more now */
6030 if (file_mgr_data->busy_status != not_busy)
6032 DPRINTF(("done (busy)\n"));
6036 #ifdef DT_PERFORMANCE
6037 printf(" Beginning UpdateFileIcons\n");
6038 gettimeofday(&update_time_s, NULL);
6041 _DtPerfChkpntMsgSend("Begin Update Icons");
6045 /* set up new layout data */
6046 layout_data = (IconLayoutData *)XtCalloc(1, sizeof(IconLayoutData));
6047 file_mgr_data->layout_data = (XtPointer)layout_data;
6049 FlattenTree(file_mgr_data, &order_list, &order_count);
6050 layout_data->order_list = order_list;
6051 layout_data->order_count = order_count;
6053 MakeReuseList(file_window->composite.children,
6054 file_window->composite.num_children,
6055 order_list, order_count,
6056 &layout_data->reuse_icons,
6057 &layout_data->reuse_btns);
6058 layout_data->next_icon_to_use = layout_data->reuse_icons;
6059 layout_data->next_btn_to_use = layout_data->reuse_btns;
6061 layout_data->manage = (Widget *)XtMalloc(2*order_count*sizeof(Widget));
6062 layout_data->manage_count = 0;
6064 layout_data->i_do_next_vis = 0;
6065 layout_data->i_do_next_all = 0;
6068 * Iterate through the file list and mark all entries to be in
6069 * need of update. We also construct icon labels at this time,
6070 * since they are need by LayoutFileIcons to estimate icon gadget
6076 /* only need to iterate throught the new entries */;
6077 order_list = add_dir_set->order_list;
6078 order_count = add_dir_set->file_count;
6081 for (i = 0; i < order_count; i++)
6083 order_list[i]->need_update = True;
6084 order_list[i]->selected = False;
6085 UpdateOneIconLabel(file_mgr_data, order_list[i]);
6088 /* set selected flag on all files in selection_list */
6089 for (i = 0; i < file_mgr_data->selected_file_count; i++)
6090 file_mgr_data->selection_list[i]->selected = True;
6092 #ifdef DT_PERFORMANCE
6093 gettimeofday(&update_time_f, NULL);
6094 if (update_time_s.tv_usec > update_time_f.tv_usec) {
6095 update_time_f.tv_usec += 1000000;
6096 update_time_f.tv_sec--;
6098 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);
6101 _DtPerfChkpntMsgSend("Done Update Icons");
6104 DPRINTF(("done\n"));
6110 /************************************************************************
6113 * Create icons for tree-branch-expand buttons.
6115 ************************************************************************/
6118 CreateTreeIcons(Widget w)
6121 Pixel background_color = 0;
6122 Pixel foreground_color = 0;
6126 unsigned int width, height, dummy;
6128 XtSetArg (args[0], XmNbackground, &background_color);
6129 XtSetArg (args[1], XmNforeground, &foreground_color);
6130 XtGetValues (w, args, 2);
6132 for (i = 0; i < 3; i++)
6136 for (j = 0; j < tpxN; j++)
6138 strcpy(pxname, TreePxTab[j].name);
6139 strcat(pxname, TreePxSuffix[i]);
6140 TreePxTab[j].px[i] = _DtGetPixmap(XtScreen(w), pxname,
6141 foreground_color, background_color);
6143 XGetGeometry(XtDisplay(w), TreePxTab[j].px[i],
6144 (Window *) &dummy, /* returned root window */
6145 (int *) &dummy, (int *) &dummy, /* x, y of pixmap */
6146 &width, &height, /* pixmap width, height */
6147 &dummy, &dummy); /* border width, depth */
6150 TreeNilWd[i] = width;
6151 TreeNilHt[i] = height;
6155 if (width > TreeBtnWd[i])
6156 TreeBtnWd[i] = width;
6157 if (height > TreeBtnHt[i])
6158 TreeBtnHt[i] = height;
6165 /************************************************************************
6168 * Get icon for tree-branch-expand buttons.
6170 ************************************************************************/
6172 Pixmap GetTreebtnPixmap(
6173 FileMgrData *file_mgr_data,
6174 FileViewData *file_view_data)
6178 /* if not yet done, create tree button icons */
6179 /* @@@ do this earlier from main? */
6180 if (TreeBtnWd[0] == 0)
6181 CreateTreeIcons(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
6183 if (file_view_data->ts == tsNotRead)
6185 else if (file_view_data->ts == tsError)
6187 else if (file_view_data->ndir == 0 &&
6188 (file_view_data->nfile == 0 ||
6189 file_mgr_data->tree_files == TREE_FILES_NEVER)
6190 && (file_view_data->ts == tsNone || !showEmptySet))
6192 else if (file_view_data->ts == tsNone)
6194 else if (file_view_data->ts == tsDirs)
6195 pxid = (file_view_data->nfile == 0 ||
6196 file_mgr_data->tree_files == TREE_FILES_NEVER)? tpxLess:
6197 (file_view_data->ndir == 0)? tpxMore:
6199 else if (file_view_data->ts == tsAll)
6202 if (file_mgr_data->view == BY_NAME)
6203 return TreePxTab[pxid].px[0]; /* small pixmap */
6204 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6205 return TreePxTab[pxid].px[2]; /* large pixmap */
6207 return TreePxTab[pxid].px[1]; /* medium pixmap */
6211 /************************************************************************
6214 * Compute maximum icon size.
6216 ************************************************************************/
6220 FileMgrRec *file_mgr_rec,
6221 FileMgrData *file_mgr_data,
6224 DirectorySet *directory_set;
6226 FileViewData **file_list;
6230 Dimension shadowThickness;
6231 Dimension marginWidth;
6232 Dimension maxWidth = ld->pixmap_width;
6233 Dimension gadgetWidth;
6235 /* determine pixmap size */
6236 if (file_mgr_data->view == BY_NAME)
6239 ld->pixmap_width = 0;
6240 ld->pixmap_height = 0;
6242 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6245 ld->pixmap_width = largeIconWidth;
6246 ld->pixmap_height = largeIconHeight;
6251 ld->pixmap_width = smallIconWidth;
6252 ld->pixmap_height = smallIconHeight;
6255 /* find the icon gadget for "." */
6256 directory_set = file_mgr_data->directory_set[0];
6257 file_count = directory_set->file_count;
6258 file_list = directory_set->file_view_data;
6261 for (i = 0; i < file_count; i++)
6263 if (strcmp(file_list[i]->file_data->file_name, ".") == 0)
6265 g = (DtIconGadget)file_list[i]->widget;
6270 /* get layout parameters from "." */
6273 XtSetArg(args[0], XmNhighlightThickness, &ld->highlight);
6274 XtSetArg(args[1], XmNshadowThickness, &shadowThickness);
6275 XtSetArg(args[2], XmNmarginWidth, &marginWidth);
6276 XtSetArg(args[3], XmNspacing, &ld->spacing);
6277 XtSetArg(args[4], XmNalignment, &ld->alignment);
6278 XtSetArg(args[5], XmNpixmapPosition, &ld->pixmap_position);
6279 XtGetValues((Widget)g, args, 6);
6281 if (g->icon.pixmap_width < maxWidth)
6282 ld->spacing = ld->spacing - (maxWidth - g->icon.pixmap_width);
6284 ld->width = ((Widget)g)->core.width +
6285 ld->pixmap_width - g->icon.pixmap_width;
6286 ld->height = ((Widget)g)->core.height +
6287 ld->pixmap_height - g->icon.pixmap_height;
6289 ld->char_width = (g->icon.string_width)/strlen(file_list[i]->label);
6290 if (ld->pixmap_position != XmPIXMAP_TOP)
6291 ld->width -= g->icon.string_width;
6292 ld->margin = ld->highlight + shadowThickness + marginWidth;
6296 /* No icon gadget for "." found: strange! Guess some defaults. */
6298 ld->margin = 2 + 1 + 1;
6300 ld->highlight = (keybdFocusPolicy == XmEXPLICIT)? 2: 0;
6301 ld->alignment = XmALIGNMENT_END;
6302 if (file_mgr_data->view == BY_NAME_AND_ICON &&
6303 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6305 ld->pixmap_position = XmPIXMAP_TOP;
6306 ld->width = 2*ld->margin + ld->pixmap_width;
6307 ld->height = 2*ld->margin + ld->pixmap_height + ld->spacing + 14;
6311 ld->pixmap_position = XmPIXMAP_LEFT;
6312 ld->width = 2*ld->margin + ld->pixmap_width +
6313 ld->spacing + ld->char_width;
6314 ld->height = 2*ld->margin + ld->pixmap_height;
6318 /* determine which size tree buttons to use */
6319 if (file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6320 ld->treebtn_size = 0; /* no tree buttons needed */
6321 else if (file_mgr_data->view == BY_NAME)
6322 ld->treebtn_size = 0; /* small size */
6323 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6324 ld->treebtn_size = 2; /* large size */
6326 ld->treebtn_size = 1; /* medium size */
6332 FileMgrRec *file_mgr_rec,
6333 FileMgrData *file_mgr_data,
6334 IconLayoutData *layout_data,
6335 FileViewData *file_view_data,
6342 if (file_view_data == NULL) {
6346 label_len = DtCharCount(file_view_data->label == NULL ?
6347 file_view_data->file_data->file_name : file_view_data->label);
6349 label_len = strlen(file_view_data->label == NULL ?
6350 file_view_data->file_data->file_name : file_view_data->label);
6354 if (layout_data->pixmap_position == XmPIXMAP_TOP)
6356 label_width = 2*layout_data->margin + label_len*layout_data->char_width;
6357 if ((Dimension)label_width > layout_data->width)
6358 *width = label_width;
6360 *width = layout_data->width;
6363 *width = layout_data->width + (label_len) * layout_data->char_width;
6364 *height = layout_data->height;
6368 /************************************************************************
6371 * Compute extra height for drawing nil symbol for empty tree branches.
6373 ************************************************************************/
6377 FileMgrData *file_mgr_data,
6378 FileViewData *file_view_data,
6382 file_view_data->file_data->is_subdir &&
6383 file_view_data->ts >= tsDirs &&
6384 file_view_data->ndir == 0 &&
6385 (file_view_data->nfile == 0 ||
6386 file_mgr_data->tree_files == TREE_FILES_NEVER))
6388 return YSPACING(file_mgr_data) + TreeNilHt[treebtn_size];
6395 /************************************************************************
6398 * Erase connecting lines in tree mode from a specified icon widget
6399 * on down; called when a tree branch is expanded or collapsed to
6400 * erase previous tree lines before drawing new icons and tree lines.
6402 ************************************************************************/
6406 FileMgrRec *file_mgr_rec,
6407 FileMgrData *file_mgr_data,
6408 FileViewData *file_view_data)
6410 XmManagerWidget file_window;
6411 Dimension fw_width, fw_height;
6414 file_window = (XmManagerWidget) file_mgr_rec->file_window;
6415 if (!XtIsManaged((Widget)file_window))
6418 /* get upper left corner of grid space for the icon widget */
6419 x = file_view_data->x;
6420 y = file_view_data->y - file_mgr_data->grid_height;
6422 /* Get file window width and height */
6423 fw_width = file_window->core.width;
6424 fw_height = file_window->core.height;
6426 DPRINTF2(("EraseTreeLines(\"%s\"): x/y %d/%d (widget %d/%d)\n",
6427 file_view_data->file_data->file_name, x, y,
6428 file_view_data->widget->core.x,
6429 file_view_data->widget->core.y));
6431 /* clear area from icon widget to bottom of file window */
6432 XClearArea(XtDisplay(file_window), XtWindow(file_window),
6433 x, y, fw_width - x, fw_height - y, False);
6436 * clear area to the right and above the icon widget
6437 * (necessary if there are multiple columns, which happens if
6438 * there are more icons than fit into a single column of
6439 * maximum height 32767)
6441 if (y > 0 && (Dimension)(x + file_mgr_data->grid_width) < fw_width)
6443 x += file_mgr_data->grid_width;
6444 XClearArea(XtDisplay(file_window), XtWindow(file_window),
6445 x, 0, fw_width - x, y, False);
6450 /************************************************************************
6453 * Redraw connecting lines in tree mode.
6455 ************************************************************************/
6460 int ex, int ey, int ewidth, int eheight, int ecount,
6461 FileMgrRec *file_mgr_rec,
6462 FileMgrData *file_mgr_data)
6464 static char *empty_msg = NULL;
6466 FileViewData *file_view_data;
6467 IconLayoutData *layout_data;
6468 Dimension grid_width, grid_height;
6469 Dimension extra_height, e_height;
6471 FileViewData **order_list;
6473 GC solid_gc, dash_gc;
6479 XFontSetExtents *extents;
6484 if (!XtIsManaged(w))
6487 /* get layout parameters */
6488 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
6489 order_list = layout_data->order_list;
6490 order_count = layout_data->order_count;
6491 grid_width = file_mgr_data->grid_width;
6492 grid_height = file_mgr_data->grid_height;
6493 sz = layout_data->treebtn_size;
6495 DPRINTF2(("RedrawTreeLines(x %d, y %d, wd %d, ht %d, count %d)\n",
6496 ex, ey, ewidth, eheight, ecount));
6498 if (grid_width == 0 || grid_height == 0)
6499 /* layout probably not yet done */
6502 /* if not yet done, create tree button icons */
6503 /* @@@ do this earlier from main? */
6504 if (TreeBtnWd[0] == 0)
6505 CreateTreeIcons(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
6507 /* select line styles */
6508 if (file_mgr_data->view == BY_NAME) {
6509 solid_gc = file_mgr_data->tree_solid_thin_gc;
6510 dash_gc = file_mgr_data->tree_dash_thin_gc;
6512 solid_gc = file_mgr_data->tree_solid_thick_gc;
6513 dash_gc = file_mgr_data->tree_dash_thick_gc;
6519 for (k = 0; k < order_count; k++)
6521 if (!order_list[k]->displayed)
6524 /* determine the height of this item */
6525 file_view_data = order_list[k];
6526 extra_height = GetExtraHeight(file_mgr_data, file_view_data, sz);
6527 GetLevel(file_view_data, &level);
6529 /* check if we need to go to the next column */
6530 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
6531 if (tmp + MARGIN > MAXWINSIZE)
6533 /* window would exceed height limit; go to the next column */
6534 x += grid_width + XSPACING;
6536 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
6539 /* check if current item intersects the exposed region */
6540 y0 = y - YSPACING(file_mgr_data)
6542 + (Dimension)(grid_height - TreeBtnHt[sz])/(Dimension)2
6544 y1 = y + grid_height + extra_height + YSPACING(file_mgr_data);
6545 if (x <= ex + ewidth && x + TreeWd(level, sz) > ex &&
6546 y0 <= ey + eheight && y1 > ey)
6548 GetAncestorInfo(file_mgr_data, file_view_data, NULL, NULL, more);
6550 /* draw vertical connecting lines for upper tree levels */
6551 for (i = 0; i < level; i++) {
6553 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6554 x + TreeLX(i, sz), y0,
6555 x + TreeLX(i, sz), y1);
6558 /* draw vertical connecting line for this tree level */
6559 xl = x + TreeLX(level, sz);
6561 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6563 xl, more[level]? y1: y + grid_height/2);
6565 if (file_view_data->file_data->is_subdir || !more[level]) {
6566 /* draw horizontal line */
6567 XDrawLine(XtDisplay(w), XtWindow(w),
6568 (file_view_data->file_data->is_subdir &&
6569 file_view_data->ts == tsNotRead)? dash_gc: solid_gc,
6570 xl, y + grid_height/2,
6571 xl + TreeOffset, y + grid_height/2);
6575 /* draw nil symbol for empty subdirs */
6578 xl += TreeOneWd(sz);
6579 y0 += grid_height + YSPACING(file_mgr_data);
6580 y1 = y + grid_height + YSPACING(file_mgr_data);
6581 e_height = extra_height - YSPACING(file_mgr_data);
6583 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6585 xl, y1 + e_height/2);
6587 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6588 xl, y1 + e_height/2,
6589 xl + TreeOffset, y1 + e_height/2);
6591 xl = x + TreeWd(level, sz) + TreeBtnWd[sz];
6592 XCopyArea(XtDisplay(w), TreePxTab[tpxNil].px[sz],
6593 XtWindow(w), solid_gc,
6594 0, 0, TreeNilWd[sz], TreeNilHt[sz],
6597 if (empty_msg == NULL)
6598 empty_msg = XtNewString("(empty)");
6600 if (file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET)
6602 extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
6603 font_yoffset = extents->max_logical_extent.y;
6604 font_height = extents->max_logical_extent.height;
6608 font_yoffset = file_mgr_data->cd_font->ascent;
6609 font_height = file_mgr_data->cd_font->ascent +
6610 file_mgr_data->cd_font->descent;
6613 XDrawImageString(XtDisplay(w), XtWindow(w), solid_gc,
6614 xl + TreeNilWd[sz] + 2,
6615 y1 + (TreeNilHt[sz] - font_height)/2 + font_yoffset,
6616 empty_msg, strlen(empty_msg));
6621 /* goto next item */
6627 /************************************************************************
6630 * Check if any incons or widgets in the area given by ex, ey, ewd,
6631 * and eht need to be updated.
6633 ************************************************************************/
6636 static int g_workCount1 = 0;
6637 static int g_workCount2 = 0;
6638 static int g_callCount = 0;
6643 IconLayoutData *layout_data,
6644 FileViewData *file_view_data)
6648 for (i = 0; i < layout_data->manage_count; i++)
6649 if (layout_data->manage[i] == file_view_data->widget)
6658 FileMgrRec *file_mgr_rec,
6659 FileMgrData *file_mgr_data,
6660 int ex, int ey, int ewd, int eht,
6664 #ifdef DT_PERFORMANCE
6665 struct timeval update_time_s;
6666 struct timeval update_time_f;
6668 XmManagerWidget file_window;
6669 FileViewData **order_list;
6672 Arg args_dso_get[1];
6673 Arg args_dso_set[1];
6674 IconLayoutData *layout_data;
6675 FileViewData **change;
6681 Dimension grid_width, grid_height;
6682 Dimension icon_width, icon_height;
6683 Dimension extra_height;
6686 FileViewData *file_view_data;
6691 unsigned char operations;
6693 ObjectPosition *position_data;
6694 XRectangle textExtent;
6696 /* Get a list of icon and button widgets we can re-use */
6697 file_window = (XmManagerWidget) file_mgr_rec->file_window;
6698 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
6699 order_list = layout_data->order_list;
6700 order_count = layout_data->order_count;
6701 manage = layout_data->manage + layout_data->manage_count;
6703 /* allocate storage for list of changed icons */
6704 change = (FileViewData **)XtMalloc(order_count * sizeof(FileViewData *));
6706 /* Find the maximum values for the icon heights and widths */
6707 grid_width = file_mgr_data->grid_width;
6708 grid_height = file_mgr_data->grid_height;
6711 #ifdef DT_PERFORMANCE
6712 printf(" Begin Part 1, DisplaySomeIcons (update icons)\n");
6713 gettimeofday(&update_time_s, NULL);
6716 _DtPerfChkpntMsgSend("Begin Display Icons");
6720 "DisplaySomeIcons(\"%s\", x/y %d/%d, wd/ht %d/%d, i %d:%d) ...\n",
6721 file_mgr_data->current_directory, ex, ey, ewd, eht,
6722 layout_data->i_do_next_vis,
6723 layout_data->i_do_next_all));
6725 /* set up args for querying/unregistering drop sites */
6726 XtSetArg (args_dso_get[0], XmNdropSiteOperations, &operations);
6727 XtSetArg (args_dso_set[0], XmNdropSiteOperations, XmDROP_NOOP);
6730 * Iterate through the list of files and create/update and position
6731 * all visible icon gadgets for which this work hasn't been done yet
6732 * (need_update flag set).
6740 k = layout_data->i_do_next_all;
6742 k = layout_data->i_do_next_vis;
6743 for ( ; k < order_count && workCount1 < workLimit; k++)
6746 * Process focus widget before everything else so that we can restore
6747 * the focus when we manage the file_window again. If a file was
6748 * being renamed, we do that one first.
6750 if (!layout_data->focus_done)
6752 /* search for focus widget in order_list and see if still displayed */
6753 file_view_data = NULL;
6754 if (file_mgr_rec->focus_widget != NULL)
6756 if (file_mgr_rec->focus_widget == file_mgr_rec->file_window)
6758 for (i = 0; i < order_count; i++)
6759 if (order_list[i]->displayed)
6761 file_view_data = order_list[i];
6767 for (i = 0; i < order_count; i++)
6768 if (order_list[i]->widget == file_mgr_rec->focus_widget)
6770 if (order_list[i]->displayed)
6771 file_view_data = order_list[i];
6777 /* if not found, focus could be on a rename text widget */
6778 if (file_view_data == NULL)
6779 file_view_data = file_mgr_data->renaming;
6781 layout_data->focus_done = True;
6786 /* decrement loop index, so that the entry that was supposed to be
6787 processed here will be looked at again in the next iteration
6794 /* ignore files that are filtered */
6795 file_view_data = order_list[k];
6796 if (file_view_data->filtered &&
6797 strcmp(file_view_data->file_data->file_name, ".") != 0)
6803 * If the file is not currenly displayed (collapsed tree branch) or
6804 * is currenly scrolled out of view, we don't need to do anything
6805 * at this time. Except ...
6807 if (!file_view_data->displayed ||
6808 ((int)file_view_data->x + (int)grid_width) < ex ||
6809 file_view_data->x >= ex + ewd ||
6810 file_view_data->y < ey ||
6811 ((int)file_view_data->y - (int)grid_height) >= (ey + eht))
6814 * ... if this file still has an old icon widget, AND if the
6815 * old icon position is visible, AND if the icon was registered
6816 * as a drop site, we will have a "ghost drop zone" showing up where
6817 * the icon used to be. The old icon gadget is unmanaged and will
6818 * remain unmanaged until later when we update it and move it to the
6819 * correct positon (happens only when the user scrolls to the new
6820 * position). In the meantime, even though the gadget is unmanged,
6821 * its old position still remains registered as a drop site,
6822 * so we have to either unregister it or move the gadget to
6823 * its new position now.
6825 child = file_view_data->widget;
6826 if (child != NULL &&
6827 (Position)(child->core.x + child->core.width) >= (Position)ex &&
6828 child->core.x < ex + ewd &&
6829 (Position)(child->core.y + child->core.height) >= (Position)ey &&
6830 child->core.y < ey + eht)
6832 if (!file_view_data->displayed)
6834 XtGetValues (child, args_dso_get, 1);
6835 if (operations != XmDROP_NOOP)
6837 XtSetValues (child, args_dso_set, 1);
6839 file_view_data->registered = False;
6850 * If not yet done, create/update the icon gadget for this file
6852 if (file_view_data->need_update)
6854 UpdateOneFileIcon(file_mgr_rec, file_mgr_data, file_view_data);
6855 child = file_view_data->widget;
6858 * We may need to adjust the icon position based on the difference
6859 * between estimated size and actual size.
6861 if (layout_data->alignment == XmALIGNMENT_CENTER &&
6862 file_mgr_data->view == BY_NAME_AND_ICON)
6864 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data,
6865 file_view_data, &icon_width, &icon_height);
6867 if (child->core.width != icon_width)
6869 file_view_data->x = file_view_data->x
6870 - (Dimension)(grid_width - icon_width)/(Dimension)2
6871 + (Dimension)(grid_width - child->core.width)/(Dimension)2;
6875 if (PositioningEnabledInView(file_mgr_data))
6877 position_data = file_view_data->position_info;
6878 if (position_data->late_bind)
6881 * When new objects are dropped on the random placement window,
6882 * they do not yet have a widget, so the drop_y could not be
6883 * adjusted to take into account the height of the icon;
6884 * this must be done now, after the object has an icon.
6887 position_data->y -= child->core.height/2;
6889 position_data->late_bind = False;
6890 file_view_data->y = position_data->y + child->core.height;
6892 else if (child->core.height != grid_height)
6895 * Not quite right: have to distinguish two cases:
6896 * (1) position_data->y read from .!xxx file
6897 * file_view_data->y computed by adding grid_height
6898 * (2) file_view_data->y from layout
6899 * position_data->y computed by subtracting grid_height
6900 * In case (1) have to recompute file_view_data->y; in case
6901 * (2) have to recompute position_data->y. Code below only
6902 * works for case (2).
6905 position_data->y = file_view_data->y - child->core.height;
6916 /* if focus is supposed to be in the file window, focus on this widget */
6917 if (file_mgr_rec->focus_widget == file_mgr_rec->file_window)
6918 file_mgr_rec->focus_widget = file_view_data->widget;
6921 /* determine desired icon postition */
6922 child = file_view_data->widget;
6924 if (PositioningEnabledInView(file_mgr_data))
6926 x = file_view_data->position_info->x;
6927 y = file_view_data->position_info->y;
6929 else if (file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6931 x = file_view_data->x;
6932 y = file_view_data->y - child->core.height;
6934 else /* file_mgr_data->show_type == MULTIPLE_DIRECTORY */
6936 GetLevel(file_view_data, &level);
6937 extra_height = GetExtraHeight(file_mgr_data, file_view_data,
6938 layout_data->treebtn_size);
6940 /* check position of tree button, if any */
6941 if (file_view_data->treebtn)
6943 child = file_view_data->treebtn;
6945 x = file_view_data->x
6946 + TreeLX(level, layout_data->treebtn_size) + TreeOffset;
6947 y = file_view_data->y
6949 + (Dimension)(grid_height - child->core.height)/(Dimension)2;
6951 if (child->core.x != x || child->core.y != y)
6952 XmeConfigureObject(child, x, y, child->core.width,
6953 child->core.height, child->core.border_width);
6955 child = file_view_data->widget;
6958 if (child->core.height < grid_height)
6960 x = file_view_data->x + TreeWd(level, layout_data->treebtn_size);
6961 y = file_view_data->y
6963 +(Dimension)(grid_height - child->core.height)/(Dimension)2;
6967 x = file_view_data->x + TreeWd(level, layout_data->treebtn_size);
6968 y = file_view_data->y - grid_height;
6972 if (child->core.x != x || child->core.y != y)
6974 XmeConfigureObject(child, x, y, child->core.width,
6975 child->core.height, child->core.border_width);
6979 /* make sure the icon gadget and tree button, if any, are managed */
6980 if (!XtIsManaged(child) && !ToBeManaged(layout_data, file_view_data))
6982 manage[manageCount++] = child;
6983 if (file_view_data->treebtn)
6984 manage[manageCount++] = file_view_data->treebtn;
6990 /* remember which icons were changed */
6991 change[changeCount++] = file_view_data;
6995 * If the icon we just changed was being renamed, make sure
6996 * the corresponding text widget is positioned correctly.
6998 if (file_view_data == file_mgr_data->renaming)
7000 for (i = 0; i < file_window->composite.num_children; i++)
7002 child = file_window->composite.children[i];
7003 if (XmIsTextField(child))
7005 /* Check if the text field is still needed */
7006 if (!child->core.being_destroyed)
7008 /* move to the correct position */
7009 _DtIconGetTextExtent_r(file_view_data->widget,
7013 (Dimension)(child->core.height - textExtent.height)/(Dimension)2;
7014 XmeConfigureObject(child, x, y, child->core.width,
7016 child->core.border_width);
7019 manage[manageCount++] = child;
7028 /* remember where we left off ... */
7030 layout_data->i_do_next_all = k;
7032 layout_data->i_do_next_vis = k;
7034 #ifdef DT_PERFORMANCE
7035 gettimeofday(&update_time_f, NULL);
7036 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7037 update_time_f.tv_usec += 1000000;
7038 update_time_f.tv_sec--;
7040 printf(" done Part 1, DisplaySomeIcons, time: %ld.%ld\n\n",
7041 update_time_f.tv_sec - update_time_s.tv_sec,
7042 update_time_f.tv_usec - update_time_s.tv_usec);
7044 /* the following message send call added by Rafi */
7045 _DtPerfChkpntMsgSend("Done Display Icons");
7048 #ifdef DT_PERFORMANCE
7049 printf(" Begin Part 2, DisplaySomeIcons (register drop sites)\n");
7050 gettimeofday(&update_time_s, NULL);
7053 _DtPerfChkpntMsgSend("Begin Register drop sites");
7056 /* unregister drop sites of unused icon gadgets */
7058 #ifdef DELAYED_UNREGISTER
7059 for (wp = layout_data->next_icon_to_use;
7060 (child = *wp) != NULL;
7063 if ((Position)(child->core.x + child->core.width) >= (Position)ex &&
7064 child->core.x < ex + ewd &&
7065 (Position)(child->core.y + child->core.height) >= (Position)ey &&
7066 child->core.y < ey + eht)
7068 XtGetValues (child, args_dso_get, 1);
7069 if (operations != XmDROP_NOOP)
7071 XtSetValues (child, args_dso_set, 1);
7074 if (workCount2/2 >= workLimit)
7082 * Register drop sites
7084 * Note: in "as placed" mode, we defer this work and do it in
7085 * CommitWorkProcUpdates instead. Reason: need to re-register
7086 * all drop sites in top-to-bottom stacking order at that time.
7088 if (! PositioningEnabledInView(file_mgr_data) &&
7089 file_mgr_data != trashFileMgrData)
7091 for (k = 0; k < changeCount; k++)
7093 SetHotRects(change[k],
7094 (XtCallbackProc) DropOnObject,
7095 (XtPointer) change[k]);
7100 XtFree((char *)change);
7103 /* update count of children to be managed */
7104 layout_data->manage_count += manageCount;
7107 #ifdef DT_PERFORMANCE
7108 gettimeofday(&update_time_f, NULL);
7109 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7110 update_time_f.tv_usec += 1000000;
7111 update_time_f.tv_sec--;
7113 printf(" done Part 2 DisplaySomeIcons, time: %ld.%ld\n\n",
7114 update_time_f.tv_sec - update_time_s.tv_sec,
7115 update_time_f.tv_usec - update_time_s.tv_usec);
7117 /* the following message send call added by Rafi */
7118 _DtPerfChkpntMsgSend("Done Register drop sites");
7121 DPRINTF2((" ... %d+%d changed (%d managed)\n",
7122 workCount1, workCount2, manageCount));
7125 g_workCount1 += workCount1;
7126 g_workCount2 += workCount2;
7130 return (workCount1 >= workCount2)? workCount1: workCount2;
7134 /************************************************************************
7136 * Display work procedure
7138 ************************************************************************/
7141 CommitWorkProcUpdates(
7142 FileMgrRec *file_mgr_rec,
7143 FileMgrData * file_mgr_data,
7146 XmManagerWidget file_window;
7147 IconLayoutData *layout_data;
7151 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7152 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7154 if (layout_data == NULL)
7158 "CommitWorkProcUpdates: %d+%d updates (m %d, n %d, i %d:%d, reset %d)\n",
7161 layout_data->manage_count,
7163 layout_data->i_do_next_vis,
7164 layout_data->i_do_next_all,
7175 layout_data->i_do_next_vis = 0;
7176 layout_data->i_do_next_all = 0;
7179 /* if work proc no longer active, everything should already be commited */
7180 if (layout_data->work_id == 0)
7183 /* manage new children */
7184 if (layout_data->manage_count > 0)
7186 if (PositioningEnabledInView(file_mgr_data))
7187 OrderChildrenList(file_mgr_data);
7188 XtManageChildren(layout_data->manage, layout_data->manage_count);
7192 * In "as placed" mode, need to register drop sites now.
7193 * (If not "as placed" mode, this was already done in DisplaySomeIcons.)
7195 if (PositioningEnabledInView(file_mgr_data))
7196 RegisterDesktopHotspots(file_mgr_data, file_mgr_rec);
7198 /* commit drop site updates */
7199 XmDropSiteEndUpdate(layout_data->drop_site_w);
7201 /* If not managed yet, manage the file window again */
7202 if (!XtIsManaged((Widget)file_window))
7207 XtManageChild ((Widget)file_window);
7208 XtVaGetValues(file_mgr_rec->vertical_scroll_bar,XmNuserData,&incr,NULL);
7209 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7210 file_mgr_rec->scroll_window)
7213 XtSetArg (args[0], XmNincrement,incr);
7214 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 1);
7216 XmUpdateDisplay ((Widget)file_window);
7219 /* Try to preserve the focus */
7220 if (file_mgr_rec->focus_widget)
7222 /* see if the widget that previously had the focus was just managed */
7224 for (i = 0; i < layout_data->manage_count; i++)
7226 if (layout_data->manage[i] == file_mgr_rec->focus_widget)
7228 w = file_mgr_rec->focus_widget;
7233 /* if focus widget not found, set focus on file_window */
7235 w = (Widget)file_window;
7237 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
7239 file_mgr_rec->focus_widget = NULL;
7242 layout_data->manage_count = 0;
7244 /* start new update */
7245 XmDropSiteStartUpdate(layout_data->drop_site_w);
7251 XtPointer client_data)
7253 FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
7254 DialogData * dialog_data;
7255 FileMgrData * file_mgr_data;
7256 XmManagerWidget file_window;
7257 IconLayoutData *layout_data;
7258 int ex, ey, ewd, eht;
7259 ObjectPosition *bottom;
7262 Boolean commit_updates = False;
7267 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
7268 if (dialog_data == NULL)
7271 file_mgr_data = (FileMgrData *) dialog_data->data;
7272 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7273 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7275 /* get the position and size of the currently visible area */
7276 ex = -file_window->core.x;
7277 ey = -file_window->core.y;
7278 ewd = XtParent(file_window)->core.width;
7279 eht = XtParent(file_window)->core.height;
7281 /* check if the window scrolled */
7282 if (ex != layout_data->ex || ey != layout_data->ey)
7284 layout_data->i_do_next_vis = layout_data->i_do_next_all;
7285 layout_data->visible_done = False;
7288 /* first work on icons in the currently visible area */
7289 if (layout_data->visible_done)
7293 n = DisplaySomeIcons(file_mgr_rec, file_mgr_data, ex, ey, ewd, eht, n1, False);
7296 /* we just finished updating all visible icons */
7297 DPRINTF(("DisplayWorkProc: visible done.\n"));
7298 layout_data->visible_done = True;
7299 commit_updates = True;
7303 /* if we still have some time left, work on other icons */
7304 if (layout_data->visible_done && n < n2)
7306 n = DisplaySomeIcons(file_mgr_rec, file_mgr_data,
7307 0, 0, 32767, 32767, n2 - n, True);
7309 /* check if we are done */
7312 layout_data->all_done = True;
7313 commit_updates = True;
7315 else if (layout_data->manage_count >= 100)
7316 commit_updates = True;
7321 /* manage new children and commit drop site updates */
7322 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, False);
7325 * In "as placed" mode, icons may overlap.
7326 * Force redraw in bottom to top stacking order.
7328 if (PositioningEnabledInView(file_mgr_data))
7330 for (bottom = GetBottomOfStack(file_mgr_data);
7332 bottom = (ObjectPosition *)bottom->prev)
7334 if (bottom->file_view_data != NULL &&
7335 bottom->file_view_data->displayed &&
7336 !bottom->file_view_data->need_update)
7338 child = bottom->file_view_data->widget;
7339 if ((Position)(child->core.x + child->core.width) >= (Position)ex &&
7340 child->core.x < ex + ewd &&
7341 (Position)(child->core.y + child->core.height) >= (Position)ey &&
7342 child->core.y < ey + eht)
7344 RedrawOneGadget(child, NULL, NULL);
7351 if (layout_data->all_done)
7353 /* all work is done; all icons are up-to-date */
7354 file_mgr_data->newSize = False;
7355 layout_data->work_id = 0;
7356 XmDropSiteEndUpdate(layout_data->drop_site_w);
7358 DPRINTF(("DisplayWorkProc: all done.\n"));
7360 /* returning True will end the work proc */
7365 /* remember current scroll position */
7366 layout_data->ex = ex;
7367 layout_data->ey = ey;
7373 /************************************************************************
7376 * Position and size the full set of icons for the file mgr data.
7378 ************************************************************************/
7382 FileMgrRec *file_mgr_rec,
7383 FileMgrData *file_mgr_data,
7384 Boolean update_scrolling_position,
7385 Boolean turn_off_hourglass )
7387 #ifdef DT_PERFORMANCE
7388 struct timeval update_time_s;
7389 struct timeval update_time_f;
7391 XmManagerWidget file_window;
7392 FileViewData ** order_list;
7394 int total_icon_count;
7395 IconLayoutData *layout_data;
7396 Dimension file_window_width, file_window_height;
7397 Dimension scrolled_window_width, scrolled_window_height;
7398 Dimension vert_scrollbar_width, horiz_scrollbar_height;
7399 Dimension grid_width, grid_height;
7400 Dimension icon_width, icon_height;
7401 Dimension extra_height;
7402 Dimension sw_shadow_thickness, sb_highlight_thickness, space;
7404 int level, max_level;
7405 FileViewData *file_view_data;
7406 Boolean overflow = False;
7415 unsigned char operations = 0L;
7416 static XtCallbackRec dropCB[] = { {DropOnFileWindow, NULL}, {NULL, NULL} };
7419 /* if directory-read still in progress, don't do anything now */
7420 if (file_mgr_data->busy_status != not_busy)
7423 DPRINTF(("LayoutFileIcons(\"%s\", u_s_p %c, t_o_h %c) ...\n",
7424 file_mgr_data->current_directory,
7425 update_scrolling_position? 'T': 'F',
7426 turn_off_hourglass? 'T': 'F'));
7428 #ifdef DT_PERFORMANCE
7429 printf(" Begin LayoutFileIcons\n");
7430 gettimeofday(&update_time_s, NULL);
7433 _DtPerfChkpntMsgSend("Begin Layout Icons");
7437 * Just in case a previous update work proc is still active,
7438 * we commit pending updates made by the work proc before we
7439 * start making changes.
7441 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, True);
7443 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7444 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7446 fileType = GetDirectoryLogicalType(file_mgr_data,
7447 file_mgr_data->current_directory);
7448 operations = TypeToDropOperations(fileType);
7450 if (!file_mgr_data->dropSite)
7452 dropCB[0].closure = (XtPointer)file_mgr_data;
7454 DtDndVaDropRegister((Widget)file_mgr_rec->file_window,
7455 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
7458 DtNdropAnimateCallback, dropCB,
7459 DtNregisterChildren, True,
7460 DtNtextIsBuffer, True,
7461 XmNanimationStyle, XmDRAG_UNDER_SHADOW_IN,
7463 file_mgr_data->dropSite = True;
7467 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
7468 XmDropSiteUpdate((Widget)file_mgr_rec->file_window, args, 1);
7474 XtSetArg (args[0], XmNdropSiteOperations, operations);
7476 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
7477 XmDropSiteUpdate((Widget)file_mgr_rec->file_window, args, 1);
7480 /* Get the count of the total icon to be displayed. */
7481 order_list = layout_data->order_list;
7482 order_count = layout_data->order_count;
7483 total_icon_count = 0;
7484 for (i = 0; i < order_count; i++)
7486 if (order_list[i]->displayed)
7490 /* Get the colors to be used for drawing the icons */
7491 XtSetArg (args[0], XmNbackground, &layout_data->background);
7492 XtSetArg (args[1], XmNforeground, &layout_data->foreground);
7494 XtSetArg (args[2], XmNtopShadowColor, &layout_data->topshadow);
7495 XtGetValues (file_mgr_rec->file_window, args, 3);
7497 XtGetValues (file_mgr_rec->file_window, args, 2);
7499 XtSetArg (args[0], XmNtopShadowColor, &layout_data->pixmap_back);
7500 XtSetArg (args[1], XmNbottomShadowColor, &layout_data->pixmap_fore);
7501 XtGetValues (file_mgr_rec->main, args, 2);
7504 * Create/update icon gadget for ".".
7505 * This gadget may not actually be displayed (depends of filter settings;
7506 * by default it is filtered out), but we need at least one gadget
7507 * created here so we can figure out fonts and margins used by icon
7508 * gadgets. This is necessary to compute the grid spacing.
7510 for (i = 0; i < order_count; i++)
7511 if (strcmp(order_list[i]->file_data->file_name, ".") == 0)
7513 UpdateOneFileIcon(file_mgr_rec, file_mgr_data, order_list[i]);
7514 order_list[i]->need_update = True;
7518 /* Find the icon with the longest label */
7520 file_view_data = NULL;
7521 for (i = 0; i < order_count; i++)
7523 if (!order_list[i]->filtered &&
7524 (len = strlen(order_list[i]->label)) > max_len)
7526 file_view_data = order_list[i];
7531 /* get the size of the icon with the longest label */
7532 GetIconLayoutParms(file_mgr_rec, file_mgr_data, layout_data);
7533 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data, file_view_data,
7534 &grid_width, &grid_height);
7536 /* for tree view add space for tree lines and buttons */
7538 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
7540 for (i = 0; i < order_count; i++)
7542 if (order_list[i]->displayed)
7544 GetLevel(order_list[i], &level);
7545 if (level > max_level)
7549 grid_width += TreeWd(max_level, layout_data->treebtn_size);
7552 file_mgr_data->grid_height = grid_height;
7553 file_mgr_data->grid_width = grid_width;
7556 * If positioning is enabled in this view, then we need to use the other
7557 * layout function, which is capable of handling overlapping icons and
7560 if (PositioningEnabledInView(file_mgr_data))
7562 if (file_mgr_data->object_positions)
7564 LayoutDesktopIcons(file_mgr_rec, file_mgr_data,
7565 order_list, order_count, turn_off_hourglass);
7566 /* RepairFileWindow(file_mgr_data); *OBSOLETE* */
7572 * Position and size the icons according to the show and view types.
7575 scrolled_window_width = file_mgr_rec->scroll_window->core.width;
7576 scrolled_window_height = file_mgr_rec->scroll_window->core.height;
7577 vert_scrollbar_width = file_mgr_rec->vertical_scroll_bar->core.width;
7578 horiz_scrollbar_height = file_mgr_rec->horizontal_scroll_bar->core.height;
7580 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
7582 /* if not yet done, create tree button icons */
7583 if (TreeBtnWd[0] == 0)
7584 CreateTreeIcons(file_mgr_rec->file_window);
7586 /* layout for tree mode */
7589 file_window_width = MARGIN + grid_width - TreeOffset + XSPACING;
7591 for (k = 0; k < order_count; k++)
7593 if (!order_list[k]->displayed)
7596 /* make sure window height won't exceed limit */
7597 extra_height = GetExtraHeight(file_mgr_data, order_list[k],
7598 layout_data->treebtn_size);
7599 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
7600 if (tmp + MARGIN > MAXWINSIZE)
7602 /* window would exceed height limit; start a new column */
7603 x += grid_width + XSPACING;
7605 file_window_width += grid_width + XSPACING;
7606 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
7610 order_list[k]->x = x;
7611 order_list[k]->y = y + grid_height;
7618 file_window_height = MAXWINSIZE;
7620 file_window_height = y + MARGIN;
7622 else if (file_mgr_data->view == BY_ATTRIBUTES)
7624 /* layout for details view, no tree mode */
7627 file_window_width = 2*MARGIN + grid_width;
7629 for (k = 0; k < order_count; k++)
7631 if (!order_list[k]->displayed)
7634 /* make sure window height won't exceed limit */
7635 tmp = (int)y + grid_height + YSPACING(file_mgr_data);
7636 if (tmp + MARGIN > MAXWINSIZE)
7638 /* window would exceed height limit; start a new column */
7639 x += grid_width + XSPACING;
7641 file_window_width += grid_width + XSPACING;
7642 tmp = (int)y + grid_height + YSPACING(file_mgr_data);
7646 order_list[k]->x = x;
7647 order_list[k]->y = y + grid_height;
7654 file_window_height = MAXWINSIZE;
7656 file_window_height = y + MARGIN;
7658 else /* show_type == SINGLE_DIRECTORY, view != BY_ATTRIBUTES */
7660 /* layout for "normal" views (no tree mode, no details) */
7662 /* calculate how many columns fit in the window width */
7663 column_count = ((int)scrolled_window_width - 4 - 2*MARGIN + XSPACING) /
7664 ((int)grid_width + XSPACING);
7665 if (column_count == 0)
7666 column_count = 1; /* need at least one column */
7669 * Calculate the window height. Need to do calculation in int's
7670 * rather than short (Dimension) because of possible overflow.
7672 row_count = (total_icon_count + column_count - 1) / column_count;
7673 tmp = 2*MARGIN - YSPACING(file_mgr_data) +
7674 row_count * ((int)grid_height + YSPACING(file_mgr_data));
7676 /* check if the height is larger than the scrolled window */
7677 if (tmp >= (int)scrolled_window_height - 2*MARGIN)
7679 /* need to recompute everything because of space for vert scrollbar */
7680 column_count = ((int)scrolled_window_width - 4 - 2*MARGIN + XSPACING
7681 - (int)vert_scrollbar_width)
7682 / ((int)grid_width + XSPACING);
7683 if (column_count == 0)
7685 row_count = (total_icon_count + column_count - 1) / column_count;
7686 tmp = 2*MARGIN - YSPACING(file_mgr_data) +
7687 row_count * ((int)grid_height + YSPACING(file_mgr_data));
7690 /* check if the window height is within the limit */
7691 if (tmp <= MAXWINSIZE)
7692 file_window_height = (Dimension)tmp;
7695 /* window height too large; use more columns */
7697 row_count = (int)(MAXWINSIZE - 2*MARGIN + YSPACING(file_mgr_data)) /
7698 (int)((int)grid_height + YSPACING(file_mgr_data));
7699 column_count = (total_icon_count + row_count - 1) / row_count;
7700 row_count = (total_icon_count + column_count - 1) / column_count;
7701 file_window_height = (Dimension) (2*MARGIN - YSPACING(file_mgr_data) +
7702 row_count * ((int)grid_height + YSPACING(file_mgr_data)));
7705 DPRINTF((" %d columns, %d rows (scroll_window width %d)\n",
7706 column_count, row_count,
7707 scrolled_window_width));
7709 /* assign positions to all icons */
7711 file_window_width = (Dimension)
7712 (2*MARGIN - XSPACING + column_count*((int)grid_width + XSPACING));
7715 for (i = 0; i < row_count; i++)
7719 for (j = 0; j < column_count && k < order_count;)
7721 /* find the next icon to display */
7722 while (k < order_count && !order_list[k]->displayed)
7724 if (k == order_count)
7727 if (layout_data->alignment == XmALIGNMENT_CENTER &&
7728 file_mgr_data->view == BY_NAME_AND_ICON)
7730 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data,
7731 order_list[k], &icon_width, &icon_height);
7732 order_list[k]->x = x +
7733 (Dimension)(grid_width - icon_width)/(Dimension)2;
7736 order_list[k]->x = x;
7737 order_list[k]->y = y + grid_height;
7739 x += grid_width + XSPACING;
7744 y += grid_height + YSPACING(file_mgr_data);
7748 DPRINTF((" file_window size: width %d, height %d\n",
7749 file_window_width, file_window_height));
7751 /* Manage/unmanage the scrollbars as needed. */
7753 XtSetArg (args[0], XmNwidth, file_window_width);
7754 XtSetArg (args[1], XmNheight, file_window_height);
7755 XtSetValues ((Widget)file_window, args, 2);
7757 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
7758 XtSetValues (file_mgr_rec->scroll_window, args, 1);
7761 /* Unmanage the horizontal scrollbar if it is not needed */
7762 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7763 file_mgr_rec->scroll_window))
7765 if (file_window_width >= (Dimension)(scrolled_window_width - 4 -
7766 vert_scrollbar_width))
7767 XtManageChild (file_mgr_rec->horizontal_scroll_bar);
7770 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
7771 XtSetArg (args[0], XmNx, 0);
7772 XtSetValues ((Widget)file_window, args, 1);
7775 else if (file_window_width >= (Dimension)(scrolled_window_width - 4))
7776 XtManageChild (file_mgr_rec->horizontal_scroll_bar);
7779 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
7780 XtSetArg (args[0], XmNx, 0);
7781 XtSetValues ((Widget)file_window, args, 1);
7784 XSync (XtDisplay (file_window), False);
7786 /* Set the file window width and height to be at least */
7787 /* the size of the scrolled window. */
7789 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7790 file_mgr_rec->scroll_window))
7792 if(file_window_width <= (Dimension)(scrolled_window_width -
7793 (vert_scrollbar_width + 4)))
7795 file_window_width = scrolled_window_width -
7796 (vert_scrollbar_width + 4);
7800 if(file_window_width < (Dimension)(scrolled_window_width - 4))
7801 file_window_width = scrolled_window_width - 4;
7804 if (HorizontalScrollbarIsVisible(file_mgr_rec->horizontal_scroll_bar,
7805 file_mgr_rec->scroll_window))
7809 XtSetArg (args[0], XmNhighlightThickness, &sb_highlight_thickness);
7810 XtGetValues ((Widget)file_mgr_rec->horizontal_scroll_bar, args, 1);
7812 XtSetArg (args[0], XmNshadowThickness, &sw_shadow_thickness);
7813 XtSetArg (args[1], XmNspacing, &space);
7814 XtGetValues ((Widget)file_mgr_rec->scroll_window, args, 2);
7816 pad = (int)(((sb_highlight_thickness + sw_shadow_thickness) * 2) + space);
7818 if(file_window_height < (Dimension)(scrolled_window_height -
7819 (horiz_scrollbar_height + pad)))
7820 file_window_height = scrolled_window_height -
7821 (horiz_scrollbar_height + pad);
7825 if (file_window_height < (Dimension)(scrolled_window_height - 4))
7826 file_window_height = scrolled_window_height - 4;
7830 XtSetArg (args[0], XmNwidth, file_window_width);
7831 XtSetArg (args[1], XmNheight, file_window_height);
7832 XtSetValues ((Widget)file_window, args, 2);
7834 if( file_mgr_data->scrollToThisFile == NULL )
7836 if (update_scrolling_position)
7838 XtSetArg (args[0], XmNx, 0);
7839 XtSetArg (args[1], XmNy, 0);
7840 XtSetValues ((Widget)file_window, args, 2);
7843 /* Set the vertical scrollbar's increment to icon height */
7844 XtSetArg (args[0], XmNincrement, grid_height + YSPACING(file_mgr_data));
7845 XtSetArg (args[1], XmNuserData, grid_height + YSPACING(file_mgr_data));
7846 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 2);
7849 if (PositioningEnabledInView(file_mgr_data))
7851 BuildObjectPositions(file_mgr_data);
7852 /* RepairFileWindow(file_mgr_data); *OBSOLETE* */
7856 * Don't keep up the hourglass; this helps the user to get the impression
7857 * that all of the work is done.
7859 if (turn_off_hourglass && !overflow)
7860 _DtTurnOffHourGlass(file_mgr_rec->shell);
7867 * Start up a work proc that will update the display.
7869 layout_data->visible_done = False;
7870 layout_data->all_done = False;
7871 if (layout_data->work_id == 0)
7873 XtAppContext app_context =
7874 XtWidgetToApplicationContext(file_mgr_rec->shell);
7876 DPRINTF(("LayoutFileIcons: starting workproc\n"));
7877 layout_data->drop_site_w = (Widget)file_mgr_rec->shell;
7878 XmDropSiteStartUpdate(layout_data->drop_site_w);
7880 layout_data->work_id =
7881 XtAppAddWorkProc(app_context, DisplayWorkProc, file_mgr_rec);
7885 if( file_mgr_data->scrollToThisFile )
7888 DirectorySet * directory_set = NULL;
7890 file_view_data = NULL;
7892 for( i = 0; i < file_mgr_data->directory_count; ++i)
7894 if( strcmp( ((DirectorySet *)file_mgr_data->directory_set[i])->name, file_mgr_data->scrollToThisDirectory ) == 0 )
7896 directory_set = (DirectorySet *)file_mgr_data->directory_set[i];
7903 for( i = 0; i < directory_set->file_count; ++i )
7905 if( strcmp( directory_set->order_list[i]->file_data->file_name,
7906 file_mgr_data->scrollToThisFile ) == 0 )
7908 file_view_data = directory_set->order_list[i];
7915 && file_view_data->filtered == False )
7917 FileMgrRec * file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
7919 DeselectAllFiles( file_mgr_data );
7920 SelectFile( file_mgr_data, file_view_data );
7921 ActivateSingleSelect( file_mgr_rec,
7922 file_mgr_data->selection_list[0]->file_data->logical_type );
7924 PositionFileView(file_view_data, file_mgr_data);
7928 if (update_scrolling_position)
7930 XtSetArg (args[0], XmNx, 0);
7931 XtSetArg (args[1], XmNy, 0);
7932 XtSetValues ((Widget)file_window, args, 2);
7935 /* Set the vertical scrollbar's increment to icon height */
7936 XtSetArg (args[0], XmNincrement, grid_height + YSPACING(file_mgr_data));
7937 XtSetArg (args[1], XmNuserData, grid_height + YSPACING(file_mgr_data));
7938 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 2);
7941 XtFree( file_mgr_data->scrollToThisFile );
7942 file_mgr_data->scrollToThisFile = NULL;
7943 XtFree( file_mgr_data->scrollToThisDirectory );
7944 file_mgr_data->scrollToThisDirectory = NULL;
7947 #ifdef DT_PERFORMANCE
7948 gettimeofday(&update_time_f, NULL);
7949 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7950 update_time_f.tv_usec += 1000000;
7951 update_time_f.tv_sec--;
7953 printf(" done LayoutFileIcons, time: %ld.%ld\n\n",
7954 update_time_f.tv_sec - update_time_s.tv_sec,
7955 update_time_f.tv_usec - update_time_s.tv_usec);
7957 /* the following message send call added by Rafi */
7958 _DtPerfChkpntMsgSend("Done LayoutFileIcons");
7961 DPRINTF(("... done\n"));
7966 /************************************************************************
7969 * Callback function invoked upon clicking the tree-branch-expand button.
7971 ************************************************************************/
7976 XtPointer clientData,
7977 XmAnyCallbackStruct *callData )
7979 FileMgrRec *file_mgr_rec;
7980 FileMgrData *file_mgr_data;
7981 FileViewData *file_view_data = (FileViewData *)clientData;
7985 /* check which mouse button was pressed */
7986 if ((callData->event->type == ButtonPress ||
7987 callData->event->type == ButtonRelease) &&
7988 ((XButtonEvent *)callData->event)->button != Button1)
7994 /* get file mgr data and record */
7995 XtSetArg (args[0], XmNuserData, &file_mgr_data);
7996 XtGetValues (w, args, 1);
7997 file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
7999 XmDropSiteStartUpdate(file_mgr_rec->file_window);
8000 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, True);
8001 DirTreeExpand(file_mgr_data, file_view_data, expand);
8002 DrawCurrentDirectory (file_mgr_rec->current_directory,
8003 file_mgr_rec, file_mgr_data);
8004 LayoutFileIcons(file_mgr_rec, file_mgr_data, False, True);
8005 XmDropSiteEndUpdate(file_mgr_rec->file_window);
8006 RedrawTreeLines(file_mgr_rec->file_window,
8007 -file_mgr_rec->file_window->core.x,
8008 -file_mgr_rec->file_window->core.y,
8009 XtParent(file_mgr_rec->file_window)->core.width,
8010 XtParent(file_mgr_rec->file_window)->core.height,
8011 0, file_mgr_rec, file_mgr_data);
8016 * When a drop occurs on a File Manger window, which now
8017 * support random placement, what is dropped may not ultimately be what
8018 * is displayed. Since the dissolve transition effect has been disabled
8019 * for drops on the desktop, we can sometimes end up with garbage left on
8020 * the desktop. This function will attempt to clear up the leftover garbage,
8021 * by resetting all areas of the desktop which are not covered by an icon
8022 * to the background color for the file window.
8024 * This function is OBSOLETE (?).
8029 FileMgrData * file_mgr_data)
8032 FileMgrRec * file_mgr_rec;
8035 Region redrawRegion;
8040 XmManagerWidget file_window;
8045 file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
8046 file_window = (XmManagerWidget)file_mgr_rec->file_window;
8048 /* Initialize the clip region to that of the file window */
8051 rect.height = file_window->core.height;
8052 rect.width = file_window->core.width;
8053 clipList = XCreateRegion();
8054 XUnionRectWithRegion(&rect, clipList, clipList);
8056 /* Subtract out the hotspots associated with each icon */
8057 num_children = file_window->composite.num_children;
8058 children = file_window->composite.children;
8059 hotspot = XCreateRegion();
8061 for (i = 0; i < num_children; i++)
8063 if (XtIsManaged(children[i]) &&
8064 XtIsSubclass(children[i], dtIconGadgetClass))
8066 WidgetRectToRegion(file_mgr_data, children[i], hotspot);
8067 XSubtractRegion(clipList, hotspot, clipList);
8071 /* Create a GC for doing our drawing */
8072 mask = GCForeground;
8073 values.foreground = file_window->core.background_pixel;
8074 gc = XCreateGC(XtDisplay(file_window), XtWindow(file_window), mask, &values);
8075 XSetRegion(XtDisplay(file_window), gc, clipList);
8077 /* Restore the window */
8078 XFillRectangle(XtDisplay(file_window), XtWindow(file_window), gc, 0, 0,
8079 file_window->core.width, file_window->core.height);
8082 * Force all icons to redraw, since we are only able to repair the
8083 * areas where icons are not; the drop image may have extended onto
8084 * some of the icons.
8088 rect.height = file_window->core.height;
8089 rect.width = file_window->core.width;
8090 redrawRegion = XCreateRegion();
8091 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
8092 (*file_window->core.widget_class->core_class.expose)
8093 ((Widget)file_window, NULL, redrawRegion);
8096 XFreeGC(XtDisplay(file_window), gc);
8097 XDestroyRegion(clipList);
8098 XDestroyRegion(hotspot);
8099 XDestroyRegion(redrawRegion);
8106 * Compress the stacking order values, anytime an item is removed.
8110 CompressObjectList (
8111 ObjectPosition ** object_positions,
8117 for (i = 0; i < num_objects; i++)
8119 if (object_positions[i]->stacking_order > starting_index)
8120 object_positions[i]->stacking_order--;
8126 /************************************************************************
8128 * LayoutDesktopIcons
8129 * Position and size the full set of icons for the file mgr data.
8131 ************************************************************************/
8134 LayoutDesktopIcons (
8135 FileMgrRec * file_mgr_rec,
8136 FileMgrData * file_mgr_data,
8137 FileViewData ** order_list,
8139 Boolean turn_off_hourglass )
8142 XmManagerWidget file_window;
8143 int directory_count, largest_x, largest_y;
8144 int value, size, increment, page;
8145 Dimension current_wd;
8146 Dimension current_ht;
8147 Dimension file_window_width;
8148 Dimension grid_height;
8149 Dimension grid_width;
8150 FileViewData * object;
8151 ObjectPosition * position_data;
8152 ObjectPosition * bottom;
8155 Boolean set_size = False;
8161 /* Get the grid block size */
8162 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8163 grid_height = file_mgr_data->grid_height;
8164 grid_width = file_mgr_data->grid_width;
8166 file_window_width = file_mgr_rec->scroll_window->core.width - 4;
8167 current_ht = file_mgr_rec->file_window->core.height;
8168 current_wd = file_mgr_rec->file_window->core.width;
8171 /* Before positioning, mark all position entries as 'not used' */
8172 for (i = 0; i < file_mgr_data->num_objects; i++)
8174 file_mgr_data->object_positions[i]->in_use = False;
8175 file_mgr_data->object_positions[i]->file_view_data = NULL;
8179 * Before attempting to place new icons, we need to make sure that
8180 * all of the existing object_positions entries have had their
8181 * file_view_data field filled in. This is so that during placement,
8182 * we can get the height and width of the associated icons, to help
8185 for (i = 0; i < order_count; i++)
8187 object = order_list[i];
8188 if (object->displayed)
8190 if (position_data = GetPositionalData(file_mgr_data, object, 0, False))
8192 /* Save; used later during redraw */
8193 position_data->file_view_data = object;
8194 object->position_info = (ObjectPtr)position_data;
8197 else if (position_data = GetPositionalData(file_mgr_data, object, 0,
8201 * If an object has position information, but is currently
8202 * filtered, don't discard its position info; mark it as in-use.
8204 position_data->file_view_data = object;
8205 object->position_info = (ObjectPtr)position_data;
8209 /* Remove any unused position data entries */
8210 for (i = 0; i < file_mgr_data->num_objects; )
8212 if (!file_mgr_data->object_positions[i]->in_use)
8214 /* If this object had a text field, delete it */
8215 for (k = 0; k < file_window->composite.num_children; k++)
8217 if (XmIsTextField(file_window->composite.children[k]) &&
8218 !file_window->composite.children[k]->core.being_destroyed)
8220 XtSetArg(args[0], XmNuserData, &edit_name);
8221 XtGetValues(file_window->composite.children[k], args, 1);
8222 if (strcmp(edit_name,file_mgr_data->object_positions[i]->name)
8226 XtUnmanageChild(file_window->composite.children[k]);
8227 XtDestroyWidget(file_window->composite.children[k]);
8233 /* Free up the entry; bump up the other array entries */
8234 /* Update the linked list */
8235 if (file_mgr_data->object_positions[i]->prev)
8237 file_mgr_data->object_positions[i]->prev->next = (ObjectPtr)
8238 file_mgr_data->object_positions[i]->next;
8240 if (file_mgr_data->object_positions[i]->next)
8242 file_mgr_data->object_positions[i]->next->prev = (ObjectPtr)
8243 file_mgr_data->object_positions[i]->prev;
8245 sorder = file_mgr_data->object_positions[i]->stacking_order;
8246 XtFree(file_mgr_data->object_positions[i]->name);
8247 file_mgr_data->object_positions[i]->name = NULL;
8248 XtFree((char *)file_mgr_data->object_positions[i]);
8249 file_mgr_data->object_positions[i] = NULL;
8250 for (j = i; j < file_mgr_data->num_objects - 1; j++)
8252 file_mgr_data->object_positions[j] =
8253 file_mgr_data->object_positions[j+1];
8255 file_mgr_data->num_objects--;
8256 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8257 (char *)file_mgr_data->object_positions,
8258 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8259 CompressObjectList(file_mgr_data->object_positions,
8260 file_mgr_data->num_objects, sorder);
8266 /* Now, it is safe to position any unplaced objects */
8267 for (i = 0; i < order_count; i++)
8269 object = order_list[i];
8270 if (object->displayed)
8272 position_data = GetPositionalData(file_mgr_data, object,
8273 file_window_width, True);
8275 /* Save; used later during redraw */
8276 position_data->file_view_data = object;
8277 object->position_info = (ObjectPtr)position_data;
8279 /* record position of bottom left corner for DisplaySomeIcons */
8280 object->x = position_data->x;
8281 object->y = position_data->y +
8282 (object->need_update? grid_height: object->widget->core.height);
8286 /* Get largest x value */
8289 bottom = GetBottomOfStack(file_mgr_data);
8292 if (bottom->file_view_data != NULL && bottom->file_view_data->displayed)
8294 if (bottom->file_view_data->position_info->x > largest_x)
8295 largest_x = bottom->file_view_data->position_info->x;
8296 if (bottom->file_view_data->position_info->y > largest_y)
8297 largest_y = bottom->file_view_data->position_info->y;
8299 bottom = (ObjectPosition *)bottom->prev;
8301 largest_x += grid_width;
8302 largest_y += grid_height;
8304 /* if necessary, shrink the width & height to what we need */
8305 if (current_wd == 32767)
8307 current_wd = largest_x;
8311 if (current_ht == 32767)
8313 current_ht = largest_y;
8317 /* Get the horizontal and vertical scrollbars. */
8318 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
8319 XtSetValues (file_mgr_rec->scroll_window, args, 1);
8322 * Typically, dtfile does everything possible to prevent a horizontal
8323 * scrollbar from being displayed. However, when random placement is
8324 * enabled, we don't mind having a horizontal scrollbar, when needed.
8325 * We need to manually manage this, since the normal dtfile layout
8326 * code may have forcably unmanaged the scrollbar earlier.
8328 if (XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8330 /* get scroll bar values */
8331 (void)XmScrollBarGetValues(file_mgr_rec->horizontal_scroll_bar,
8332 &value, &size, &increment, &page);
8335 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
8336 file_mgr_rec->scroll_window))
8338 if ((Dimension)largest_x >= (Dimension)(file_mgr_rec->scroll_window->core.width -
8339 (file_mgr_rec->vertical_scroll_bar->core.width + 4)))
8341 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8345 /* set scroll bar values changing its position */
8346 if(value != 0 && XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8347 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8350 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
8351 XtSetArg (args[0], XmNx, 0);
8352 XtSetValues ((Widget)file_window, args, 1);
8356 else if ((Dimension)largest_x >= (Dimension)(file_mgr_rec->scroll_window->core.width - 4))
8357 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8360 /* set scroll bar values changing its position */
8361 if(value != 0 && XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8362 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8365 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
8366 XtSetArg (args[0], XmNx, 0);
8367 XtSetValues ((Widget)file_window, args, 1);
8371 /* Set the file window width and height to be at least */
8372 /* the size of the scrolled window. */
8373 if ((Dimension)(current_wd) < (Dimension)(file_mgr_rec->scroll_window->core.width - 4))
8375 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
8376 file_mgr_rec->scroll_window))
8377 current_wd = file_mgr_rec->scroll_window->core.width -
8378 (file_mgr_rec->vertical_scroll_bar->core.width + 4);
8380 current_wd = file_mgr_rec->scroll_window->core.width - 4;
8384 if ((Dimension)(current_ht) < (Dimension)(file_mgr_rec->scroll_window->core.height - 4))
8386 current_ht = file_mgr_rec->scroll_window->core.height - 4;
8392 XtSetArg (args[0], XmNwidth, current_wd);
8393 XtSetArg (args[1], XmNheight, current_ht);
8394 XtSetValues (file_mgr_rec->file_window, args, 2);
8397 /* Set the vertical scrollbar's increment to icon height */
8398 XtSetArg (args[0], XmNincrement, file_mgr_data->grid_height + 2);
8399 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 1);
8402 * Don't keep up the hourglass; this helps the user to get the impression
8403 * that all of the work is done.
8405 if (turn_off_hourglass)
8406 _DtTurnOffHourGlass(file_mgr_rec->shell);
8410 /***************************************************
8412 * Given a desktop object, see if it has already been assigned a position;
8413 * if not, then try to fit it into the next available grid position.
8415 **************************************************/
8429 int srcABot, srcBBot;
8430 int srcARight, srcBRight;
8434 srcABot = y1 + h1 - 1;
8435 srcBBot = y2 + h2 - 1;
8436 srcARight = x1 + w1 - 1;
8437 srcBRight = x2 + w2 - 1;
8449 if (srcARight >= srcBRight)
8450 dw = srcBRight - dx + 1;
8452 dw = srcARight - dx + 1;
8454 if (srcABot > srcBBot)
8455 dh = srcBBot - dy + 1;
8457 dh = srcABot - dy + 1;
8459 if (dw <= 0 || dh <= 0)
8465 static ObjectPosition *
8467 FileMgrData * file_mgr_data,
8468 FileViewData * object,
8469 Dimension max_width,
8474 ObjectPosition *entry, *top;
8477 Dimension grid_height;
8478 Dimension grid_width;
8480 ObjectPosition * oP;
8481 Dimension objWidth, objHeight;
8482 Dimension oWidth, oHeight;
8484 /* If object already has positional data, then use it */
8485 for (i = 0; i < file_mgr_data->num_objects; i++)
8487 if (strcmp(object->file_data->file_name,
8488 file_mgr_data->object_positions[i]->name) == 0)
8491 file_mgr_data->object_positions[i]->in_use = True;
8492 return(file_mgr_data->object_positions[i]);
8499 /* Create a new entry, and place into the grid on the top of the stack */
8500 entry = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8501 entry->name = XtNewString(object->file_data->file_name);
8502 entry->in_use = True;
8503 entry->late_bind = False;
8504 entry->stacking_order = 2;
8507 entry->file_view_data = NULL;
8509 if(file_mgr_data->num_objects == 1)
8511 top = file_mgr_data->object_positions[0];
8512 top->next = (ObjectPtr)entry;
8513 entry->prev = (ObjectPtr)top;
8518 /* Push all other objects down in the stack */
8519 for (i = 0; i < file_mgr_data->num_objects; i++)
8521 /* Find the previous top of the stack */
8522 if (file_mgr_data->object_positions[i]->stacking_order == 1)
8524 top = file_mgr_data->object_positions[i];
8527 else if (file_mgr_data->object_positions[i]->stacking_order == 2)
8530 top = GetTopOfStack(file_mgr_data);
8531 top->next = (ObjectPtr)entry;
8532 entry->next = (ObjectPtr)file_mgr_data->object_positions[i];
8533 entry->prev = (ObjectPtr)top;
8534 file_mgr_data->object_positions[i]->prev = (ObjectPtr)entry;
8536 file_mgr_data->object_positions[i]->stacking_order++;
8540 grid_height = file_mgr_data->grid_height;
8541 grid_width = file_mgr_data->grid_width;
8545 if (object->widget && !object->need_update)
8547 objWidth = object->widget->core.width;
8548 objHeight = object->widget->core.height;
8552 objWidth = grid_width;
8553 objHeight = grid_height;
8556 /* Find the first open spot, which will not cause any overlap */
8561 for (i = 0; i < file_mgr_data->num_objects; i++)
8563 oP = file_mgr_data->object_positions[i];
8564 if (oP->file_view_data->widget && !oP->file_view_data->need_update)
8566 oWidth = oP->file_view_data->widget->core.width;
8567 oHeight = oP->file_view_data->widget->core.height;
8571 oWidth = grid_width;
8572 oHeight = grid_height;
8574 if (oP->file_view_data->displayed &&
8575 IntersectRects(x, y, objWidth, objHeight,
8576 oP->x, oP->y, oWidth, oHeight))
8578 /* Try next grid spot */
8579 x += grid_width + XSPACING;
8581 if ((Dimension)(x + objWidth) >= max_width)
8583 /* Go to next row */
8584 y += grid_height + YSPACING(file_mgr_data);
8593 /* Add to the end of the list */
8596 file_mgr_data->num_objects++;
8597 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8598 (char *)file_mgr_data->object_positions,
8599 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8601 /* Force the ordered list to be maintained */
8602 for (i = 0; i < file_mgr_data->num_objects - 1; i++)
8604 if ((entry->y < file_mgr_data->object_positions[i]->y) ||
8605 ((entry->y == file_mgr_data->object_positions[i]->y) &&
8606 (entry->x < file_mgr_data->object_positions[i]->x)))
8608 /* Fits here; slide later entries down */
8609 for (k = file_mgr_data->num_objects - 1; k > i; k--)
8611 file_mgr_data->object_positions[k] =
8612 file_mgr_data->object_positions[k-1];
8619 file_mgr_data->object_positions[i] = entry;
8620 return(file_mgr_data->object_positions[i]);
8624 /*******************************************************************
8626 * BuildObjectPositons - builds up the object positions for directories
8627 * which have now object position information.
8629 *********************************************************************/
8631 BuildObjectPositions(
8632 FileMgrData *file_mgr_data)
8635 FileViewData * file_view_data;
8636 ObjectPosition * ptr;
8638 file_mgr_data->object_positions = (ObjectPosition **)XtMalloc(
8639 sizeof(ObjectPosition *) *
8640 file_mgr_data->directory_set[0]->file_count);
8642 for (i = 0, j = 0; i < file_mgr_data->directory_set[0]->file_count; i++)
8644 file_view_data = file_mgr_data->directory_set[0]->order_list[i];
8646 if (file_view_data->filtered)
8649 ptr = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8650 ptr->name = XtNewString(file_view_data->file_data->file_name);
8651 ptr->x = file_view_data->x;
8652 ptr->y = file_view_data->y -
8653 (file_view_data->need_update? file_mgr_data->grid_height:
8654 file_view_data->widget->core.height);
8656 ptr->late_bind = False;
8657 ptr->stacking_order = j+1;
8658 ptr->file_view_data = file_view_data;
8659 file_view_data->position_info = (ObjectPtr)ptr;
8663 /* Sort according to left-to-right, top-to-bottom */
8664 for (k = 0; k < j; k++)
8666 if ((ptr->y < file_mgr_data->object_positions[k]->y) ||
8667 ((ptr->y == file_mgr_data->object_positions[k]->y) &&
8668 (ptr->x < file_mgr_data->object_positions[k]->x)))
8670 /* Shift others down, to open up a spot */
8671 for (l = j; l > k; l--)
8673 file_mgr_data->object_positions[l] =
8674 file_mgr_data->object_positions[l - 1];
8679 file_mgr_data->object_positions[k] = ptr;
8683 file_mgr_data->num_objects = j;
8685 /* Repair all of the next and prev pointers */
8686 RepairStackingPointers(file_mgr_data);
8687 OrderChildrenList(file_mgr_data);
8691 /***********************************
8693 * When items are dragged around on a random placement window, they will be
8694 * repositioned at the point where they were dropped. Multiple drop items
8695 * will be positioned 'around' where the drop occurred.
8697 **********************************/
8701 FileMgrData * file_mgr_data,
8706 Boolean late_binding_needed)
8715 ObjectPosition * save_object;
8717 FileMgrRec * file_mgr_rec;
8718 XmManagerWidget file_window;
8723 int newEntryCount = 0;
8724 char dot_dir[3] = ".";
8725 char dotdot_dir[3] = "..";
8727 /* if random placement is not enabled, positioning doesn't matter */
8728 if(file_mgr_data->positionEnabled == RANDOM_OFF)
8731 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
8734 * For directory views, no positional data may be present if positioning
8735 * was disabled for this view. So ... we must create some now.
8737 if ((file_mgr_data->num_objects == 0) &&
8738 (file_mgr_data->directory_set[0]->file_count > 0))
8740 BuildObjectPositions(file_mgr_data);
8744 * Update to the new position.
8745 * The position needs to be adjusted so that the icon actually ends
8746 * up where the user dropped it. This is because the drag icon includes
8747 * margins and shadow area, but not the highlight area of the icon gadget
8748 * that was dragged. Coordinates drop_x, drop_y are the upper left corner
8749 * of the drag icon when it was dropped. To convert to icon gadget
8750 * coordinates we need to subtract the highlight thickness.
8752 if (file_mgr_data->layout_data != NULL)
8753 adj = ((IconLayoutData *)file_mgr_data->layout_data)->highlight;
8758 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8760 /* Process each of the dropped files */
8761 /* Go from bottom to top, to retain stacking order */
8762 for (i = file_count - 1; i >= 0; i--)
8767 * The names typically come in as complete paths; we only want
8768 * the filename portion.
8769 * fdt: this check will break for root (/)
8771 if( strcmp(file_mgr_data->current_directory, file_list[i]) == 0)
8773 else if(strncmp(file_mgr_data->current_directory, file_list[i], strlen(file_list[i]) ) == 0 )
8777 if ((name = strrchr(file_list[i], '/')) == NULL)
8778 name = file_list[i];
8783 /* Try to gracefully handle root (/) */
8791 /* Find the positional data for this object, if any */
8792 for (j = 0; j < file_mgr_data->num_objects; j++)
8794 if (strcmp(name, file_mgr_data->object_positions[j]->name) == 0)
8796 /* Find the associated widget */
8797 for (k = 0; strcmp(name,
8798 file_mgr_data->directory_set[0]->file_view_data[k]->file_data-> file_name); k++);
8802 /* If this object has a text field, then move it also */
8803 for (l = 0; l < file_window->composite.num_children; l++)
8805 if (XmIsTextField(file_window->composite.children[l]) &&
8806 !file_window->composite.children[l]->core.being_destroyed)
8808 XtSetArg(args[0], XmNuserData, &edit_name);
8809 XtGetValues(file_window->composite.children[l], args, 1);
8810 if (strcmp(edit_name, name) == 0)
8812 textWidget = file_window->composite.children[l];
8823 ObjectPosition * data;
8825 /* Create positional data at the top of the ordered array */
8828 data = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8829 data->name = XtNewString(name);
8832 data->in_use = True;
8833 data->late_bind = True;
8834 data->stacking_order = 1;
8835 data->file_view_data = NULL;
8839 /* Push all other objects down in the stack */
8840 for (i2 = 0; i2 < file_mgr_data->num_objects; i2++)
8842 /* Find the previous top of the stack */
8843 if (file_mgr_data->object_positions[i2]->stacking_order == 1)
8845 data->next = (ObjectPtr)file_mgr_data->object_positions[i2];
8846 file_mgr_data->object_positions[i2]->prev = (ObjectPtr)data;
8848 file_mgr_data->object_positions[i2]->stacking_order++;
8851 file_mgr_data->num_objects++;
8852 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8853 (char *)file_mgr_data->object_positions,
8854 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8856 /* Add entry to the top of the ordered array */
8857 for (j = file_mgr_data->num_objects - 1; j > 0; j--)
8859 file_mgr_data->object_positions[j] =
8860 file_mgr_data->object_positions[j - 1];
8863 file_mgr_data->object_positions[0] = data;
8867 /* Move item upto top of the stack */
8868 RepositionUpInStack(file_mgr_data,
8869 file_mgr_data->object_positions[j]->stacking_order, 1);
8872 orig_x = file_mgr_data->object_positions[j]->x;
8873 orig_y = file_mgr_data->object_positions[j]->y;
8874 file_mgr_data->object_positions[j]->x = x;
8875 file_mgr_data->object_positions[j]->y = y;
8876 save_object = file_mgr_data->object_positions[j];
8878 /* Move the object */
8881 /* We need to force a geometry request */
8882 XtSetArg(args[0], XmNx, x);
8883 XtSetArg(args[1], XmNy, y);
8884 XtSetValues(file_mgr_data->directory_set[0]->file_view_data[k]->widget,
8887 /* Move associated text widget, if there is one */
8892 t_x = textWidget->core.x + x - orig_x;
8893 t_y = textWidget->core.y + y - orig_y;
8895 /* We need to force a geometry request */
8896 XtSetArg(args[0], XmNx, t_x);
8897 XtSetArg(args[1], XmNy, t_y);
8898 XtSetValues(textWidget, args, 2);
8903 * Reorder the positional array, so that it remains ordered.
8904 * Bubble down toward the end of the list if the object has moved
8905 * farther from the origin; bubble up if it has moved closer to
8908 if ((y > orig_y) || ((y == orig_y) && (x > orig_x)))
8911 for (k = j + 1; k < file_mgr_data->num_objects; k++)
8913 if ((y < file_mgr_data->object_positions[k]->y) ||
8914 ((y == file_mgr_data->object_positions[k]->y) &&
8915 (x < file_mgr_data->object_positions[k]->x)))
8917 /* We fit right here */
8918 file_mgr_data->object_positions[k - 1] = save_object;
8924 file_mgr_data->object_positions[k - 1] =
8925 file_mgr_data->object_positions[k];
8929 /* See if it goes at the end */
8930 if (k == file_mgr_data->num_objects)
8931 file_mgr_data->object_positions[k - 1] = save_object;
8936 for (k = j - 1; k >= 0; k--)
8938 if ((y > file_mgr_data->object_positions[k]->y) ||
8939 ((y == file_mgr_data->object_positions[k]->y) &&
8940 (x > file_mgr_data->object_positions[k]->x)))
8942 /* We fit right here */
8943 file_mgr_data->object_positions[k + 1] = save_object;
8949 file_mgr_data->object_positions[k + 1] =
8950 file_mgr_data->object_positions[k];
8954 /* See if it goes at the end */
8956 file_mgr_data->object_positions[0] = save_object;
8959 /* Create position for the next file to be processed */
8964 * Reregister the desktop hotspots.
8965 * Even if the caller told us that late binding was needed, if no new
8966 * objects were specified, then we need to register hotspots now, because
8967 * the layout function will never be called because the directory never
8968 * really changed. This situation can occur when an icon is dropped on
8969 * the desktop from a regular dtfile view, but that icon is already on
8970 * the desktop (it thus is just a reposition).
8972 if (!late_binding_needed ||
8973 (late_binding_needed && (newEntryCount == 0)))
8975 RegisterDesktopHotspots(file_mgr_data, file_mgr_rec);
8980 RegisterDesktopHotspots (
8981 FileMgrData * file_mgr_data,
8982 FileMgrRec * file_mgr_rec)
8984 XmManagerWidget file_window;
8985 FileViewData * file_view_data;
8986 int ex, ey, ewd, eht;
8991 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8992 ex = -file_window->core.x;
8993 ey = -file_window->core.y;
8994 ewd = XtParent(file_window)->core.width;
8995 eht = XtParent(file_window)->core.height;
8997 /* Set up the icon location information with the drag handler */
8998 /* Register in top to bottom stacking order */
8999 top = GetTopOfStack(file_mgr_data);
9003 file_view_data = top->file_view_data;
9005 if (file_view_data != NULL &&
9006 file_view_data->displayed &&
9007 !file_view_data->need_update)
9009 icon = file_view_data->widget;
9010 if ((Position)(icon->core.x + icon->core.width) >= (Position)ex &&
9011 icon->core.x < ex + ewd &&
9012 (Position)(icon->core.y + icon->core.height) >= (Position)ey &&
9013 icon->core.y < ey + eht)
9015 SetHotRects(file_view_data,
9016 (XtCallbackProc) DropOnObject,
9017 (XtPointer) file_view_data);
9027 * Dtfile used to try to determine if the vertical scrollbar was visible
9028 * by checking to see if it was managed; the assumption here was that the
9029 * scrolled window widget unmanaged the scrollbar, when it was not needed.
9030 * Unfortunately, it turns out that instead of unmanaging the scrollbar,
9031 * the scrolled window simply moves the scrollbar out of sight; it is moved
9032 * such that the X for the scrollbar is the same as the width of the
9033 * scrolled window. So ... in order for us to really determine if the
9034 * scrollbar is visible, we need to see whether or not its X falls within
9035 * the visible area of the scrolled window.
9039 VerticalScrollbarIsVisible(
9044 if (vertSB && XtIsManaged(vertSB) &&
9045 (vertSB->core.x < (Position)scrolledWin->core.width))
9054 HorizontalScrollbarIsVisible(
9059 if (hortSB && XtIsManaged(hortSB) &&
9060 (hortSB->core.y <= (Position)scrolledWin->core.height))