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 ************************************<+>*************************************/
155 #include <Xm/BulletinB.h>
156 #include <Xm/MwmUtil.h>
157 #include <X11/ShellP.h>
158 #include <X11/Shell.h>
159 #include <X11/Xutil.h>
160 #include <X11/Xatom.h>
161 #include <X11/keysymdef.h>
164 #include <X11/extensions/shape.h>
167 #include <Xm/DrawingA.h>
168 #include <Xm/DrawingAP.h>
169 #include <Xm/RowColumn.h>
170 #include <Xm/LabelG.h>
171 #include <Xm/PushBG.h>
172 #include <Xm/SeparatoG.h>
173 #include <Xm/ScrollBar.h>
174 #include <Xm/TextF.h>
175 #include <Xm/Frame.h>
176 #include <Xm/Screen.h>
177 #include <sys/types.h>
178 #include <sys/stat.h>
180 #include <Dt/IconP.h>
181 #include <Dt/IconFile.h>
183 #include <Xm/DragIcon.h>
184 #include <Xm/DragC.h>
190 #include <Dt/Action.h>
191 #include <Dt/Connect.h>
193 #include <Dt/DtNlUtils.h>
194 #include <Dt/HourGlass.h>
196 #include <Dt/UserMsg.h>
201 #include "SharedProcs.h"
209 #include "SharedMsgs.h"
212 extern Widget _DtDuplicateIcon ( Widget, Widget, XmString, String, XtPointer, Boolean );
214 /* absolute value macro */
216 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
222 * MAXWINSIZE: maximum width of the file window
224 * Note: the file window width and height can't exceed the maximum value
225 * for a short (32767), because x and y coords of the icon gadgets placed
226 * in the file window are stored as short's by the Xt library (the
227 * Position type is a short).
228 * Furthermore, somewhere in the code for registering icon drop sites
229 * in libDt or libXm calculations are done that overflow if the window
230 * size is too close to the maximum of 32767. The symptom is observed
231 * most easily in tree mode on a directory large enough for icons to
232 * overflow into a second column: for values of MAXWINSIZE of 32767,
233 * none of the icons are sensitive as drop sites any more. The value
234 * for MAXWINSIZE defined below has been found to be "safe" by experiment.
236 #define MAXWINSIZE 32600
238 /******** Static Function Declarations ********/
240 static int FileNameAscending(
243 static int FileNameDescending(
246 static int FileTypeAscending(
249 static int FileTypeDescending(
252 static int FileSizeAscending(
255 static int FileSizeDescending(
258 static int FileDateAscending(
261 static int FileDateDescending(
264 static void CompressObjectList (
265 ObjectPosition ** object_positions,
267 int starting_index) ;
268 static ObjectPosition *GetPositionalData (
269 FileMgrData * file_mgr_data,
270 FileViewData * object,
273 static void RedisplayUsingStackingOrder (
274 FileMgrData * file_mgr_data,
276 register XEvent *event,
278 static void ReorderChildrenList (
279 XmManagerWidget file_window,
284 static Boolean IsDesktopPtr (
285 FileViewData * fileViewData,
286 FileMgrData ** fileMgrData,
287 DesktopRec ** desktopRec) ;
288 static Boolean IntersectRects(
297 static void InitiateIconDrag(
298 FileViewData * fileViewData,
302 static void RelocateDesktopIcon(
303 DesktopRec * desktopRec,
306 static void BuildObjectPositions(
307 FileMgrData *file_mgr_data);
308 static void moveCopyLinkCancel(
310 XtPointer client_data,
311 XtPointer call_data );
312 static void moveCopyLinkOK(
314 XtPointer client_data,
315 XtPointer call_data );
316 static void DropOnRootCB (
318 XtPointer client_data,
319 XtPointer call_data);
320 static void _UpdateFileIcons(
321 FileMgrRec *file_mgr_rec,
322 FileMgrData *file_mgr_data,
323 Boolean new_directory,
324 DirectorySet * add_dir_set );
325 static void CreateTreeIcons(
327 static void TreeBtnCallback(
329 XtPointer clientData,
330 XmAnyCallbackStruct * callData );
331 static void LayoutDesktopIcons(
332 FileMgrRec *file_mgr_rec,
333 FileMgrData *file_mgr_data,
334 FileViewData ** order_list,
336 Boolean turn_off_hourglass);
337 static XmGadget InputInGadget (
341 static XmGadget InputForGadget (
346 /******** End Static Function Declarations ********/
348 /* cursor for double-click-drag (@@@ should be a resource) */
349 static Cursor loc_cursor1 = None;
350 static Cursor loc_cursor2 = None;
351 #define DBLCLICK_DRAG_THRESHOLD 20
353 /* layout constants (@@@ could be made resources) */
356 #define YSPACING(fmd) \
358 (fmd->view != BY_NAME? - ((IconLayoutData *)fmd->layout_data)->highlight: \
359 - ((IconLayoutData *)fmd->layout_data)->highlight + 2): \
362 #define TreeOffset 15
363 #define TreeOneWd(sz) (TreeOffset + TreeBtnWd[sz]/2)
364 #define TreeLX(level,sz) (TreeBtnWd[sz]/2 + ((level) - 1)*TreeOneWd(sz))
365 #define TreeWd(level,sz) \
366 (TreeLX(level,sz) + TreeOffset + TreeBtnWd[sz] + TreeSep)
368 /* maximum size of the small, medium, and large tree buttons */
369 static int TreeBtnWd[3] = { 0, 0, 0 };
370 static int TreeBtnHt[3] = { 0, 0, 0 };
372 static int TreeNilWd[3] = { 0, 0, 0 };
373 static int TreeNilHt[3] = { 0, 0, 0 };
375 /* tree expansion circle pixmap indices */
377 tpxNotRead, /* dotted circle */
378 tpxError, /* crossed circle */
379 tpxMore, /* "+" circle */
380 tpxLess, /* "-" circle */
381 tpxBoth, /* "+/-" circle */
382 tpxEmpty, /* empty circle */
383 tpxNil, /* empty-set symbol */
387 /* pixmaps for expand circles in tree mode */
388 static struct TreePx {
389 char *name; /* name of pixmap file */
390 Pixmap px[3]; /* small, medium, and large pixmap */
402 static char *TreePxSuffix[3] = { ".s", ".m", ".l" };
404 /* value need to to convert drop position to icon placement */
405 static int dragIconPixmapOffsetX;
406 static int dragIconPixmapOffsetY;
412 #define FILE_INVALID 2
415 FileMgrPopup fileMgrPopup = {NULL};
418 /************************************************************************
419 ************************************************************************
421 * Comparison functions used for sorting the files
423 ************************************************************************
424 ************************************************************************/
425 /* only use when LANG=C on platforms that don't
426 provide strcasecmp(). Otherwise, use strcoll() */
432 /* Note: This is not really a string case insensitive compare. So don't
433 even think of replacing it with any other library routines.
435 char *s1a = (char *)s1, *s2a = (char *)s2;
437 if (s1 == s2) return 0;
439 for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) {
442 /* File Manager depends heavily on this routine to position the
444 We want case INSENSITIVE comparision, however when we have
445 2 same size and case equivalent strings i.e. "A" and "a", we
446 need this routine to behave like a case SENSITIVE comparision, so
447 the position of the icon is constant so "A" is always
452 for (; *s1a == *s2a; ++s1a, ++s2a) {
463 return tolower(*s1) - tolower(*s2);
466 StrcollProc FMStrcoll = NULL;
473 struct locale_data * li;
480 /* if locale is C, use the explicit case insensitive compare */
482 li = getlocale(LOCALE_STATUS);
483 if ( NULL == li->LC_COLLATE_D || strcmp(C_LANG,li->LC_COLLATE_D) == 0 )
486 locale = setlocale(LC_COLLATE,NULL); /* put locale in buf */
487 if (strcmp(locale,C_LANG) == 0)
494 return ((StrcollProc)strcoll);
504 if (((FileMgrData *)((DirectorySet *)((*t1)->directory_set))->file_mgr_data)
505 ->show_type == MULTIPLE_DIRECTORY)
507 if (!(*t1)->file_data->is_subdir && (*t2)->file_data->is_subdir)
509 else if ((*t1)->file_data->is_subdir && !(*t2)->file_data->is_subdir)
523 if (FMStrcoll ((*t1)->file_data->file_name, "." ) == 0 )
529 if (FMStrcoll ((*t1)->file_data->file_name, "..") == 0 )
531 if ( FMStrcoll ((*t2)->file_data->file_name, ".") == 0 )
538 if (FMStrcoll ((*t2)->file_data->file_name, ".") == 0 || FMStrcoll ((*t2)->file_data->file_name, "..") == 0)
552 if (!(*t1)->file_data->is_subdir && (*t2)->file_data->is_subdir)
558 if ((*t1)->file_data->is_subdir && !(*t2)->file_data->is_subdir)
574 if( SpecialCases( t1, t2, &rc ) )
577 if((*t1)->file_data->action_name == NULL)
579 if((*t2)->file_data->action_name == NULL)
580 rc = FMStrcoll((*t1)->file_data->file_name,
581 (*t2)->file_data->file_name);
583 rc = FMStrcoll((*t1)->file_data->file_name,
584 (*t2)->file_data->action_name);
588 if((*t2)->file_data->action_name != NULL)
589 rc = FMStrcoll((*t1)->file_data->action_name,
590 (*t2)->file_data->action_name);
592 rc = FMStrcoll((*t1)->file_data->action_name,
593 (*t2)->file_data->file_name);
606 if( SpecialCases( t1, t2, &rc ) )
609 if((*t1)->file_data->action_name == NULL)
611 if((*t2)->file_data->action_name == NULL)
612 rc = FMStrcoll((*t1)->file_data->file_name,
613 (*t2)->file_data->file_name);
615 rc = FMStrcoll((*t1)->file_data->file_name,
616 (*t2)->file_data->action_name);
620 if((*t2)->file_data->action_name != NULL)
621 rc = FMStrcoll((*t1)->file_data->action_name,
622 (*t2)->file_data->action_name);
624 rc = FMStrcoll((*t1)->file_data->action_name,
625 (*t2)->file_data->file_name);
644 if( SpecialCases( t1, t2, &rc ) )
647 rc = strcoll( (*t1)->file_data->logical_type, (*t2)->file_data->logical_type );
649 rc = FileNameAscending( t1, t2 );
661 if( SpecialCases( t1, t2, &rc ) )
664 rc = strcoll( (*t1)->file_data->logical_type, (*t2)->file_data->logical_type );
672 rc = FileNameDescending( t1, t2 );
684 if( SpecialCases( t1, t2, &rc ) )
687 if ((*t1)->file_data->stat.st_size < (*t2)->file_data->stat.st_size)
690 else if ((*t1)->file_data->stat.st_size > (*t2)->file_data->stat.st_size)
703 if( SpecialCases( t1, t2, &rc ) )
706 if ((*t1)->file_data->stat.st_size < (*t2)->file_data->stat.st_size)
709 if ((*t1)->file_data->stat.st_size > (*t2)->file_data->stat.st_size)
722 if( SpecialCases( t1, t2, &rc ) )
725 if ((*t1)->file_data->stat.st_mtime < (*t2)->file_data->stat.st_mtime)
728 if ((*t1)->file_data->stat.st_mtime > (*t2)->file_data->stat.st_mtime)
742 if( SpecialCases( t1, t2, &rc ) )
745 if ((*t1)->file_data->stat.st_mtime < (*t2)->file_data->stat.st_mtime)
748 if ((*t1)->file_data->stat.st_mtime > (*t2)->file_data->stat.st_mtime)
758 /************************************************************************
761 * Sort the file display list according to the ordering data.
763 ************************************************************************/
767 FileMgrData *file_mgr_data,
768 DirectorySet *directory_set )
770 FileViewData ** file_view_data;
772 FileViewData ** order_list;
778 file_view_data = directory_set->file_view_data;
779 file_count = directory_set->file_count;
782 /* Allocate an ordering list */
784 if (directory_set->order_list != NULL)
786 XtFree ((char *) directory_set->order_list);
787 directory_set->order_list = NULL;
791 directory_set->order_list = order_list =
792 (FileViewData **) XtMalloc (sizeof (FileViewData **) * file_count);
794 directory_set->order_list = order_list = NULL;
796 /* Get pointers to all of the file data into the order list */
798 for (i = 0; i < file_count; i++)
799 order_list[i] = file_view_data[i];
801 /* Set up the sorting functions according to the order and direction. */
805 if (file_mgr_data->order == ORDER_BY_FILE_TYPE)
807 if (file_mgr_data->direction == DIRECTION_ASCENDING)
809 sort = (int *) FileTypeAscending;
810 sub_sort = (int *) FileNameAscending;
814 sort = (int *) FileTypeDescending;
815 sub_sort = (int *) FileNameDescending;
819 else if (file_mgr_data->order == ORDER_BY_ALPHABETICAL)
821 if (file_mgr_data->direction == DIRECTION_ASCENDING)
822 sort = (int *) FileNameAscending;
824 sort = (int *) FileNameDescending;
826 else if (file_mgr_data->order == ORDER_BY_DATE)
828 if (file_mgr_data->direction == DIRECTION_ASCENDING)
829 sort = (int *) FileDateAscending;
831 sort = (int *) FileDateDescending;
834 else if (file_mgr_data->order == ORDER_BY_SIZE)
836 if (file_mgr_data->direction == DIRECTION_ASCENDING)
837 sort = (int *) FileSizeAscending;
839 sort = (int *) FileSizeDescending;
843 /* Sort the files and if the sub_sort function is non-null, */
844 /* sort sets of the files broken according to file type. */
846 qsort (order_list, file_count, sizeof (FileViewData *), (int (*)())sort);
848 if (sub_sort != NULL)
853 while (i < file_count)
855 if (order_list[start]->file_data->logical_type !=
856 order_list[i]->file_data->logical_type)
858 qsort (order_list + start, i - start,
859 sizeof (FileViewData *), (int (*)())sub_sort);
866 qsort (order_list + start, i - start, sizeof (FileViewData *),
867 (int (*)())sub_sort);
873 /************************************************************************
876 * Filter out the files which do not match the filtering criteria.
878 * The `mustMatch' flag is used to determine whether the user has
879 * requested that the files which match the specification are to
880 * be displayed, or instead, filtered out.
882 ************************************************************************/
886 FileMgrData *file_mgr_data,
887 DirectorySet *directory_set )
889 FileViewData **file_view_data;
890 FilterData * filter_data;
891 register int i, j, k;
894 Boolean mustMatch, matches;
896 int invisibleCount = 0;
897 FileViewData *sub_root;
898 #ifdef DT_PERFORMANCE
899 struct timeval update_time_s;
900 struct timeval update_time_f;
902 printf(" Begin FilterFiles\n");
903 gettimeofday(&update_time_s, NULL);
906 _DtPerfChkpntMsgSend("Begin Filtering Files");
910 file_view_data = directory_set->file_view_data;
912 filter_data = (FilterData *)(file_mgr_data->filter_active->data);
913 show_hidden = filter_data->show_hidden;
914 filter = filter_data->filter;
915 mustMatch = filter_data->match_flag;
917 /* set the show hidden boolean depending on the filter specification */
919 file_mgr_data->show_hid_enabled = True;
921 file_mgr_data->show_hid_enabled = False;
923 /* Filter out all files not matching the specifications */
925 for (i = 0; i < directory_set->file_count; i++)
927 /* Initially assume the file is not filtered out */
929 file_view_data[i]->filtered = False;
931 /* If in tree mode, explicitly filter out . and .. */
932 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY &&
933 (strcmp(file_view_data[i]->file_data->file_name, ".") == 0 ||
934 strcmp(file_view_data[i]->file_data->file_name, "..") == 0))
937 file_view_data[i]->filtered = True;
941 /* filter out any files that have their attributes "invisible" */
942 /* field set to false */
943 if((_DtCheckForDataTypeProperty(
944 file_view_data[i]->file_data->logical_type,
946 (file_mgr_data != trashFileMgrData))
949 file_view_data[i]->filtered = True;
954 /* Filter hidden files, according to the user setting */
956 if (file_view_data[i]->file_data->file_name[0] == '.')
958 if(strcmp(file_mgr_data->current_directory, "/") == 0 &&
959 strcmp(file_view_data[i]->file_data->file_name, "..") == 0)
962 file_view_data[i]->filtered = True;
965 if(file_mgr_data->restricted_directory != NULL)
967 if((strcmp(file_mgr_data->restricted_directory,
968 file_mgr_data->current_directory) == 0 &&
969 (strcmp(file_view_data[i]->file_data->file_name, ".") == 0 || strcmp(file_view_data[i]->file_data->file_name, "..") == 0 )) ||
970 (strncmp(file_mgr_data->restricted_directory,file_mgr_data->current_directory, strlen(file_mgr_data->restricted_directory)) == 0 &&
971 strcmp(file_view_data[i]->file_data->file_name, ".") == 0 ))
974 file_view_data[i]->filtered = True;
981 (strcmp(file_view_data[i]->file_data->file_name, "..") == 0 ||
982 strcmp(file_view_data[i]->file_data->file_name, ".") == 0))
986 tempName = (char *)XtMalloc( strlen(file_mgr_data->current_directory) + 3);
987 sprintf( tempName, "%s/", file_mgr_data->current_directory );
988 if( strcmp(users_home_dir, tempName) == 0 ||
989 strcmp(users_home_dir, file_mgr_data->current_directory) == 0)
992 file_view_data[i]->filtered = True;
1000 /* if we want to show the hidden files no more should be filtered out */
1004 /* don't show .trashinfo in the trash directory */
1005 if(trashFileMgrData == file_mgr_data &&
1006 (strcmp(file_view_data[i]->file_data->file_name, ".trashinfo") == 0))
1009 file_view_data[i]->filtered = True;
1013 /* Check for a match against the filter expression string, except for
1014 * files in the trash directory and sub directories in tree mode. */
1017 if (strcmp(filter, "") != 0 &&
1018 file_mgr_data != trashFileMgrData &&
1019 !(file_mgr_data->show_type == MULTIPLE_DIRECTORY &&
1020 file_view_data[i]->file_data->is_subdir))
1022 /* Special case for ".." that need not be filtered */
1023 if( !strcmp( file_view_data[i]->file_data->file_name, ".." )
1024 || !strcmp( file_view_data[i]->file_data->file_name, "." ) )
1027 else if (file_view_data[i]->file_data->action_name)
1029 if(fnmatch((const char *)filter,
1030 (const char *)file_view_data[i]->file_data->action_name,
1036 file_view_data[i]->filtered = True;
1043 else if (fnmatch((const char *)filter,
1044 (const char *)file_view_data[i]->file_data->file_name, 0) == 0)
1049 file_view_data[i]->filtered = True;
1057 /* now lets check through the filter filetypes and if the file is */
1058 /* filtered, filter it out */
1059 if(file_mgr_data != trashFileMgrData)
1061 /* This is for the case of files likes 'action' files which
1062 do not have a logical_type */
1064 if(strcmp(file_view_data[i]->file_data->file_name,file_view_data[i]->
1065 file_data->logical_type) == 0)
1067 if(!filter_data->match_flag)
1072 file_view_data[i]->filtered = True;
1077 for(j = 0; j < filter_data->count; j++)
1079 if(strcmp(filter_data->user_data[j]->filetype,
1080 file_view_data[i]->file_data->logical_type) == 0)
1082 if((filter_data->user_data[j]->selected == True &&
1083 filter_data->match_flag) ||
1084 (filter_data->user_data[j]->selected == False &&
1085 !filter_data->match_flag))
1090 file_view_data[i]->filtered = True;
1099 /* update ndir, nfile counts for this sub directory */
1100 directory_set->filtered_file_count = filterCount;
1101 directory_set->invisible_file_count = invisibleCount;
1102 sub_root = directory_set->sub_root;
1103 sub_root->ndir = sub_root->nfile = 0;
1106 for (i = 0; i < directory_set->file_count; i++)
1108 if (!file_view_data[i]->filtered)
1110 if (file_view_data[i]->file_data->is_subdir)
1117 UpdateBranchState(file_mgr_data, sub_root, BRANCH_UPDATE, False);
1119 #ifdef DT_PERFORMANCE
1120 gettimeofday(&update_time_f, NULL);
1121 if (update_time_s.tv_usec > update_time_f.tv_usec) {
1122 update_time_f.tv_usec += 1000000;
1123 update_time_f.tv_sec--;
1125 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);
1128 _DtPerfChkpntMsgSend("Done Filtering Files");
1136 /************************************************************************
1138 * GetAncestorInfo, GetLevel, GetFullName
1140 ************************************************************************/
1144 FileMgrData *file_mgr_data,
1150 * Get information related to the ancestory of an entry:
1151 * - tree depth level
1153 * - for each level: flag indicating whether there are additional siblings
1154 * to be diplayed after this entry
1157 FileViewData *pp, *pa[256];
1161 /* determine tree depth level of this entry */
1163 for (pp = ip->parent; pp; pp = pp->parent)
1168 /* get a list of all ancestors (including ip) in top down order */
1170 for (pp = ip; pp; pp = pp->parent)
1173 /* construct path name of this entry */
1175 strcpy(path, file_mgr_data->current_directory);
1176 p = path + strlen(path);
1177 for (l = 1; l <= level; l++) {
1180 strcpy(p, pa[l]->file_data->file_name);
1185 /* compile more array */
1187 for (l = 0; l <= level; l++) {
1188 DirectorySet *ds = (DirectorySet *)pa[l]->directory_set;
1190 if (ds->order_list == NULL)
1192 for (i = 0; i < ds->file_count; i++)
1193 if (ds->order_list[i] == pa[l])
1195 for (i = i + 1; i < ds->file_count; i++) {
1196 if (ds->order_list[i]->displayed) {
1208 FileMgrData *file_mgr_data,
1212 GetAncestorInfo(file_mgr_data, ip, NULL, path, NULL);
1218 FileMgrData *file_mgr_data,
1224 GetAncestorInfo(file_mgr_data, ip, NULL, path, NULL);
1225 p = strrchr(path, '/');
1236 for (ip = ip->parent; ip; ip = ip->parent)
1242 /************************************************************************
1246 ************************************************************************/
1251 FileViewData *fvd_array[],
1254 * Copy all entries from the tree to an array
1257 DirectorySet *directory_set;
1260 fvd_array[*index] = ip;
1265 directory_set = (DirectorySet *)ip->desc->directory_set;
1266 for (i = 0; i < directory_set->file_count; i++)
1267 CopyOrderedEntries(directory_set->order_list[i], fvd_array, index);
1274 FileMgrData *file_mgr_data,
1275 FileViewData ***file_view_data,
1281 for (i = 0; i < file_mgr_data->directory_count; i++)
1282 *file_count += file_mgr_data->directory_set[i]->file_count;
1285 (FileViewData **) XtMalloc (*file_count * sizeof(FileViewData *));
1287 CopyOrderedEntries(file_mgr_data->tree_root, *file_view_data, &i);
1291 /************************************************************************
1294 * Callback function invoked upon an action occuring on an icon.
1296 ************************************************************************/
1304 return (ep->type == MotionNotify || ep->type == ButtonRelease);
1311 XtPointer clientData,
1312 XtPointer callData )
1314 XmAnyCallbackStruct * callback;
1315 XButtonEvent * event;
1316 FileViewData * fileViewData;
1317 FileMgrData * fileMgrData;
1318 static Boolean highlightType = INIT_VALUE;
1319 static Widget highlightWidget = NULL;
1322 DesktopRec * desktopRec;
1327 WindowPosition position;
1329 static int adjustState=-1;
1330 XrmValue value_return;
1331 char *str_type_return;
1334 if( adjustState == -1)
1336 if (XrmGetResource(XrmGetDatabase(XtDisplay(w)), "*enableBtn1Transfer", "*EnableBtn1Transfer",&str_type_return, &value_return) && !strcmp(value_return.addr,"True") )
1344 callback = (XmAnyCallbackStruct *) callData;
1345 fileViewData = (FileViewData *) clientData;
1346 event = (XButtonEvent *) callback->event;
1348 if (callback->reason == XmCR_DRAG && event->button == bMenuButton)
1349 callback->reason = XmCR_POPUP;
1351 if(callback->reason != XmCR_UNHIGHLIGHT)
1353 /* Get the directory data and the file manager data */
1354 (void)IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
1357 /* Process the different callback types */
1358 if ((callback->reason == XmCR_ARM) || (callback->reason == XmCR_SELECT))
1361 * Both ARM and SELECT are generated using Button1. We pass on these
1362 * requests to the code responsible for processing button 1 selects
1365 FileMgrRec * fileMgrRec;
1366 DtIconGadget new = (DtIconGadget)w;
1368 if( event->type == KeyPress )
1370 /* if a keypress we only want to select on an SELECT */
1371 if( callback->reason == XmCR_ARM )
1379 kevent = (XKeyEvent *)event;
1380 if (kevent->state & ShiftMask)
1385 keysym = XLookupKeysym((XKeyEvent *)kevent, offset);
1387 if( keysym == XK_Return )
1388 goto run_default_action;
1392 if (callback->reason == XmCR_ARM)
1393 new->icon.armed = False;
1397 B1DragPossible = False;
1398 B2DragPossible = False;
1399 XtCallCallbacks(desktopRec->drawA, XmNinputCallback, callData);
1403 B1DragPossible = False;
1404 B2DragPossible = False;
1406 fileMgrRec = (FileMgrRec *)fileMgrData->file_mgr_rec;
1407 XtCallCallbacks(fileMgrRec->file_window, XmNinputCallback, callData);
1410 if (callback->reason == XmCR_ARM)
1411 new->icon.armed = True;
1413 else if (callback->reason==XmCR_DISARM)
1416 * DISARM is generated as the result of a button 1 up event.
1417 * If we are in the middle of a button 2 drag, then we'll ignore this;
1418 * otherwise, we now know a drag will not start, so clear all state flags.
1423 B1DragPossible = False;
1424 B2DragPossible = False;
1425 ProcessBtnUp = False;
1427 else if (callback->reason == XmCR_DROP)
1430 * DROP is generated as the result of a button 2 up event.
1431 * If we are in the middle of a button 1 drag, then we'll ignore this;
1432 * otherwise, we now know a drag will not start, so clear all state flags.
1437 B1DragPossible = False;
1438 B2DragPossible = False;
1439 ProcessBtnUp = False;
1441 else if (callback->reason == XmCR_DEFAULT_ACTION)
1445 if(event->type == KeyPress)
1451 kevent = (XKeyEvent *)event;
1452 if (kevent->state & ShiftMask)
1457 keysym = XLookupKeysym((XKeyEvent *)kevent, offset);
1459 if (keysym == XK_Escape)
1461 /* an escape unposts the name change text widget */
1463 UnpostDTTextField();
1465 UnpostTextField(fileMgrData);
1470 KeySym SpaceKeySym = XStringToKeysym( "space" );
1471 if( keysym == SpaceKeySym )
1481 * If DEFAULT_ACTION was generated by button press,
1482 * wait for the button release
1485 if(event->type == ButtonPress)
1487 if (loc_cursor1 == None)
1488 loc_cursor1 = XCreateFontCursor(XtDisplay(w), 40);
1489 if (loc_cursor2 == None)
1490 loc_cursor2 = XCreateFontCursor(XtDisplay(w), 34);
1492 root = RootWindowOfScreen(XtScreen(w));
1493 XGrabPointer(XtDisplay(w), root,
1494 False, ButtonReleaseMask | PointerMotionMask,
1495 GrabModeAsync, GrabModeAsync,
1496 None, loc_cursor1, CurrentTime);
1498 XIfEvent(XtDisplay(w), &bevent, IsButtonOrMotion, NULL);
1499 if (!dragged && bevent.type == MotionNotify) {
1500 dx = event->x_root - bevent.xmotion.x_root; if (dx < 0) dx = -dx;
1501 dy = event->y_root - bevent.xmotion.y_root; if (dy < 0) dy = -dy;
1502 if (dx > DBLCLICK_DRAG_THRESHOLD || dy > DBLCLICK_DRAG_THRESHOLD) {
1503 DPRINTF(("dragged!\n"));
1504 XGrabPointer(XtDisplay(w), root,
1505 False, ButtonReleaseMask | PointerMotionMask,
1506 GrabModeAsync, GrabModeAsync,
1507 None, loc_cursor2, CurrentTime);
1511 } while (bevent.type != ButtonRelease);
1513 XUngrabPointer(XtDisplay(w), CurrentTime);
1514 XFlush(XtDisplay(w));
1516 position.x = bevent.xbutton.x_root;
1517 position.y = bevent.xbutton.y_root;
1521 * DEFAULT_ACTION is generated by a double-click of button 1.
1522 * We now know a drag will not start, so clear all state flags.
1524 B1DragPossible = False;
1525 B2DragPossible = False;
1526 ProcessBtnUp = False;
1528 logicalType = fileViewData->file_data->logical_type;
1529 command = _DtRetrieveDefaultAction(logicalType);
1533 /* Any button event unposts the text field */
1534 UnpostDTTextField();
1537 RunDTCommand(command, desktopRec, NULL);
1543 /* Any button event unposts the text field */
1544 UnpostTextField(fileMgrData);
1546 if((openDirType == NEW && strcmp(command, openInPlace) == 0) ||
1547 (openDirType != NEW && strcmp(command, openNewView) == 0))
1549 unsigned int modifiers = event->state;
1551 RunCommand (openNewView, fileMgrData, fileViewData,
1552 dragged? &position: NULL, NULL, NULL);
1553 if((modifiers != 0) && ((modifiers & ControlMask) != 0))
1555 DialogData *dialog_data;
1557 dialog_data = _DtGetInstanceData(fileMgrData->file_mgr_rec);
1558 CloseView(dialog_data);
1565 if ((fileMgrData->show_type == MULTIPLE_DIRECTORY || dragged) &&
1566 strcmp(command, openInPlace) == 0)
1568 RunCommand (openNewView, fileMgrData, fileViewData,
1569 dragged? &position: NULL, NULL, NULL);
1572 RunCommand (command, fileMgrData, fileViewData,
1588 tmpStr = (GETMESSAGE(9,6, "Action Error"));
1589 title = (char *)XtMalloc(strlen(tmpStr) + 1);
1590 strcpy(title, tmpStr);
1592 (void) sprintf (msg,
1593 (GETMESSAGE(9,7, "There are no actions defined for %s\n")),
1596 _DtMessage (desktopRec->shell, title, msg, NULL, HelpRequestCB);
1598 _DtMessage (fileViewData->widget, title, msg, NULL, HelpRequestCB);
1602 else if (callback->reason == XmCR_DRAG)
1605 * DRAG is generated by a button 2 down event. It flags that
1606 * the user may possible be initiating a drag; we won't know
1607 * for sure until the drag threshold is surpassed.
1608 * Ignore this if a Button 1 drag is ramping up.
1613 /* Any button event unposts the text field */
1616 UnpostDTTextField();
1617 if(!DTFileIsSelected(desktopRec, fileViewData) && adjustState)
1618 SelectDTFile(desktopRec);
1622 if( fileMgrData && !FileIsSelected(fileMgrData,fileViewData) &&
1626 SelectFile(fileMgrData, fileViewData);
1628 UnpostTextField(fileMgrData);
1631 /* Save starting X & Y, in case a drag really starts */
1632 initialDragX = event->x;
1633 initialDragY = event->y;
1634 B2DragPossible = True;
1635 memcpy((char *) &desktop_data->event, (char *) event,
1636 (int) sizeof(XButtonEvent));
1638 else if (callback->reason == XmCR_POPUP)
1642 FmPopup (w, clientData, (XEvent *)event, fileMgrData);
1645 else if (callback->reason == XmCR_HIGHLIGHT)
1647 DtIconGadget g = (DtIconGadget)w;
1651 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1652 _XmUnhighlightBorder(w);
1654 B1DragPossible = False;
1655 B2DragPossible = False;
1659 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1662 if ((highlightType != INIT_VALUE) && (highlightWidget))
1666 if (highlightType == NOT_DESKTOP)
1667 DrawUnhighlight(highlightWidget, NOT_DESKTOP);
1668 else if (highlightWidget != w)
1669 DrawUnhighlight(highlightWidget, DESKTOP);
1673 if (highlightType == DESKTOP)
1674 DrawUnhighlight(highlightWidget, DESKTOP);
1675 else if (highlightWidget != w)
1676 DrawUnhighlight(highlightWidget, NOT_DESKTOP);
1682 DrawHighlight(w, NULL, NULL, DESKTOP);
1683 highlightType = DESKTOP;
1687 DrawHighlight(w, fileViewData, fileMgrData, NOT_DESKTOP);
1688 highlightType = NOT_DESKTOP;
1690 highlightWidget = w;
1692 else if (callback->reason == XmCR_UNHIGHLIGHT)
1694 DtIconGadget g = (DtIconGadget)w;
1698 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1699 _XmHighlightBorder(w);
1701 B1DragPossible = False;
1702 B2DragPossible = False;
1706 if ((g->icon.border_type == DtRECTANGLE) || (!g->icon.pixmap))
1709 if (w == highlightWidget)
1711 if (highlightType == DESKTOP)
1712 DrawUnhighlight(w, DESKTOP);
1714 DrawUnhighlight(w, NOT_DESKTOP);
1716 highlightType = INIT_VALUE;
1717 highlightWidget = NULL;
1720 else if (callback->reason == XmCR_SHADOW)
1721 DrawShadowTh(w, NULL, DESKTOP);
1727 FileViewData * fileViewData,
1728 FileMgrData * fileMgrData,
1729 DesktopRec * desktopRec,
1736 /* If the initiation of the drag occured upon an */
1737 /* already selected icon, check for a multiple drag. */
1739 if ((desktopRec == NULL) && FileIsSelected(fileMgrData, fileViewData))
1740 selectedCount = fileMgrData->selected_file_count;
1741 else if (desktopRec == NULL)
1745 if (DTFileIsSelected(desktopRec, fileViewData))
1747 if(DtWsmGetCurrentWorkspace(XtDisplay(desktopRec->shell),
1748 RootWindowOfScreen(XtScreen(desktopRec->shell)),
1749 &pCurrent) == Success)
1751 wsName = XGetAtomName(XtDisplay(desktopRec->shell), pCurrent);
1752 CleanUpWSName(wsName);
1755 wsName = XtNewString("One");
1757 for(*dt = 0; *dt < desktop_data->numWorkspaces; (*dt)++)
1759 if(strcmp(wsName, desktop_data->workspaceData[*dt]->name) == 0)
1761 selectedCount = desktop_data->workspaceData[*dt]->files_selected;
1771 return(selectedCount);
1782 Display *dpy = XtDisplay(w);
1783 unsigned char flags;
1784 XRectangle pRect, lRect;
1788 Dimension shadowThickness;
1789 Dimension marginWidth, marginHeight;
1791 Boolean minXUndefined, minYUndefined;
1793 dragMask = XCreatePixmap(dpy, RootWindowOfScreen (XtScreenOfObject(w)),
1796 /* Create a GC for drawing 0's into the pixmap */
1797 fillGC = XCreateGC(dpy, dragMask, 0, (XGCValues *) NULL);
1799 XFillRectangle(dpy, dragMask, fillGC, 0, 0, wid, hei);
1801 values.foreground = 1;
1802 XChangeGC(dpy, fillGC, GCForeground, &values);
1804 /* Create the drag pixmap, and the associated mask bitmap */
1805 _DtIconGetIconRects((DtIconGadget)w, &flags, &pRect, &lRect);
1809 minXUndefined = minYUndefined = True;
1810 if (flags & XmPIXMAP_RECT)
1814 minXUndefined = minYUndefined = False;
1816 if (flags & XmLABEL_RECT)
1818 if ((lRect.x < minX) || minXUndefined)
1820 if ((lRect.y < minY) || minYUndefined)
1824 XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
1825 XtSetArg (args[1], XmNmarginWidth, &marginWidth);
1826 XtSetArg (args[2], XmNmarginHeight, &marginHeight);
1827 XtGetValues (w, args, 3);
1829 if (flags & XmPIXMAP_RECT)
1830 XFillRectangle(dpy, dragMask, fillGC,
1831 pRect.x - minX + shadowThickness + marginWidth,
1832 pRect.y - minY + shadowThickness + marginHeight,
1833 pRect.width - 2*marginWidth,
1834 pRect.height - 2*marginHeight);
1835 if (flags & XmLABEL_RECT)
1837 XFillRectangle(dpy, dragMask, fillGC,
1838 lRect.x - minX + shadowThickness + marginWidth,
1839 lRect.y - minY + shadowThickness + marginHeight,
1840 lRect.width - 2*marginWidth,
1841 lRect.height - 2*marginHeight);
1843 XFreeGC(dpy, fillGC);
1851 FileViewData * fileViewData )
1853 XmManagerWidget mw = (XmManagerWidget) XtParent(w);
1854 Widget screen_object = (Widget) XmGetXmScreen(XtScreenOfObject(w));
1857 unsigned int wid, hei, d, junk;
1862 dragPixmap = _DtIconDraw (w, 0, 0, 0, False);
1864 XGetGeometry (XtDisplay(w), dragPixmap,
1865 (Window *) &junk, /* returned root window */
1866 (int *) &junk, (int *) &junk, /* x, y of pixmap */
1867 &wid, &hei, /* width, height of pixmap */
1868 &junk, /* border width */
1872 && ((FileMgrData *)initiating_view)->view == BY_ATTRIBUTES)
1874 XmFontList fontList;
1875 XmString fileNameString;
1876 DtIconGadget g = (DtIconGadget)w;
1879 XtSetArg( args[0], XmNfontList, &fontList );
1880 XtGetValues( fileViewData->widget, args, 1 );
1882 fileNameString = XmStringCreateLocalized( fileViewData->file_data->file_name );
1883 wid = XmStringWidth( fontList, fileNameString )
1884 + g->icon.pixmap_width
1885 + g->icon.cache->margin_width
1886 + g->icon.cache->spacing
1887 + G_ShadowThickness(g)
1888 + G_HighlightThickness(g);
1889 XmStringFree( fileNameString );
1892 dragMask = GetDragIconMask(w, wid, hei);
1895 XtSetArg(args[n], XmNhotX, 0); n++;
1896 XtSetArg(args[n], XmNhotY, 0); n++;
1897 XtSetArg(args[n], XmNwidth, wid); n++;
1898 XtSetArg(args[n], XmNheight, hei); n++;
1899 XtSetArg(args[n], XmNmaxWidth, wid); n++;
1900 XtSetArg(args[n], XmNmaxHeight, hei); n++;
1901 XtSetArg(args[n], XmNdepth, d); n++;
1902 XtSetArg(args[n], XmNpixmap, dragPixmap); n++;
1903 XtSetArg(args[n], XmNmask, dragMask); n++;
1904 XtSetArg(args[n], XmNforeground, mw->core.background_pixel); n++;
1905 XtSetArg(args[n], XmNbackground, mw->manager.foreground); n++;
1906 dragIcon = XtCreateWidget("drag_icon", xmDragIconObjectClass,
1907 screen_object, args, n);
1914 /* The following function is called if the completeMove flag is */
1915 /* set to TRUE. Internally, dtfile sets this to FALSE; thus, only */
1916 /* receiving clients that set this to true will get this function */
1917 /* called for them. */
1918 /* This function will delete the files/dirs that were dropped */
1919 /* on the receiving client. */
1924 FileViewData * fileViewData,
1928 static char *pname = "NewConvertDelete";
1932 DPRINTF(("%s: Entering function\n", pname));
1934 /* fork a background child process to honor the Move Completion */
1937 if (child_pid == -1)
1939 char *msg, *tmpStr, *title;
1941 DBGFORK(("%s: Cannot create child process\n", pname));
1943 tmpStr = GETMESSAGE(11,59,
1944 "Cannot create a child process to delete the dropped files.");
1945 msg = XtNewString(tmpStr);
1946 title = XtNewString((GETMESSAGE(11,58,"Process Create Error")));
1948 /* Display Error message */
1949 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
1956 /* In the Child Process, we simply erase the files */
1957 /* and directories that were dropped on the receiver */
1960 DBGFORK(("%s: child forked\n", pname));
1962 for (i = 0; i < numFiles; i++)
1964 DPRINTF(("%s: Erasing file %s\n", pname, fileList[i]));
1965 EraseObject(fileList[i]);
1968 DBGFORK(("%s: child exiting\n", pname));
1973 DBGFORK(("%s: forked child<%d>\n", pname, child_pid));
1981 FileViewData * fileViewData,
1985 FileMgrData * fileMgrData;
1986 DesktopRec * desktopRec;
1989 char * directoryName;
1993 if(fileViewData != NULL)
1995 (void)IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
1996 selectedCount = GetSelectedCount(fileViewData, fileMgrData, desktopRec, &dt);
2000 /* If fileViewData is NULL, then the file no long exists */
2001 fileMgrData = (FileMgrData *)initiating_view;
2004 selectedCount = fileMgrData->selected_file_count;
2009 if (selectedCount > 1)
2011 for (i = (selectedCount-1); i >= 0; i--)
2015 fileViewData = desktop_data->workspaceData[dt]->
2016 selectedDTWindows[i]->file_view_data;
2017 directoryName = desktop_data->workspaceData[dt]->
2018 selectedDTWindows[i]->dir_linked_to;
2019 fileName = fileViewData->file_data->file_name;
2023 fileViewData = fileMgrData->selection_list[i];
2024 directoryName = ((DirectorySet *)fileViewData->directory_set)->name;
2025 fileName = fileViewData->file_data->file_name;
2027 path = (char *)XtMalloc(strlen(directoryName) + strlen(fileName) + 2);
2028 sprintf(path,"%s/%s", directoryName, fileName);
2030 if ((!desktopRec) && (fileMgrData->toolbox))
2031 path = _DtResolveAppManPath(path,
2032 fileMgrData->restricted_directory);
2034 fileList[i] = DtEliminateDots(path);
2036 *numFiles = selectedCount;
2042 directoryName = desktopRec->dir_linked_to;
2043 fileName = fileViewData->file_data->file_name;
2045 else if(fileViewData)
2047 directoryName = ((DirectorySet *)fileViewData->directory_set)->name;
2048 fileName = fileViewData->file_data->file_name;
2052 directoryName = fileMgrData->current_directory;
2055 path = (char *)XtMalloc(strlen(directoryName) + strlen(fileName) + 2);
2056 sprintf(path,"%s/%s", directoryName, fileName);
2058 if ((!desktopRec) && (fileMgrData->toolbox))
2059 path = _DtResolveAppManPath(path, fileMgrData->restricted_directory);
2061 fileList[0] = DtEliminateDots( path );
2068 printf("NewConvertFileName: returns %d files\n", selectedCount);
2069 for (i = 0; i < selectedCount; i++) {
2070 printf("\t\"%s\"\n", fileList[i]);
2072 if (selectedCount == 0)
2073 printf("\t\"%s\"\n", fileList[0]);
2086 FileViewData * fileViewData = (FileViewData *) client;
2087 DtDndConvertCallback cb = (DtDndConvertCallback) call;
2088 FileMgrData *fmd = (FileMgrData *)initiating_view;
2092 fileViewData = fmd->drag_file_view_data;
2093 fmd->drag_file_view_data = NULL;
2095 if (cb->reason == DtCR_DND_CONVERT_DATA)
2097 if(fmd && !fmd->selected_file_count && fileViewData == NULL)
2099 cb->status = DtDND_FAILURE;
2100 cb->dragData->numItems = 0; /* Just to be on safe side */
2103 NewConvertFileName(w, fileViewData,
2104 cb->dragData->data.files, &cb->dragData->numItems);
2105 } else if (cb->reason == DtCR_DND_CONVERT_DELETE)
2107 NewConvertDelete(w, fileViewData,
2108 cb->dragData->data.files, cb->dragData->numItems);
2113 /* This callback procedure removes the icons when the drop is complete */
2116 DragFinishCB(Widget w, XtPointer client, XtPointer call)
2118 DtDndDragFinishCallback cb = (DtDndDragFinishCallback) call;
2120 static Window root = 0;
2122 DPRINTF(("DragFinishCB: dragActive -> False\n"));
2127 B1DragPossible = False;
2128 B2DragPossible = False;
2129 ProcessBtnUp = False;
2132 XtDestroyWidget(cb->sourceIcon);
2134 DPRINTF (("DragFinishCB: Number of items being freed are %d\n",
2135 cb->dragData->numItems));
2136 for (i = 0; i < cb->dragData->numItems; i++) {
2138 DPRINTF(("DragFinishCB: Freeing %s\n", cb->dragData->data.files[i]));
2139 XtFree(cb->dragData->data.files[i]);
2140 cb->dragData->data.files[i] = NULL;
2149 FileViewData * fileViewData,
2152 static XtCallbackRec fileConvertCB[] = { {FileConvertCB, NULL},
2154 static XtCallbackRec dragFinishCB[] = { {DragFinishCB, NULL},
2156 static XtCallbackRec dropOnRootCB[] = { {DropOnRootCB, NULL},
2161 FileMgrData * fileMgrData = NULL;
2162 DesktopRec * desktopRec = NULL;
2166 unsigned char operations;
2168 if (event->type == INVALID_TYPE) return;
2170 if (fileViewData == NULL) return;
2172 fileConvertCB[0].closure = (XtPointer)fileViewData;
2173 dropOnRootCB[0].closure = (XtPointer)fileViewData;
2175 desktopObj = IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
2176 selectedCount = GetSelectedCount(fileViewData, fileMgrData,
2179 if (selectedCount > 1)
2182 drag_icon = GetDragIcon(w, fileViewData);
2185 XtSetArg(args[numArgs], DtNsourceIcon, drag_icon); numArgs++;
2186 XtSetArg(args[numArgs], DtNdropOnRootCallback, dropOnRootCB); numArgs++;
2188 if ((desktopObj && desktopRec->toolbox) ||
2189 (!desktopObj && fileMgrData->toolbox))
2190 operations = XmDROP_COPY;
2192 operations = XmDROP_MOVE | XmDROP_COPY | XmDROP_LINK;
2194 if (DtDndDragStart(w, event, DtDND_FILENAME_TRANSFER, selectedCount,
2196 fileConvertCB, dragFinishCB, args, numArgs) == NULL) {
2197 DPRINTF(("StartDrag: dragActive -> False\n"));
2202 B1DragPossible = False;
2203 B2DragPossible = False;
2204 ProcessBtnUp = False;
2210 * This function is capable of initiating either a button 1 or button 2
2211 * drag operation; which one gets started is dependent upon which of the
2212 * two state flags (B1DragPossible or B2DragPossible) is set.
2217 FileViewData * fileViewData,
2223 FileMgrData * fileMgrData;
2228 char * directoryName;
2230 XRectangle dragMask[2];
2232 XRectangle pRect, lRect;
2233 unsigned char flags;
2237 Boolean allowDropInInitiatingWindow;
2240 Boolean minXUndefined, minYUndefined;
2241 DesktopRec * desktopRec;
2244 Boolean spaces = False;
2245 Boolean trash = False;
2246 char *tmpStr, *link_path, *ptr;
2248 /* Don't allow multi-drags to start */
2253 B1DragPossible = False;
2254 B2DragPossible = False;
2255 ProcessBtnUp = False;
2261 DPRINTF(("InitiateIconDrag: dragActive -> True\n"));
2263 dragIcon = fileViewData->widget;
2264 (void)IsDesktopPtr(fileViewData, &fileMgrData, &desktopRec);
2266 /* if what we are dragging is a trash item, we want the objects to be
2267 * real objects, not their links
2269 if(fileMgrData == trashFileMgrData && trashFileMgrData != NULL)
2273 * We need to mark the icon which initiated the drag as no longer
2274 * being 'armed', since it will not receive the button up event,
2275 * because we will have release the drag.
2277 iconG = (DtIconGadget)dragIcon;
2278 iconG->icon.armed = False;
2281 * Remember the posistion of the icon pixmap within the drag icon.
2283 dragIconPixmapOffsetX = G_ShadowThickness(iconG) + G_MarginWidth(iconG);
2284 dragIconPixmapOffsetY = G_ShadowThickness(iconG) + G_MarginHeight(iconG);
2288 initiating_view = (XtPointer) NULL;
2289 widget_dragged = dragIcon;
2293 initiating_view = (XtPointer) fileMgrData;
2294 widget_dragged = NULL;
2296 StartDrag(dragIcon, fileViewData, event);
2301 * These are replacements for the corresponding libXm functions. They allow
2302 * us to treat icon gadgets as non-rectangular, so that input processing
2303 * is handled correctly.
2313 CompositeWidget cw = (CompositeWidget)w;
2314 static Region r = NULL;
2315 FileMgrData * file_mgr_data;
2316 Boolean simpleCheck = False;
2318 unsigned char flags;
2319 XRectangle pRect, lRect;
2320 register Widget widget;
2322 file_mgr_data = ReturnDesktopPtr((Widget)cw);
2325 * Tree views and attribute views do not have the non-rectangular
2326 * hotspots, so we can resort to the standard checking algorithm.
2328 if ((file_mgr_data == NULL) ||
2329 (file_mgr_data->show_type != SINGLE_DIRECTORY) ||
2330 (file_mgr_data->view == BY_ATTRIBUTES))
2335 for (i = 0; i < cw->composite.num_children; i++)
2337 widget = cw->composite.children[i];
2339 if (XmIsGadget(widget) && XtIsManaged(widget))
2343 if (x >= widget->core.x && y >= widget->core.y &&
2344 (Position) x < (Position) (widget->core.x + widget->core.width) &&
2345 (Position) y < (Position) (widget->core.y + widget->core.height))
2347 return ((XmGadget) widget);
2352 /* Initialize the region to be empty */
2354 r = XCreateRegion();
2356 XSubtractRegion(r, r, r);
2358 _DtIconGetIconRects((DtIconGadget)widget, &flags, &pRect, &lRect);
2360 if (flags & XmPIXMAP_RECT)
2361 XUnionRectWithRegion(&pRect, r, r);
2363 if (flags & XmLABEL_RECT)
2364 XUnionRectWithRegion(&lRect, r, r);
2366 if (XPointInRegion(r, x, y))
2367 return ((XmGadget) widget);
2377 * This function is identical to the libXm version; it needs to be here
2378 * so that it will call our InputInGadget() instead of the libXm
2379 * version, which was bundled together with it in GadgetUtil.c
2390 gadget = InputInGadget (cw, x, y);
2392 if (!gadget || !XtIsSensitive ((Widget)gadget))
2394 return ((XmGadget) NULL);
2402 * This function processes motion events anytime a B1 or B2 drag operation
2403 * has the potential of starting for a file icon. When the drag threshold
2404 * is surpassed, a drag operation will be started.
2410 XtPointer clientData,
2414 FileViewData * fileViewData = NULL;
2415 Position rootX, rootY;
2416 DirectorySet * directoryData = NULL;
2421 if ((B1DragPossible && (event->xmotion.state & Button1Mask)) ||
2422 (B2DragPossible && (event->xmotion.state & Button2Mask)))
2424 /* Have we passed the drag threshold? */
2425 diffX = initialDragX - event->xmotion.x;
2426 diffY = initialDragY - event->xmotion.y;
2428 if ((ABS(diffX) >= dragThreshold) || (ABS(diffY) >= dragThreshold))
2430 /* Map the original (x,y) into a gadget Id */
2431 if (dragIcon =(Widget)InputForGadget(w, initialDragX, initialDragY))
2433 /* Map the icon into its fileViewData structure */
2434 /* Check for desktop icon first */
2435 for (i = 0, fileViewData = NULL; i<desktop_data->numIconsUsed; i++)
2437 if (desktop_data->desktopWindows[i]->iconGadget == dragIcon)
2439 fileViewData = desktop_data->desktopWindows[i]->file_view_data;
2443 if (fileViewData == NULL)
2445 /* Not a desktop icon */
2446 XtSetArg(args[0], XmNuserData, (XtPointer) &directoryData);
2447 XtGetValues(dragIcon, args, 1);
2448 for (i = 0; i < directoryData->file_count; i++)
2450 if (directoryData->file_view_data[i]->widget == dragIcon &&
2451 directoryData->file_view_data[i]->displayed)
2453 fileViewData = directoryData->file_view_data[i];
2460 /* Map to root coordinates */
2461 XtTranslateCoords(w, (Position)initialDragX, (Position)initialDragY,
2467 fmd = (FileMgrData *)(directoryData->file_mgr_data);
2469 fmd->drag_file_view_data = fileViewData;
2471 InitiateIconDrag(fileViewData, (int)rootX, (int)rootY, event);
2476 * The file manager view must have changed between the time
2477 * the user did the button down, and the time they moved
2478 * enough to pass the drag threshold, because there is now
2479 * no icon located where the drag initiated. Therefore,
2480 * we'll just clean up, because there is much else we can do.
2482 B1DragPossible = False;
2483 B2DragPossible = False;
2484 ProcessBtnUp = False;
2487 /* Force the button up to be ignored */
2495 /* Compute position of desktop icon shell for given a drop position */
2497 PositionDesktopIcon(
2504 int pixmap_offset_x;
2505 int pixmap_offset_y;
2509 * We want to position the shell, so that the icon pixmap in the icon
2510 * gadget will appear at the same spot that the icon pixmap of the drag
2511 * cursor was when the drop occurred.
2514 /* First we caculate the top left corner of the drag pixmap by adding
2515 * the offset of the pixmap within the drag icon to the drop position. */
2516 drop_x += dragIconPixmapOffsetX;
2517 drop_y += dragIconPixmapOffsetY;
2519 /* In order to calculate the correct position of the dektop icon shell
2520 * such that the pixmap within the icon gadget will end up at the desired
2521 * position, we need to know the offset of the gadget's icon pixmap relative
2522 * to the desktop icon shell.
2523 * Since a desktop icon consists a frame widget, a drawing area and an
2524 * icon gadget (all within a popup shell), this offset is computed by adding
2525 * the frame width and and drawing area margins to the icon gadget's
2526 * highlight thickness.
2527 * The frame width is 3 and and and the drawing area margin width is 1
2528 * (both hardcoded in Desktop.c). We determine the remaining components
2529 * by looking at one of the existing desktop icon gadgets. */
2530 if (desktop_data != NULL &&
2531 desktop_data->numIconsUsed + desktop_data->numCachedIcons > 0)
2533 g = (DtIconGadget) desktop_data->desktopWindows[0]->iconGadget;
2535 pixmap_offset_y = 3 + 1 + G_HighlightThickness(g) + G_ShadowThickness(g);
2536 pixmap_offset_x += G_MarginWidth(g);
2537 pixmap_offset_y += G_MarginHeight(g);
2541 /* don't have an icon gadget; assume default values */
2542 pixmap_offset_x = pixmap_offset_y = 3 + 1 + 2 + 2 + 2;
2545 /* Finally, calculate the position of the dektop icon shell by
2546 * subtracting the offset of the gadget's icon pixmap from the
2547 * desired pixmap position */
2548 *root_x = drop_x - pixmap_offset_x;
2549 *root_y = drop_y - pixmap_offset_y;
2553 /* Code to reposition a desktop icon after a drag */
2556 RelocateDesktopIcon(
2557 DesktopRec * desktopRec,
2563 Dimension width, height;
2565 XSizeHints wmSizeHints;
2567 pu_shell = desktopRec->shell;
2570 XtSetArg (args[0], XmNwidth, &width);
2571 XtSetArg (args[1], XmNheight, &height);
2572 XtGetValues(pu_shell, args, 2);
2574 RegisterInGrid((int)width, (int)height,
2577 desktopRec->workspace_num,
2580 XtSetArg (args[0], XmNx, root_x);
2581 XtSetArg (args[1], XmNy, root_y);
2583 XtSetValues (pu_shell, args, 2);
2584 XRaiseWindow(XtDisplay(pu_shell), XtWindow(pu_shell));
2585 XSync(XtDisplay(pu_shell), False);
2587 RegisterInGrid((int)width, (int)height, root_x, root_y,
2588 desktopRec->workspace_num, True);
2590 desktopRec->root_x = root_x;
2591 desktopRec->root_y = root_y;
2592 SaveDesktopInfo(NORMAL_RESTORE);
2596 /************************************************************************
2599 * Loop through the file selection list to see if the specified
2602 ************************************************************************/
2606 FileMgrData *file_mgr_data,
2607 FileViewData *file_view_data )
2609 return file_view_data->selected;
2615 /************************************************************************
2618 * Display the icon representing file_data as selected.
2620 ************************************************************************/
2624 FileMgrData *file_mgr_data,
2625 FileViewData *file_view_data )
2628 file_view_data->selected = True;
2630 /* if this file has an up-to-date gadget, change its colors */
2631 if (!file_view_data->need_update)
2633 if (file_view_data->file_data->link == NULL)
2634 SetToSelectColors (file_view_data->widget,
2635 (Widget)((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window,
2638 SetToSelectColors (file_view_data->widget,
2639 (Widget)((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window,
2641 if (PositioningEnabledInView(file_mgr_data))
2642 RedrawOneGadget(file_view_data->widget, NULL, NULL);
2646 /************************************************************************
2649 * Display the icon representing file_data as not selected.
2651 ************************************************************************/
2655 FileMgrData *file_mgr_data,
2656 FileViewData *file_view_data )
2659 file_view_data->selected = False;
2661 /* if this file has an up-to-date gadget, change its colors */
2662 if (!file_view_data->need_update)
2664 if (file_view_data->file_data->link != NULL)
2665 SetToNormalColors (file_view_data->widget,
2666 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->file_window,
2667 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->main,
2670 SetToNormalColors (file_view_data->widget,
2671 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->file_window,
2672 ((FileMgrRec *)(file_mgr_data->file_mgr_rec))->main,
2675 if (PositioningEnabledInView(file_mgr_data))
2676 RedrawOneGadget(file_view_data->widget, NULL, NULL);
2680 /************************************************************************
2683 * Add the file to the selection list.
2685 ************************************************************************/
2689 FileMgrData *file_mgr_data,
2690 FileViewData *file_view_data )
2692 int selection_count;
2695 /* Add to the front of the selection list */
2696 selection_count = file_mgr_data->selected_file_count;
2697 file_mgr_data->selected_file_count++;
2699 file_mgr_data->selection_list = (FileViewData **)
2700 XtRealloc ((char *) file_mgr_data->selection_list,
2701 sizeof(FileViewData *) * (selection_count + 2));
2703 for (i = file_mgr_data->selected_file_count; i > 0; i--)
2704 file_mgr_data->selection_list[i] = file_mgr_data->selection_list[i-1];
2706 file_mgr_data->selection_list[0] = file_view_data;
2709 SetFileSelected(file_mgr_data, file_view_data);
2715 /************************************************************************
2718 * Remove the file from the selection list.
2720 ************************************************************************/
2724 FileMgrData *file_mgr_data,
2725 FileViewData *file_view_data,
2728 int selection_count;
2733 selection_count = file_mgr_data->selected_file_count;
2734 file_mgr_data->selected_file_count--;
2736 for (i = 0; i < selection_count; i++)
2737 if (file_mgr_data->selection_list[i] == file_view_data)
2740 for (j = i; j < selection_count - 1; j++)
2741 file_mgr_data->selection_list[j] = file_mgr_data->selection_list[j + 1];
2743 file_mgr_data->selection_list = (FileViewData **)
2744 XtRealloc ((char *) file_mgr_data->selection_list,
2745 sizeof(FileViewData *) * selection_count);
2746 file_mgr_data->selection_list[selection_count - 1] = NULL;
2749 SetFileUnselected(file_mgr_data, file_view_data);
2751 file_view_data->selected = False;
2757 /************************************************************************
2760 * Unselect all of the selected icons within the file manager data
2762 ************************************************************************/
2766 FileMgrData *file_mgr_data )
2768 FileViewData * file_view_data;
2769 register int i, j, k;
2771 FileViewData ** repaint_list;
2774 /* Get the color to reset the icons. */
2776 /* Loop through the selection set, resetting the visuals for */
2777 /* each selected icon. */
2779 if (!PositioningEnabledInView(file_mgr_data))
2781 for (i = 0; i < file_mgr_data->selected_file_count; i++)
2783 file_view_data = file_mgr_data->selection_list[i];
2784 SetFileUnselected(file_mgr_data, file_view_data);
2787 else if (file_mgr_data->selected_file_count > 0)
2790 * We can't simply redraw the selected files; we must also redraw
2791 * any unselected files which are higher on the stacking order.
2794 repaint_list = (FileViewData **)XtMalloc(sizeof(FileViewData *) *
2795 file_mgr_data->selected_file_count);
2797 /* Order the objects to be unselected */
2798 for (i = 0; i < file_mgr_data->selected_file_count; i++)
2800 file_view_data = file_mgr_data->selection_list[i];
2801 for (j = 0; j < i; j++)
2803 if (file_view_data->position_info->stacking_order <
2804 repaint_list[j]->position_info->stacking_order)
2806 /* Insert here, pushing down all lower entries */
2807 for (k = file_mgr_data->selected_file_count - 1; k > j; k--)
2808 repaint_list[k] = repaint_list[k-1];
2810 repaint_list[j] = file_view_data;
2815 /* Insert at end, if necessary */
2817 repaint_list[i] = file_view_data;
2820 /* Start the redraw process */
2821 i = file_mgr_data->selected_file_count - 1;
2822 bottom = repaint_list[i]->position_info;
2826 if ((i >= 0) && (bottom == repaint_list[i]->position_info))
2828 /* Unselect this object */
2829 SetFileUnselected(file_mgr_data, bottom->file_view_data);
2832 if(bottom->file_view_data != NULL &&
2833 !bottom->file_view_data->need_update)
2835 RedrawOneGadget(bottom->file_view_data->widget, NULL, NULL);
2837 bottom = bottom->prev;
2840 XtFree((char *)repaint_list);
2841 repaint_list = NULL;
2844 if (file_mgr_data->selection_list != NULL)
2846 XtFree ((char *) file_mgr_data->selection_list);
2847 file_mgr_data->selection_list = NULL;
2850 file_mgr_data->selection_list =
2851 (FileViewData **) XtMalloc (sizeof (FileViewData *));
2852 file_mgr_data->selection_list[0] = NULL;
2853 file_mgr_data->selected_file_count = 0;
2860 /************************************************************************
2863 * Select all of the files within the file manager data.
2865 ************************************************************************/
2869 FileMgrData *file_mgr_data )
2871 DirectorySet * directory_data;
2872 FileViewData ** order_list;
2873 int directory_count;
2874 int selection_count;
2878 FileViewData ** selection_list;
2881 if (PositioningEnabledInView(file_mgr_data))
2883 /* Force selection list order to match stacking order */
2884 selection_list = (FileViewData **)XtMalloc(sizeof(FileViewData *) *
2885 (file_mgr_data->num_objects));
2887 top = GetTopOfStack(file_mgr_data);
2888 selection_count = 0;
2889 for (i = 0; i < file_mgr_data->num_objects; i++)
2891 /* If the there isn't file_view_data for it
2892 Or if it's a parent folder (..go up)
2893 Don't bother to select them
2895 if( top->file_view_data != NULL
2896 && strcmp( top->name, ".." ) != 0 )
2898 selection_list[selection_count] = top->file_view_data;
2903 selection_list[selection_count] = NULL;
2905 /* Force redraw in bottom to top order */
2906 for (i = selection_count - 1; i >= 0; i--)
2908 if (!FileIsSelected(file_mgr_data, selection_list[i]))
2909 SetFileSelected(file_mgr_data, selection_list[i]);
2912 /* Free old selection list, and save new one */
2913 XtFree ((char *) file_mgr_data->selection_list);
2914 file_mgr_data->selection_list = selection_list;
2918 /* Free up any current selection and get the selection color. */
2920 if (file_mgr_data->selection_list != NULL)
2922 DeselectAllFiles( file_mgr_data );
2925 if (file_mgr_data->show_type == SINGLE_DIRECTORY)
2926 directory_count = 1;
2928 directory_count = file_mgr_data->directory_count;
2931 /* Loop through the set of directories checking each file view */
2932 /* structure to see if the icon is filtered. If not, select it */
2933 /* and increment the selection count. */
2935 selection_count = 0;
2937 /* For tree mode the index has to be -1 */
2939 i = (file_mgr_data->show_type == MULTIPLE_DIRECTORY)?-1:0;
2940 for (; i < directory_count; i++)
2942 directory_data = file_mgr_data->directory_set[i];
2943 order_list = directory_data->order_list;
2945 for (j = 0; j < directory_data->file_count; j++)
2947 /* If the file is being filtered out
2948 Or if it's a parent folder (..go up)
2949 Don't bother to select them
2951 if (order_list[j]->filtered == True
2952 || strcmp( order_list[j]->file_data->file_name, ".." ) == 0 )
2957 file_mgr_data->selection_list = (FileViewData **)
2958 XtRealloc ((char *) file_mgr_data->selection_list,
2959 sizeof(FileViewData *) * (selection_count + 1));
2961 file_mgr_data->selection_list[selection_count] = NULL;
2962 file_mgr_data->selection_list[selection_count - 1] = order_list[j];
2963 SetFileSelected(file_mgr_data, order_list[j]);
2968 file_mgr_data->selected_file_count = selection_count;
2970 if(file_mgr_data != trashFileMgrData)
2972 if (selection_count == 0)
2973 ActivateNoSelect ((FileMgrRec *)file_mgr_data->file_mgr_rec);
2974 else if (selection_count == 1)
2976 ActivateSingleSelect ((FileMgrRec *)file_mgr_data->file_mgr_rec,
2977 file_mgr_data->selection_list[0]->file_data->logical_type);
2980 ActivateMultipleSelect ((FileMgrRec *)file_mgr_data->file_mgr_rec);
2987 /************************************************************************
2990 * Set a single icon widget to selected colors.
2992 ************************************************************************/
3001 Pixel background_color;
3005 /* Get the select color to be used as the background of */
3006 /* the icon gadgets. */
3009 XtSetArg (args[j], XmNbackground, &background_color); j++;
3010 XtGetValues (file_window, args, j);
3013 if (background_color == white_pixel)
3015 XtSetArg (args[j], XmNbackground, black_pixel); j++;
3016 XtSetArg (args[j], XmNforeground, white_pixel); j++;
3018 else if (background_color == black_pixel)
3020 XtSetArg (args[j], XmNbackground, white_pixel); j++;
3021 XtSetArg (args[j], XmNforeground, black_pixel); j++;
3025 XtSetArg (args[j], XmNbackground, white_pixel); j++;
3026 XtSetArg (args[j], XmNforeground, black_pixel); j++;
3029 XtSetValues (widget, args, j);
3032 /************************************************************************
3035 * Set a single icon widget to normal colors.
3037 ************************************************************************/
3042 Widget bg_fg_colors,
3043 Widget top_shadow_colors,
3047 Pixel background_color;
3048 Pixel foreground_color;
3049 Pixel pixmap_background;
3050 DtIconGadget new = (DtIconGadget)widget;
3053 /* Get the colors to be used for drawing the icons */
3056 XtSetArg (args[j], XmNbackground, &background_color); j++;
3057 XtSetArg (args[j], XmNforeground, &foreground_color); j++;
3058 XtGetValues (bg_fg_colors, args, j);
3061 XtSetArg (args[j], XmNtopShadowColor, &pixmap_background); j++;
3062 XtGetValues (top_shadow_colors, args, j);
3066 if(type == LINK_FILE)
3067 XtSetArg (args[j], XmNforeground, pixmap_background); j++;
3070 XtSetArg (args[j], XmNforeground, foreground_color); j++;
3072 if (background_color == white_pixel)
3074 XtSetArg (args[j], XmNbackground, white_pixel); j++;
3076 else if (background_color == black_pixel)
3078 XtSetArg (args[j], XmNbackground, black_pixel); j++;
3082 XtSetArg (args[j], XmNbackground, background_color); j++;
3085 /* we want to make sure the armed value is off so that it will get
3087 if(new->icon.armed == True)
3089 new->icon.armed = False;
3092 XtSetValues (widget, args, j);
3097 * When a text widget is destroyed, we need to free up the string we
3098 * attached as userData.
3104 XtPointer client_data,
3105 XtPointer call_data)
3110 XtSetArg(args[0], XmNuserData, &str);
3111 XtGetValues(w, args, 1);
3118 GetInsertPosition( x1, x2, fontList, name )
3121 XmFontList fontList;
3124 GetInsertPosition( int x1, int x2, XmFontList fontList, char * name )
3127 int i, width, stringWidth;
3132 #endif /* MULTIBYTE */
3139 while ((len = mblen(tmp, MB_CUR_MAX)) > 0)
3140 #else /* MULTIBYTE */
3141 for( tmp = name + 1, i = 0;
3144 #endif /* MULTIBYTE */
3150 #endif /* MULTIBYTE */
3154 string = XmStringCreateLocalized( name );
3155 stringWidth = XmStringWidth( fontList, string );
3156 XmStringFree( string );
3158 if( stringWidth > width )
3163 #endif /* MULTIBYTE */
3170 CreateNameChangeDialog (
3172 FileViewData *file_view_data,
3173 XtPointer client_data,
3176 XRectangle textExtent;
3177 FileMgrData * file_mgr_data;
3178 DesktopRec * desktopWindow;
3179 Widget parent = XtParent(w);
3184 Widget frame, shell;
3185 Dimension fHeight, sHeight;
3187 Dimension tWidth, tHeight;
3190 XtTranslations trans_table;
3191 XmFontList fontList;
3192 Dimension stringWidth;
3193 XmString fileNameString;
3194 char tmpBuf[MAX_PATH];
3196 _DtIconGetTextExtent_r(w, &textExtent);
3200 char buf[MAXPATHLEN];
3202 desktopWindow = (DesktopRec *)client_data;
3203 if(desktopWindow->text != NULL)
3206 sprintf( buf, "%s:%s", home_host_name, root_title );
3209 * If the object is on the DESKTOP and its name is root_title, then
3210 * the user can't rename it.
3212 if( strcmp( buf, desktopWindow->title ) == 0
3213 && strcmp( desktopWindow->dir_linked_to, "/" ) == 0
3214 && strcmp( desktopWindow->file_name, "." ) == 0 )
3218 file_mgr_data = (FileMgrData *)client_data;
3220 /* if the object is in the trash, can't rename it */
3222 && file_mgr_data == trashFileMgrData )
3225 /* if the object is an action, can't rename it */
3226 if( DtDtsDataTypeIsAction( file_view_data->file_data->logical_type ) )
3228 char *tmpStr, *title, *msg;
3230 tmpStr = GETMESSAGE(10, 39, "Rename error");
3231 title = XtNewString(tmpStr);
3232 tmpStr = GETMESSAGE(10, 40, "This object is an Action.\nAction icon labels cannot be directly renamed." );
3233 msg = XtNewString(tmpStr);
3235 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
3240 else if(file_view_data->file_data->action_name)
3242 char *tmpStr, *title, *msg;
3244 tmpStr = GETMESSAGE(10, 39, "Rename error");
3245 title = XtNewString(tmpStr);
3246 tmpStr = GETMESSAGE(11, 32, "Cannot rename %s");
3247 msg = XtMalloc(strlen(tmpStr)+strlen(file_view_data->file_data->
3249 sprintf(msg,tmpStr,file_view_data->file_data->action_name);
3251 _DtMessage(toplevel, title, msg, NULL, HelpRequestCB);
3258 * The selected objects name is attached as 'userData' to text field,
3259 * to aid us in mapping back to the original object later.
3261 if( type == DESKTOP &&
3262 ( (strcmp(".", file_view_data->file_data->file_name) == 0)
3263 || strcmp("..", file_view_data->file_data->file_name) == 0) )
3265 name = XtNewString(desktopWindow->file_name);
3267 else if ( strcmp(".", file_view_data->file_data->file_name) == 0 ||
3268 strcmp("..", file_view_data->file_data->file_name) == 0 )
3273 name = XtNewString(file_view_data->file_data->file_name);
3275 /* set up translations in main edit widget */
3276 trans_table = XtParseTranslationTable(translations_escape);
3278 /* We need to set the width of the text widget.
3279 Can't use XmNcolumns because of the double-byte.
3282 XtSetArg( args[0], XmNfontList, &fontList );
3283 XtGetValues( file_view_data->widget, args, 1 );
3285 sprintf( tmpBuf, "%s ", file_view_data->file_data->file_name );
3286 fileNameString = XmStringCreateLocalized( tmpBuf );
3287 stringWidth = XmStringWidth( fontList, fileNameString );
3288 XmStringFree( fileNameString );
3291 XtSetArg(args[n], XmNuserData, name); n++;
3292 XtSetArg(args[n], XmNmarginHeight, 0); n++;
3293 XtSetArg(args[n], XmNmarginWidth, 0); n++;
3294 XtSetArg(args[n], XmNvalue, name); n++;
3295 XtSetArg(args[n], XmNwidth, stringWidth); n++;
3300 text = XmCreateTextField(parent, "nameChangeT_DT", args, n);
3301 XtAddCallback (text, XmNactivateCallback, ChangeIconNameDT,
3302 (XtPointer)desktopWindow);
3303 XtAddCallback(text, XmNhelpCallback, (XtCallbackProc)DTHelpRequestCB,
3304 HELP_NAMECHANGE_DIALOG_STR);
3305 desktopWindow->text = text;
3307 frame = XtParent(parent);
3308 shell = XtParent(frame);
3309 XtSetArg(args[0], XmNheight, &fHeight);
3310 XtGetValues(frame, args, 1);
3311 XtSetArg(args[0], XmNheight, &sHeight);
3312 XtGetValues(shell, args, 1);
3316 text = XmCreateTextField(parent, "nameChangeT", args, n);
3317 file_mgr_data->renaming = file_view_data;
3318 XtAddCallback (text, XmNmotionVerifyCallback,
3319 (XtCallbackProc)ChangeIconName,
3320 (XtPointer)file_mgr_data);
3321 XtAddCallback (text, XmNmodifyVerifyCallback,
3322 (XtCallbackProc)ChangeIconName,
3323 (XtPointer)file_mgr_data);
3324 XtAddCallback (text, XmNactivateCallback,
3325 (XtCallbackProc)ChangeIconName,
3326 (XtPointer)file_mgr_data);
3327 XtAddCallback(text, XmNhelpCallback, (XtCallbackProc)HelpRequestCB,
3328 HELP_NAMECHANGE_DIALOG_STR);
3331 XtAddCallback (text, XmNdestroyCallback, DestroyIconName, (XtPointer)NULL);
3333 /* set up translations in main edit widget */
3334 XtOverrideTranslations(text, trans_table);
3336 if(type == DESKTOP && sHeight > fHeight) {
3337 /* status area has been attached in multi-byte case */
3343 y = textExtent.y - (Dimension)(text->core.height - textExtent.height);
3347 Window rootWindow, childWindow;
3348 int pX, pY, rootX, rootY, insertPosition;
3351 XQueryPointer( XtDisplay( parent ), XtWindow( file_view_data->widget ),
3352 &rootWindow, &childWindow, &rootX, &rootY, &pX, &pY,
3355 insertPosition = strlen( name );
3358 if( type != DESKTOP )
3360 if( pX > (int) x && pX < (int) x + (int) stringWidth )
3361 insertPosition = GetInsertPosition( x, pX, fontList, name );
3363 insertPosition = strlen( name );
3366 insertPosition = GetInsertPosition( x, x + pX, fontList, name );
3369 XtSetArg( args[n], XmNcursorPosition, insertPosition); n++;
3370 XtSetArg( args[n], XmNx, x); n++;
3371 XtSetArg( args[n], XmNy, y); n++;
3372 XtSetValues (text, args, n);
3379 Dimension shadowThickness;
3381 unsigned char flags;
3383 XtSetArg (args[0], XmNwidth, &tWidth);
3384 XtSetArg (args[1], XmNheight, &tHeight);
3385 XtGetValues (text, args, 2);
3387 XtSetArg (args[0], XmNshadowThickness, &shadowThickness);
3388 XtGetValues (desktopWindow->iconGadget, args, 1);
3390 _DtIconGetIconRects((DtIconGadget)desktopWindow->iconGadget,
3391 &flags, &rect[0], &rect[1]);
3395 rect[0].width += 2*shadowThickness;
3396 rect[0].height += 2*shadowThickness;
3399 if(type == DESKTOP && sHeight > fHeight) {
3400 /* status area has been attached in multi-byte case */
3403 rect[1].width = 2*shadowThickness + tWidth;
3404 rect[1].height = sHeight - y - 1;
3409 rect[1].width = shadowThickness + tWidth;
3410 rect[1].height = tHeight;
3413 if(rect[0].width > rect[1].width)
3414 rect[1].width = rect[0].width;
3416 XShapeCombineRectangles(XtDisplay(desktopWindow->shell),
3417 XtWindow(desktopWindow->shell),
3418 ShapeBounding, 0, 0, &rect[0], 2,
3419 ShapeSet, Unsorted);
3422 XtManageChild(text);
3423 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
3427 FileMgrRec *file_mgr_rec;
3429 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3430 file_mgr_rec->menuStates &= ~RENAME;
3434 /************************************************************************
3436 * SavePositionalData
3437 * Save the desktop icon positional data.
3439 ************************************************************************/
3442 SavePositionalData (
3444 FileMgrData * file_mgr_data,
3449 FILE * fd_stream = fdopen(fd, "w");
3450 ObjectPosition * ptr;
3453 if(file_mgr_data->positionEnabled == RANDOM_ON &&
3454 file_mgr_data->object_positions &&
3455 file_mgr_data->show_type == SINGLE_DIRECTORY &&
3456 file_mgr_data->host != NULL)
3458 /* Number of object positions */
3459 fprintf(fd_stream, "*%s.%s.%s.%s: %d\n#\n", name_list[0], name_list[1],
3460 name, "num_positions", file_mgr_data->num_objects);
3462 for (i = 0; i < file_mgr_data->num_objects; i++)
3464 ptr = file_mgr_data->object_positions[i];
3465 fprintf(fd_stream, "*%s.%s.%s.%s%d: %s %d %d %d\n",
3466 name_list[0], name_list[1], name, "object", i,
3470 ptr->stacking_order);
3475 /* Number of object positions */
3476 fprintf(fd_stream, "*%s.%s.%s.%s: %d\n#\n", name_list[0], name_list[1],
3477 name, "num_positions", 0);
3485 /************************************************************************
3487 * RestorePositionalData
3488 * Restore the desktop icon positional data.
3490 ************************************************************************/
3493 RestorePositionalData (
3496 FileMgrData * file_mgr_data,
3499 XrmName xrm_name[10];
3502 char objectName[20];
3503 XrmRepresentation rep_type;
3508 ObjectPosition * ptr;
3512 while (name_list[i])
3514 xrm_name[i] = XrmStringToQuark(name_list[i]);
3517 xrm_name[i++] = XrmStringToQuark(name);
3518 xrm_name[i] = XrmStringToQuark("num_positions");
3519 xrm_name[i+1] = '\0';
3521 /* Find out how many objects there are to be loaded */
3522 file_mgr_data->object_positions = NULL;
3524 if (XrmQGetResource (db, xrm_name, NULL, &rep_type, &value))
3526 if ((num_objects = atoi (value.addr)) <= 0)
3530 file_mgr_data->object_positions = (ObjectPosition **)XtMalloc(
3531 sizeof(ObjectPosition *) * num_objects);
3535 file_mgr_data->num_objects = num_objects;
3537 for (j = 0; j < num_objects; j++)
3539 sprintf(objectName, "object%d", j);
3540 xrm_name[i] = XrmStringToQuark(objectName);
3541 ptr = file_mgr_data->object_positions[j] = (ObjectPosition *)
3542 XtMalloc(sizeof(ObjectPosition));
3544 XrmQGetResource (db, xrm_name, NULL, &rep_type, &value);
3545 str = (char *)value.addr;
3546 obj_name = XtMalloc(strlen(str) + 1);
3547 sscanf((char *)value.addr, "%s %d %d %d", obj_name, &x, &y, &s_order);
3548 ptr->name = obj_name;
3551 ptr->stacking_order = s_order;
3552 ptr->in_use = False;
3553 ptr->late_bind = False;
3554 ptr->file_view_data = NULL;
3559 /* Repair all of the next and prev pointers */
3560 RepairStackingPointers(file_mgr_data);
3566 FileMgrData * file_mgr_data)
3569 XmManagerWidget file_window;
3571 FileMgrRec * file_mgr_rec;
3573 file_mgr_data->renaming = NULL;
3575 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3576 file_window = (XmManagerWidget) file_mgr_rec->file_window;
3577 for (i = 0; i < file_window->composite.num_children; i++)
3579 if (XmIsTextField(file_window->composite.children[i]) &&
3580 !file_window->composite.children[i]->core.being_destroyed)
3582 XtUnmanageChild(file_window->composite.children[i]);
3583 XtDestroyWidget(file_window->composite.children[i]);
3592 FileMgrData * file_mgr_data)
3595 FileMgrRec * file_mgr_rec;
3598 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
3600 XtSetArg (args[0], XmNallowShellResize, False);
3601 XtSetValues(file_mgr_rec->shell, args, 1);
3603 XtUnmanageChild(file_mgr_rec->current_directory_text);
3605 XtSetArg (args[0], XmNallowShellResize, True);
3606 XtSetValues(file_mgr_rec->shell, args, 1);
3608 file_mgr_data->fast_cd_enabled = False;
3613 * Function to force a redraw of a single gadget.
3623 if (child->core.widget_class->core_class.expose)
3624 (*(child->core.widget_class->core_class.expose))(child, event, region);
3629 * Given a region describing the area to be repainted, repaint all icons,
3630 * in bottom to top order, which fall into this region.
3635 FileMgrData * file_mgr_data,
3641 ObjectPosition * bottom = GetBottomOfStack(file_mgr_data);
3643 /* Redraw all affected gadgets */
3646 if (!bottom->late_bind)
3648 if (bottom->file_view_data != NULL &&
3649 !bottom->file_view_data->need_update)
3651 child = bottom->file_view_data->widget;
3652 if (XRectInRegion(region, child->core.x, child->core.y,
3653 child->core.width, child->core.height))
3655 RedrawOneGadget(child, event, region);
3660 bottom = bottom->prev;
3666 * This function will extract all exposure events intended for this file
3667 * window, combine them into a single region, and then determine which of
3668 * the file icons need to be redrawn. It is a two step process, as
3669 * described by the comments in the code.
3673 RedisplayUsingStackingOrder (
3674 FileMgrData * file_mgr_data,
3676 register XEvent *event,
3680 register Widget child;
3681 FileViewData * file_view_data;
3682 ObjectPosition * bottom;
3683 ObjectPosition * top;
3684 Region redrawRegion = XCreateRegion();
3687 int numChildren = 0;
3688 Widget * children = NULL;
3689 Region widget_region;
3692 /* Get the initial region to redraw */
3694 XUnionRegion(redrawRegion, region, redrawRegion);
3697 rect.x = event->xexpose.x;
3698 rect.y = event->xexpose.y;
3699 rect.height = event->xexpose.height;
3700 rect.width = event->xexpose.width;
3702 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
3706 * Capture and encompass any other exposure events which are destined for
3707 * us, but are waiting in the wings.
3709 while (XCheckWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask, &expEvent))
3711 rect.x = expEvent.xexpose.x;
3712 rect.y = expEvent.xexpose.y;
3713 rect.height = expEvent.xexpose.height;
3714 rect.width = expEvent.xexpose.width;
3716 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
3719 /* Nothing to do if the redraw region is empty */
3720 if (XEmptyRegion(redrawRegion))
3722 XDestroyRegion(redrawRegion);
3727 * Starting at the top of the stack, find any items which fall into
3728 * the redraw region. As items are found which need to be redrawn,
3729 * subtract them from the redraw region, so that any items lower on the
3730 * stack which might be under these gadgets, but are within the region,
3733 * The second phase is to start at the bottom of the stack, and start
3734 * redrawing the gadgets which fell into the region, along with any
3735 * other gadgets on top of these (since they too now need to be redrawn.
3737 top = GetTopOfStack(file_mgr_data);
3743 if (!top->late_bind)
3745 file_view_data = top->file_view_data;
3746 if(file_view_data != NULL)
3748 child = file_view_data->widget;
3750 if (child && XmIsGadget(child) && XtIsManaged(child))
3752 widget_region = XCreateRegion();
3753 WidgetRectToRegion(file_mgr_data, child, widget_region);
3754 XIntersectRegion(redrawRegion, widget_region, widget_region);
3755 if (!XEmptyRegion(widget_region))
3757 XSubtractRegion(redrawRegion, widget_region, redrawRegion);
3758 children = (Widget *)XtRealloc((char *)children,
3759 (numChildren + 1) * sizeof(Widget));
3760 children[numChildren] = child;
3763 XDestroyRegion(widget_region);
3767 top = (ObjectPosition *)top->next;
3770 /* Now, start redrawing, in bottom to top order */
3771 bottom = GetBottomOfStack(file_mgr_data);
3775 if (!bottom->late_bind)
3777 file_view_data = bottom->file_view_data;
3778 if(file_view_data != NULL)
3780 child = file_view_data->widget;
3782 if (child && XmIsGadget(child) && XtIsManaged(child))
3784 widget_region = XCreateRegion();
3785 WidgetRectToRegion(file_mgr_data, child, widget_region);
3786 if ((numChildren >= 0) && (children[numChildren] == child))
3788 XUnionRegion(redrawRegion, widget_region, redrawRegion);
3789 RedrawOneGadget(child, event, redrawRegion);
3794 /* Do we overlap something which was previously redrawn? */
3795 tmp_region = XCreateRegion();
3796 XIntersectRegion(redrawRegion, widget_region, tmp_region);
3797 if (!XEmptyRegion(tmp_region))
3799 XUnionRegion(redrawRegion, widget_region, redrawRegion);
3800 RedrawOneGadget(child, event, redrawRegion);
3802 XDestroyRegion(tmp_region);
3804 XDestroyRegion(widget_region);
3808 bottom = (ObjectPosition *)bottom->prev;
3811 XDestroyRegion(redrawRegion);
3812 XtFree((char *)children);
3818 * This is the function which we use to override the class expose function
3819 * for the drawing area widget. It allows us to catch exposure events
3820 * intended for the desktop, so that we can force the redrawing of the
3821 * gadgets to occur occording to the stacking order.
3825 DrawingAreaRedisplay (
3831 XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid;
3832 XmDrawingAreaCallbackStruct cb;
3833 FileMgrData * file_mgr_data;
3835 cb.reason = XmCR_EXPOSE;
3837 cb.window = XtWindow (da);
3839 DPRINTF2(("DrawingAreaRedisplay: event %d, x/y %d/%d, wd/ht %d/%d\n",
3841 event->xexpose.x, event->xexpose.y,
3842 event->xexpose.width, event->xexpose.height));
3844 file_mgr_data = ReturnDesktopPtr(wid);
3846 if (file_mgr_data && PositioningEnabledInView(file_mgr_data))
3847 RedisplayUsingStackingOrder(file_mgr_data, (Widget)da, event, region);
3849 XmeRedisplayGadgets((Widget)da, event, region);
3851 XtCallCallbackList ((Widget)da, da->drawing_area.expose_callback, &cb);
3856 * Return the bottom of the stacking order list.
3861 FileMgrData * file_mgr_data)
3867 for (i = 0, bottom = NULL; i < file_mgr_data->num_objects; i++)
3869 if (file_mgr_data->object_positions[i]->next == NULL)
3871 bottom = file_mgr_data->object_positions[i];
3881 * Return the top of the stacking order list.
3886 FileMgrData * file_mgr_data)
3891 for (i = 0, top = NULL; i < file_mgr_data->num_objects; i++)
3893 if (file_mgr_data->object_positions[i]->prev == NULL)
3895 top = file_mgr_data->object_positions[i];
3905 * Move an object up in the stacking order. Will not work for moving an
3906 * object further down in the stacking order, but we currently have no
3907 * need for doing that.
3909 * NOTE: The top of the stack is '1', not '0'!!
3913 RepositionUpInStack (
3914 FileMgrData * file_mgr_data,
3919 ObjectPtr ptr, ptr2, savePtr;
3921 XmManagerWidget file_window;
3923 if (oldPos == newPos)
3926 ptr = GetTopOfStack(file_mgr_data);
3928 /* Find where item is to be inserted */
3929 while (ptr->stacking_order != newPos)
3932 /* Find where item currently is */
3934 while (ptr2->stacking_order != oldPos)
3939 if(savePtr->file_view_data == NULL)
3942 /* Remove from its current location */
3944 ptr2->prev->next = ptr2->next;
3946 ptr2->next->prev = ptr2->prev;
3948 /* Link into new position */
3949 ptr2->prev = ptr->prev;
3952 ptr2->prev->next = ptr2;
3955 /* Update the stacking order value */
3956 for (i = newPos; i <= oldPos; i++)
3958 ptr2->stacking_order = i;
3962 /* Update the children's list for the file window */
3963 file_window = (XmManagerWidget)
3964 (((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
3966 /* Find the affect child */
3967 for (i = 0; (i < file_window->composite.num_children) &&
3968 (file_window->composite.children[i] != savePtr->file_view_data->widget);
3971 /* Push intervening entries down */
3972 for (j = i; j >= newPos; j--)
3973 file_window->composite.children[j] = file_window->composite.children[j-1];
3975 /* Insert into new position in children list */
3976 file_window->composite.children[newPos-1] = savePtr->file_view_data->widget;
3981 * Reorder the file window's children list so that it matches the stacking
3986 ReorderChildrenList (
3987 XmManagerWidget file_window,
3994 Widget * children = file_window->composite.children;
3997 for (i = 0; i < manageCount; i++)
3998 children[i] = manage[i];
4000 for (j = 0; j < unmanageCount; j++)
4001 children[i++] = unmanage[j];
4006 * If positional information is available for the indicated file, then
4007 * return it; if not, then return NULL.
4011 FindCurrentPosition (
4012 FileMgrData * file_mgr_data,
4018 for (i = 0; i < file_mgr_data->num_objects; i++)
4020 if (strcmp(file_name, file_mgr_data->object_positions[i]->name) == 0)
4023 file_mgr_data->object_positions[i]->in_use = True;
4024 return(file_mgr_data->object_positions[i]);
4033 RepairStackingPointers (
4034 FileMgrData * file_mgr_data)
4039 ObjectPosition * ptr;
4040 ObjectPosition * prev;
4042 for (i = 1, prev = NULL; i <= file_mgr_data->num_objects; i++)
4044 for (j = 0; j < file_mgr_data->num_objects; j++)
4046 ptr = file_mgr_data->object_positions[j];
4047 if (ptr->stacking_order == i)
4062 * Reorder the children's list for the file_window, so that it matches
4063 * the stacking order. Also, set up all next and previous pointers.
4068 FileMgrData * file_mgr_data)
4071 FileMgrRec * file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
4072 XmManagerWidget file_window;
4077 ObjectPosition * top;
4080 file_window = (XmManagerWidget) file_mgr_rec->file_window;
4081 managed = (Widget *)XtMalloc(sizeof(Widget *) *
4082 file_window->composite.num_children);
4083 unmanaged = (Widget *)XtMalloc(sizeof(Widget *) *
4084 file_window->composite.num_children);
4085 num_managed = num_unmanaged = 0;
4087 top = GetTopOfStack(file_mgr_data);
4090 if (top->file_view_data != NULL && top->file_view_data->widget != NULL)
4091 managed[num_managed++] = top->file_view_data->widget;
4095 /* All the rest get put at the end of the children's list */
4096 for (i = 0; i < file_window->composite.num_children; i++)
4098 for (j = 0; j < num_managed; j++)
4100 if (managed[j] == file_window->composite.children[i])
4104 if (j >= num_managed)
4105 unmanaged[num_unmanaged++] = file_window->composite.children[i];
4108 ReorderChildrenList(file_window, managed, num_managed, unmanaged,
4110 XtFree( (char *)managed );
4111 XtFree( (char *)unmanaged );
4121 FileViewData * file_view_data,
4122 XtCallbackProc callback,
4123 XtPointer callback_data)
4128 if (file_view_data->displayed)
4130 /*************************/
4131 /* icon gadget displayed */
4132 /*************************/
4133 DtIconGadget g = (DtIconGadget) file_view_data->widget;
4134 unsigned char operations;
4136 /* find defined operations (M/C/L) for file type */
4137 operations = TypeToDropOperations(
4138 file_view_data->file_data->logical_type);
4140 /* if icon gadget not yet registered as a drop site, do so now */
4141 if (!file_view_data->registered)
4143 /* register drop site for MCL but make drop site inactive */
4144 XtSetArg (args[0], XmNdropSiteOperations,
4145 XmDROP_COPY | XmDROP_MOVE | XmDROP_LINK);
4146 XtSetValues (file_view_data->widget, args, 1);
4148 file_view_data->registered = True;
4153 /***********************************/
4154 /* file has associated MCL actions */
4155 /***********************************/
4156 XRectangle rects[2];
4157 unsigned char flags;
4160 Dimension s_t, adj_xy, adj_size;
4162 /* ensure drop site operations and drop area are correct */
4163 _DtIconGetIconRects(g, &flags, &rects[0], &rects[1]);
4166 * Compute adjustments to the drop area:
4168 * - Add shadowThickness to the drop area:
4169 * The icon gadget leaves space of width shadowThickness around
4170 * the pixmap and label; use this space to make the drop zone
4173 * - Compensate for bug in drop zone registration/drawing:
4174 * For some reason the drop zone displayed on the screen is
4175 * actually smaller than the rectangle we register:
4176 * The drag&drop library seems to reduce the size of the drop
4177 * area by the value of highlightThickness at the top and left
4178 * border and by highlightThickness-1 at the bottom and right.
4179 * Is this a Motif drag&drop bug?
4180 * We compensate by registering a larger rectangle.
4182 s_t = G_ShadowThickness(g);
4183 adj_xy = s_t + G_HighlightThickness(g);
4184 adj_size = adj_xy + s_t + G_HighlightThickness(g) - 1;
4186 if (flags & XmPIXMAP_RECT)
4188 rects[0].x -= g->rectangle.x + adj_xy;
4189 rects[0].y -= g->rectangle.y + adj_xy;
4190 rects[0].width += adj_size;
4191 rects[0].height += adj_size;
4195 if (flags & XmLABEL_RECT)
4197 rects[1].x -= g->rectangle.x + adj_xy;
4198 rects[1].y -= g->rectangle.y + adj_xy;
4199 rects[1].width += adj_size;
4200 rects[1].height += adj_size;
4201 if (!numRects) rects[0] = rects[1];
4207 XtSetArg(args[n], XmNdropRectangles, rects); n++;
4208 XtSetArg(args[n], XmNnumDropRectangles, numRects); n++;
4210 XtSetArg (args[n], XmNdropSiteOperations, operations); n++;
4212 XmDropSiteUpdate (file_view_data->widget, args, n);
4213 g->icon.operations = operations;
4215 /* add client data */
4216 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4217 XtAddCallback(file_view_data->widget, XmNdropCallback,
4218 callback, callback_data);
4222 /*********************************************/
4223 /* file does not have associated MCL actions */
4224 /*********************************************/
4225 /* make drop site inactive */
4226 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
4227 XmDropSiteUpdate (file_view_data->widget, args, 1);
4228 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4233 /*****************************/
4234 /* icon gadget not displayed */
4235 /*****************************/
4236 if (file_view_data->registered)
4238 /***************************************/
4239 /* icon gadget registered as drop site */
4240 /***************************************/
4241 /* make drop site inactive */
4242 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
4243 XmDropSiteUpdate (file_view_data->widget, args, 1);
4244 XtRemoveAllCallbacks(file_view_data->widget, XmNdropCallback);
4252 * TypeToDropOperations
4256 TypeToDropOperations (
4260 unsigned char operations = 0L;
4263 /* does object have MOVE, COPY, and/or LINK actions */
4264 /* -- or no actions at all */
4265 if (action = DtDtsDataTypeToAttributeValue(file_type,
4266 DtDTS_DA_MOVE_TO_ACTION,
4269 operations = operations | XmDROP_MOVE;
4270 DtDtsFreeAttributeValue(action);
4272 if (action = DtDtsDataTypeToAttributeValue(file_type,
4273 DtDTS_DA_COPY_TO_ACTION,
4276 operations = operations | XmDROP_COPY;
4277 DtDtsFreeAttributeValue(action);
4279 if (action = DtDtsDataTypeToAttributeValue(file_type,
4280 DtDTS_DA_LINK_TO_ACTION,
4283 operations = operations | XmDROP_LINK;
4284 DtDtsFreeAttributeValue(action);
4297 unsigned char dropOperation,
4298 char * logical_type)
4302 /* retrieve action from database based on dropOperation */
4303 switch(dropOperation)
4306 action = DtDtsDataTypeToAttributeValue(logical_type,
4307 DtDTS_DA_MOVE_TO_ACTION,
4311 action = DtDtsDataTypeToAttributeValue(logical_type,
4312 DtDTS_DA_COPY_TO_ACTION,
4316 action = DtDtsDataTypeToAttributeValue(logical_type,
4317 DtDTS_DA_LINK_TO_ACTION,
4330 * Given a fileViewData pointer, determine if it is part of a FileMgrData,
4331 * or a DesktopRec; return the appropriate pointer.
4337 FileViewData * fileViewData,
4338 FileMgrData ** fileMgrData,
4339 DesktopRec ** desktopRec)
4344 *fileMgrData = NULL;
4346 for (i = 0; i < desktop_data->numIconsUsed; i++)
4348 if (desktop_data->desktopWindows[i]->file_view_data == fileViewData)
4350 *desktopRec = desktop_data->desktopWindows[i];
4355 *fileMgrData = (FileMgrData *)
4356 ((DirectorySet *)fileViewData->directory_set)->file_mgr_data;
4361 /******************************************************************
4363 * PositionFileView -
4364 * Given a particular file, position the file view that file
4365 * is in on that particular file.
4367 ********************************************************************/
4370 FileViewData *file_view_data,
4371 FileMgrData *file_mgr_data)
4375 int value, size, increment, page, max;
4376 FileMgrRec * file_mgr_rec = (FileMgrRec *)(file_mgr_data->file_mgr_rec);
4379 /* if the file is filtered we can't highlight it! */
4380 if(!file_view_data->displayed)
4383 /* Get the y location of the icon_gadget */
4384 y = file_view_data->y - file_mgr_data->grid_height;
4388 * 1) not sure exactly how slow this is, but there seems to be no other
4389 * way to do this. (CDExc23427)
4390 * 2) XmScrollVisible does not work if the work window is not managed...
4391 * so, we call it, and then get the appropriate x,y back from the
4392 * scroll bars and set them (CDExc23428) */
4393 p = XtVaCreateManagedWidget("positionicon", xmGadgetClass,
4394 file_mgr_rec->file_window,
4395 XmNmappedWhenManaged, False,
4396 XmNx, file_view_data->x,
4398 XmNwidth, file_mgr_data->grid_width,
4399 XmNheight, file_mgr_data->grid_height,
4402 XmScrollVisible(file_mgr_rec->scroll_window, p,
4403 XSPACING, YSPACING(file_mgr_data));
4407 XmScrollBarGetValues(file_mgr_rec->horizontal_scroll_bar,
4408 &value, &size, &increment, &page);
4409 x = -((Position) value);
4411 XmScrollBarGetValues(file_mgr_rec->vertical_scroll_bar,
4412 &value, &size, &increment, &page);
4413 y = -((Position) value);
4415 XtVaSetValues(file_mgr_rec->file_window, XmNx, x, XmNy, y, NULL);
4420 InMultipleObjectRegion (FileMgrData * file_mgr_data, FileViewData * fileViewData)
4423 for( i = 0; i < file_mgr_data->selected_file_count; ++i )
4424 if( strcmp( file_mgr_data->selection_list[i]->file_data->file_name, fileViewData->file_data->file_name ) == 0 )
4432 XtPointer client_data,
4434 FileMgrData *file_mgr_data)
4436 FileMgrRec *file_mgr_rec;
4438 FileViewData *fileViewData = NULL;
4439 int i, num_of_children, obj_btns;
4440 XmManagerWidget action_pane;
4441 XmString label_string;
4444 /* set number of popup children based on annotation */
4445 num_of_children = FM_POPUP_CHILDREN_NA;
4446 obj_btns = OBJ_BTNS_NA;
4448 /* attach the popup widget info to the menu */
4449 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
4450 XtSetArg(args[0], XmNuserData, file_mgr_rec);
4451 XtSetValues(fileMgrPopup.menu, args, 1);
4454 file_mgr_data->popup_menu_icon = NULL;
4456 /* we are dealing with a white space popup */
4458 && (client_data == NULL)
4460 && (file_mgr_data->selected_file_count == 0)
4464 DirectorySet *directory_set;
4466 /* retrieve the fileViewData for the current directory */
4467 directory_set = file_mgr_data->directory_set[0];
4468 for (i = 0; i < directory_set->file_count; i++)
4470 if(strcmp(directory_set->order_list[i]->file_data->file_name, ".")
4473 fileViewData = directory_set->order_list[i];
4478 /* manage the white space buttons and unmanage the object buttons */
4479 XtManageChildren(fileMgrPopup.wsPopup, WS_BTNS);
4480 XtUnmanageChildren(fileMgrPopup.objPopup, obj_btns);
4481 XtUnmanageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4483 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_UNSELECTALL]);
4485 if(file_mgr_data == trashFileMgrData)
4487 /* Set popup menu label */
4488 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 2, "Current Folder")));
4489 XtSetArg (args[0], XmNlabelString, label_string);
4490 XtSetValues (fileMgrPopup.title, args, 1);
4491 XtManageChild(fileMgrPopup.title);
4492 XmStringFree (label_string);
4494 /* trash white space popup -- unmanage the properties and show */
4495 /* hidden files buttons */
4496 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4497 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_FIND]);
4498 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN]);
4500 /* align the remaining buttons */
4501 XtSetArg(args[0], XmNmarginLeft, 0);
4502 if( PositioningEnabledInView( file_mgr_data ) )
4504 file_mgr_rec->menuStates |= CLEAN_UP;
4505 XtSetValues(fileMgrPopup.wsPopup[BTN_CLEANUP], args, 1);
4509 file_mgr_rec->menuStates &= ~(CLEAN_UP);
4510 XtUnmanageChild( fileMgrPopup.wsPopup[BTN_CLEANUP] );
4512 XtSetValues(fileMgrPopup.wsPopup[BTN_SELECTALL], args, 1);
4514 /* unmanage the action portion of the popup menu */
4515 XtUnmanageChild(fileMgrPopup.action_separator);
4517 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4518 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4519 XtUnmanageChild(action_pane->composite.children[i]);
4525 /* manage the properties and show hidden files buttons */
4526 if( file_mgr_data->toolbox )
4527 XtUnmanageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4529 XtManageChild(fileMgrPopup.wsPopup[BTN_PROPERTIES]);
4530 XtManageChild(fileMgrPopup.wsPopup[BTN_FIND]);
4531 XtManageChild(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN]);
4533 /* Set popup menu label */
4534 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 2, "Current Folder")));
4535 XtSetArg (args[0], XmNlabelString, label_string);
4536 XtSetValues (fileMgrPopup.title, args, 1);
4537 XtManageChild(fileMgrPopup.title);
4538 XmStringFree (label_string);
4540 /* align the menu buttons */
4541 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4542 XtSetArg(args[0], XmNmarginLeft, &margin);
4543 XtGetValues(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], args, 1);
4544 XtSetArg(args[0], XmNmarginLeft, margin);
4546 if( PositioningEnabledInView( file_mgr_data ) )
4548 file_mgr_rec->menuStates |= CLEAN_UP;
4549 XtSetValues(fileMgrPopup.wsPopup[BTN_CLEANUP], args, 1);
4553 file_mgr_rec->menuStates &= ~(CLEAN_UP);
4554 XtUnmanageChild( fileMgrPopup.wsPopup[BTN_CLEANUP] );
4557 XtSetValues(fileMgrPopup.wsPopup[BTN_SELECTALL], args, 1);
4561 if (file_mgr_data->show_hid_enabled)
4562 XmToggleButtonGadgetSetState(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], True, False);
4564 XmToggleButtonGadgetSetState(fileMgrPopup.wsPopup[BTN_SHOWHIDDEN], False, False);
4567 /* ensure that there was fileViewData for the current directory */
4568 if(fileViewData != NULL)
4570 /* attach the current fileViewData to the 'Properties' button */
4571 if( ! file_mgr_data->toolbox )
4573 XtRemoveAllCallbacks(fileMgrPopup.wsPopup[BTN_PROPERTIES],
4574 XmNactivateCallback);
4575 XtAddCallback (fileMgrPopup.wsPopup[BTN_PROPERTIES],
4576 XmNactivateCallback,
4577 ShowModAttrDialog, (XtPointer) fileViewData);
4579 /* sensitize the 'Properties' option */
4580 XtSetSensitive(fileMgrPopup.wsPopup[BTN_PROPERTIES], True);
4582 /* update the actions portion of the popup menu */
4583 XtManageChild(fileMgrPopup.action_separator);
4585 XtFree(fileMgrPopup.action_pane_file_type);
4586 fileMgrPopup.action_pane_file_type =
4587 XtNewString(fileViewData->file_data->logical_type);
4589 UpdateActionMenuPane ((XtPointer)fileViewData, file_mgr_rec,
4590 fileViewData->file_data->logical_type,
4591 FM_POPUP, num_of_children,
4593 fileViewData->file_data->physical_type);
4595 /* align actions portion of the popup menu */
4596 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4597 XtSetValues(action_pane->composite.children[i], args, 1);
4601 if( ! file_mgr_data->toolbox )
4603 /* remove callback from 'Properties' button */
4604 XtRemoveAllCallbacks(fileMgrPopup.wsPopup[BTN_PROPERTIES],
4605 XmNactivateCallback);
4607 /* desensitize the 'Properties' button */
4608 XtSetSensitive(fileMgrPopup.wsPopup[BTN_PROPERTIES], False);
4611 /* unmanage the action portion of the popup menu */
4612 XtUnmanageChild(fileMgrPopup.action_separator);
4614 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4615 XtUnmanageChild(action_pane->composite.children[i]);
4620 /* we are dealing with an object popup */
4623 char label[MAX_PATH];
4625 /* retrieve the fileViewData for the selected icon */
4627 fileViewData = (FileViewData *) client_data;
4628 else if (file_mgr_data->selected_file_count != 0)
4629 fileViewData = file_mgr_data->selection_list[0];
4632 /* unmanage the white space buttons */
4633 XtUnmanageChildren(fileMgrPopup.wsPopup, WS_BTNS);
4635 if(file_mgr_data == trashFileMgrData)
4637 file_mgr_data->popup_menu_icon = fileViewData;
4639 /* Set popup menu label */
4640 if( file_mgr_data->selected_file_count > 1
4641 && InMultipleObjectRegion(file_mgr_data, fileViewData))
4644 label_string = XmStringCreateLocalized ((GETMESSAGE(33,1, "Multiple Objects")));
4650 if (fileViewData->file_data->action_name)
4651 tmp_label = fileViewData->file_data->action_name;
4653 tmp_label = fileViewData->file_data->file_name;
4655 if( strlen( tmp_label ) > 20 )
4656 sprintf( label, "%-20.20s...", tmp_label );
4658 sprintf( label, "%s", tmp_label );
4660 label_string = XmStringCreateLocalized (label);
4662 XtSetArg (args[0], XmNlabelString, label_string);
4663 XtSetValues (fileMgrPopup.title, args, 1);
4664 XtManageChild(fileMgrPopup.title);
4665 XmStringFree (label_string);
4667 /* trash popup--unmanage the non-trash buttons, manage the trash */
4668 XtUnmanageChildren(fileMgrPopup.objPopup, obj_btns);
4669 XtManageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4671 /* adjust callbacks */
4672 XtRemoveAllCallbacks(fileMgrPopup.trash_objPopup[BTN_RESTORE],
4673 XmNactivateCallback);
4674 XtAddCallback(fileMgrPopup.trash_objPopup[BTN_RESTORE],
4675 XmNactivateCallback, Restore, (XtPointer) fileViewData);
4677 XtRemoveAllCallbacks(fileMgrPopup.trash_objPopup[BTN_REMOVE],
4678 XmNactivateCallback);
4679 XtAddCallback(fileMgrPopup.trash_objPopup[BTN_REMOVE],
4680 XmNactivateCallback, ConfirmRemove,
4681 (XtPointer) fileViewData);
4683 /* unmanage the action portion of the popup menu */
4684 XtUnmanageChild(fileMgrPopup.action_separator);
4686 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4687 for(i=num_of_children; i<action_pane->composite.num_children; i++)
4688 XtUnmanageChild(action_pane->composite.children[i]);
4692 /* non-trash popup--manage the non-trash buttons, unmanage the trash */
4693 XtManageChildren(fileMgrPopup.objPopup, obj_btns);
4694 XtUnmanageChildren(fileMgrPopup.trash_objPopup, TRASH_OBJ_BTNS);
4695 if( file_mgr_data->toolbox )
4696 XtUnmanageChild(fileMgrPopup.objPopup[BTN_PROPERTIES]);
4698 if(file_mgr_data->selected_file_count > 1
4699 && InMultipleObjectRegion(file_mgr_data, fileViewData))
4701 /* we have many files selected; remove callbacks from the */
4702 /* 'Properties', 'Put on Desktop', and 'Review' buttons */
4703 /* and attach the selection list to the remaining buttons; */
4704 /* desensitize the 3 buttons listed above; unmanage the */
4705 /* actions part of the popup menu */
4707 /* adjust callbacks */
4708 if( ! file_mgr_data->toolbox )
4709 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PROPERTIES],
4710 XmNactivateCallback);
4712 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PUTON],
4713 XmNactivateCallback);
4714 XtAddCallback(fileMgrPopup.objPopup[BTN_PUTON], XmNactivateCallback,
4715 PutOnDTCB, (XtPointer) fileViewData);
4717 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_TRASH],
4718 XmNactivateCallback);
4719 XtAddCallback(fileMgrPopup.objPopup[BTN_TRASH], XmNactivateCallback,
4720 TrashFiles, (XtPointer) fileViewData);
4722 if( file_mgr_data->toolbox && geteuid() != root_user &&
4723 access(file_mgr_data->current_directory,W_OK|X_OK) != 0)
4724 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], False);
4727 /* sensitize buttons */
4728 if( !file_mgr_data->toolbox )
4729 XtSetSensitive(fileMgrPopup.objPopup[BTN_PROPERTIES], False);
4731 XtSetSensitive(fileMgrPopup.objPopup[BTN_HELP], False);
4733 /* Set popup menu label */
4734 label_string = XmStringCreateLocalized ((GETMESSAGE(33, 1, "Multiple Objects")));
4735 XtSetArg (args[0], XmNlabelString, label_string);
4736 XtSetValues (fileMgrPopup.title, args, 1);
4737 XtManageChild(fileMgrPopup.title);
4738 XmStringFree (label_string);
4741 /* unmanage actions */
4742 XtUnmanageChild(fileMgrPopup.action_separator);
4743 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4744 for(i = num_of_children;
4745 i < action_pane->composite.num_children;
4747 XtUnmanageChild(action_pane->composite.children[i]);
4753 /* we have one file selected; attach fileViewData to buttons; */
4754 /* sensitize any desensitized buttons; update the actions */
4755 /* part of the popup menu */
4757 /* adjust callbacks */
4758 if( ! file_mgr_data->toolbox )
4760 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PROPERTIES],
4761 XmNactivateCallback);
4762 XtAddCallback(fileMgrPopup.objPopup[BTN_PROPERTIES],
4763 XmNactivateCallback, ShowModAttrDialog, (XtPointer) fileViewData);
4766 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_PUTON],
4767 XmNactivateCallback);
4768 XtAddCallback(fileMgrPopup.objPopup[BTN_PUTON],
4769 XmNactivateCallback, PutOnDTCB, (XtPointer) fileViewData);
4771 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_TRASH],
4772 XmNactivateCallback);
4773 XtAddCallback(fileMgrPopup.objPopup[BTN_TRASH],
4774 XmNactivateCallback, TrashFiles, (XtPointer) fileViewData);
4776 if ( file_mgr_data->toolbox && geteuid() != root_user &&
4777 access(file_mgr_data->current_directory,W_OK|X_OK) != 0 )
4778 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], False);
4780 XtSetSensitive(fileMgrPopup.objPopup[BTN_TRASH], True);
4783 XtRemoveAllCallbacks(fileMgrPopup.objPopup[BTN_HELP],
4784 XmNactivateCallback);
4785 XtAddCallback(fileMgrPopup.objPopup[BTN_HELP],
4786 XmNactivateCallback, ObjectHelp, (XtPointer) fileViewData->widget);
4788 /* sensitize buttons */
4789 if( ! file_mgr_data->toolbox )
4790 XtSetSensitive(fileMgrPopup.objPopup[BTN_PROPERTIES], True);
4792 XtSetSensitive(fileMgrPopup.objPopup[BTN_PUTON], True);
4793 XtSetSensitive(fileMgrPopup.objPopup[BTN_HELP], True);
4795 if (fileViewData->file_data->action_name)
4796 tmp_label = fileViewData->file_data->action_name;
4798 tmp_label = fileViewData->file_data->file_name;
4800 if( strlen( tmp_label ) > 20 )
4801 sprintf( label, "%-20.20s...", tmp_label );
4803 sprintf( label, "%s", tmp_label );
4805 /* Set popup menu label */
4806 label_string = XmStringCreateLocalized (label);
4807 XtSetArg (args[0], XmNlabelString, label_string);
4808 XtSetValues (fileMgrPopup.title, args, 1);
4809 XtManageChild(fileMgrPopup.title);
4810 XmStringFree (label_string);
4813 /* update actions */
4814 XtManageChild(fileMgrPopup.action_separator);
4816 XtFree(fileMgrPopup.action_pane_file_type);
4817 fileMgrPopup.action_pane_file_type =
4818 XtNewString(fileViewData->file_data->logical_type);
4820 UpdateActionMenuPane ((XtPointer)fileViewData, file_mgr_rec,
4821 fileViewData->file_data->logical_type,
4822 FM_POPUP, num_of_children,
4824 fileViewData->file_data->physical_type);
4827 action_pane = (XmManagerWidget) fileMgrPopup.menu;
4828 XtSetArg(args[0], XmNmarginLeft, 0);
4829 for(i = num_of_children; i < action_pane->composite.num_children; i++)
4830 XtSetValues(action_pane->composite.children[i], args, 1);
4836 /* position and manage popup menu */
4840 Dimension width, height;
4841 Dimension gWidth, gHeight;
4842 int displayWidth, displayHeight;
4843 DtIconGadget g = (DtIconGadget)w;
4845 XtSetArg (args[0], XmNwidth, &width);
4846 XtSetArg (args[1], XmNheight, &height);
4847 XtGetValues(XtParent(fileMgrPopup.menu), args, 2);
4849 gWidth = g->icon.pixmap_width;
4850 gHeight = g->icon.pixmap_height;
4852 displayWidth = DisplayWidth(XtDisplay(w), DefaultScreen(XtDisplay(w)));
4853 displayHeight =DisplayHeight(XtDisplay(w), DefaultScreen(XtDisplay(w)));
4855 x = file_mgr_rec->shell->core.x +
4856 file_mgr_rec->scroll_window->core.x +
4857 w->core.x + gWidth/2;;
4859 y = file_mgr_rec->shell->core.y +
4860 file_mgr_rec->header_frame->core.y +
4861 file_mgr_rec->header_frame->core.height +
4862 file_mgr_rec->scroll_window->core.y +
4863 w->core.y + gHeight/2;;
4865 if((Dimension)(x + width) > (Dimension)displayWidth)
4866 x = displayWidth - width - 4;
4867 if((Dimension)(y + height) > (Dimension)displayHeight)
4868 y = displayHeight - height - 4;
4870 XtSetArg (args[0], XmNx, x);
4871 XtSetArg (args[1], XmNy, y);
4872 XtSetValues(XtParent(fileMgrPopup.menu), args, 2);
4876 if(( event->type == ButtonPress || event->type == ButtonRelease) ||
4877 ( ( event->type == KeyPress || event->type == KeyRelease) &&
4878 _XmIsEventUnique(event) ) )
4880 XmMenuPosition(fileMgrPopup.menu, (XButtonPressedEvent *)event);
4884 XtManageChild(fileMgrPopup.menu);
4886 if( event->type == KeyPress || event->type == KeyRelease )
4888 /* Specify that the focus is being moved by key, NOT mouse
4890 _XmSetInDragMode(fileMgrPopup.menu,False);
4892 XmProcessTraversal(fileMgrPopup.menu,XmTRAVERSE_CURRENT);
4894 /* This function is being called twice.
4895 Record this event so the above check _XmIsEventUnique will work
4897 _XmRecordEvent(event);
4905 XtPointer client_data,
4906 XtPointer call_data)
4908 DtDndDropCallbackStruct *fileList = (DtDndDropCallbackStruct *)call_data;
4910 char ** file_set = NULL;
4911 char ** host_set = NULL;
4912 FileMgrRec * file_mgr_rec;
4913 FileMgrData * file_mgr_data;
4921 int effScreenHeight;
4922 int start_x, start_y;
4926 /* Check the protocol, set to failure if not the */
4927 /* File Transfer protocol */
4928 if (fileList->dropData->protocol != DtDND_FILENAME_TRANSFER)
4930 fileList->status = DtDND_FAILURE;
4935 numFiles = fileList->dropData->numItems;
4937 DPRINTF (("DropOnRoot: Number of files dropped are %d\n", numFiles));
4939 if(fileList->reason != DtCR_DND_DROP_ANIMATE)
4941 /* set the complete move flag to False since it is not required to be called */
4942 /* In case when the drag is from non File manager client */
4944 initiating_view = NULL;
4946 fileList->completeMove = False;
4948 _DtSetDroppedFileInfo(fileList, &file_set, &host_set);
4950 if(initiating_view != NULL)
4952 file_mgr_rec = (FileMgrRec *)
4953 (((FileMgrData *) initiating_view)->file_mgr_rec);
4954 file_mgr_data = (FileMgrData *) initiating_view;
4957 file_mgr_data = NULL;
4959 /* get the correct position for the desktop icon shell */
4960 PositionDesktopIcon(fileList->x, fileList->y, &root_x, &root_y);
4965 * We will place the icons by marching down a diagonal starting
4966 * at the drop point. But we don't want to march off-screen
4967 * if there are too many icons. So ...
4968 * - We choose a step width of 20, 10, 5, or 2 depending
4969 * on the number of icons dropped.
4970 * - When we run into the edge of the screen, we start a new
4971 * diagonal shifted one step to the right.
4972 * - If all icons still won't fit, we move the starting point
4973 * closer to the top left corner of the screen.
4976 /* compute effective screen size (largest x,y where an icon
4977 * can be placed without going off-screen) */
4978 effScreenWidth = WidthOfScreen(XtScreen(w)) - (4 + 4+48+4 + 5);
4979 effScreenHeight = HeightOfScreen(XtScreen(w)) - (4 + 4+48+3+15+4 + 5);
4981 /* chosee step depending on number of icons */
4982 if (numFiles <= 200)
4984 else if (numFiles <= 400)
4986 else if (numFiles <= 1000)
4990 dstep = 40 + 4+48+4 + 5;
4992 /* choose starting point so at least two icons will fit */
4993 if (root_x <= effScreenWidth - step)
4996 start_x = effScreenWidth - step;
4998 if (root_y <= effScreenWidth - step)
5001 start_y = effScreenWidth - step;
5003 DPRINTF(("DropOnRootCB: numFiles %d, root_x %d, root_y %d, step %d\n",
5004 numFiles, root_x, root_y, step));
5006 /* check if all icons will fit */
5009 /* cacluclate how many will fit (add up icons on all diagonals) */
5011 for (root_x = start_x; root_x <= effScreenWidth; root_x += dstep)
5013 int nx = (effScreenWidth - root_x)/step + 1;
5014 int ny = (effScreenHeight - start_y)/step + 1;
5015 n += (nx <= ny)? nx: ny;
5019 DPRINTF(("start_x %d, start_y %d, nd %d, n %d\n",
5020 start_x, start_y, nd, n));
5022 /* if everything fits - great! */
5026 /* move the start point closer to the top left corner */
5027 if (effScreenWidth - start_x < effScreenHeight - start_y &&
5030 /* move left so more icons will fit */
5033 else if (effScreenWidth - start_x > effScreenHeight - start_y &&
5036 /* move up so one more icon will fit in each diagonal */
5039 else if (start_x > 0 || start_y > 0)
5041 /* move left and up */
5042 if (start_x >= step)
5046 if (start_y >= step)
5052 /* ran out of space - too bad! */
5059 /* the icon that was dropped on the root window was an
5060 icon that was already on the root window */
5061 if (file_mgr_data == NULL)
5063 DPRINTF(("DropOnRoot: Object already on Desktop\n"));
5065 /* loop through the existing desktop icons to determine which
5066 ones are being dragged, then change their location */
5067 for(i=0; i < desktop_data->numIconsUsed; i++)
5069 if((Widget)desktop_data->desktopWindows[i]->iconGadget ==
5070 (Widget)widget_dragged)
5072 if (DTFileIsSelected(desktop_data->desktopWindows[i],
5073 desktop_data->desktopWindows[i]->file_view_data))
5075 for(j=0;j< desktop_data->numWorkspaces;j++)
5076 if(desktop_data->workspaceData[j]->number ==
5077 desktop_data->desktopWindows[i]->workspace_num)
5081 j < desktop_data->workspaceData[wsNum]->files_selected;
5084 RelocateDesktopIcon(desktop_data->workspaceData[wsNum]->
5085 selectedDTWindows[j],
5089 if (root_x > effScreenWidth || root_y > effScreenHeight)
5092 if (start_x > effScreenWidth)
5101 RelocateDesktopIcon(desktop_data->desktopWindows[i],
5108 else if( file_mgr_data == trashFileMgrData )
5110 /* if the file manager data is the trash, we want to tell the
5111 user that they can't drop trash on the desktop
5116 DPRINTF(("DropOnRoot: Attempting to Drag Trash Object to Desktop\n"));
5117 file_mgr_rec = (FileMgrRec *)trashFileMgrData->file_mgr_rec;
5118 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."));
5119 msg = XtNewString(tmpStr);
5120 FileOperationError (file_mgr_rec->main, msg, NULL);
5124 else /* it was dropped on the root window so lets process it */
5126 int EndIndex = desktop_data->numIconsUsed;
5128 for(i = 0; i < numFiles; i++)
5130 ptr = strrchr(file_set[i], '/');
5131 if( strcmp(file_mgr_data->current_directory, file_set[i]) == 0)
5133 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5134 file_mgr_data, file_mgr_rec,
5135 ".", host_set[i], file_set[i],
5139 else if(strncmp(file_mgr_data->current_directory, file_set[i], strlen(file_set[i]) ) == 0 )
5141 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5142 file_mgr_data, file_mgr_rec,
5143 "..", host_set[i],file_mgr_data->current_directory,
5150 if(*(file_set[i]) == 0)
5152 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5153 file_mgr_data, file_mgr_rec,
5154 ptr + 1, host_set[i], "/",
5160 SetupDesktopWindow(XtDisplay(file_mgr_rec->shell),
5161 file_mgr_data, file_mgr_rec,
5162 ptr + 1, host_set[i], file_set[i],
5169 if (root_x > effScreenWidth || root_y > effScreenHeight)
5172 if (start_x > effScreenWidth)
5178 initiating_view = (XtPointer)NULL;
5181 _DtFreeDroppedFileInfo(numFiles, file_set, host_set);
5187 /************************************************************************
5191 ************************************************************************/
5194 FreeLayoutData(XtPointer p)
5196 IconLayoutData *layout_data;
5201 layout_data = (IconLayoutData *)p;
5203 if (layout_data->work_id != 0)
5205 DPRINTF(("FreeLayoutData: removing workproc\n"));
5206 XtRemoveWorkProc(layout_data->work_id);
5207 XmDropSiteEndUpdate(layout_data->drop_site_w);
5210 XtFree((char *)layout_data->order_list);
5211 layout_data->order_list = NULL;
5212 XtFree((char *)layout_data->reuse_icons);
5213 layout_data->reuse_icons = NULL;
5214 XtFree((char *)layout_data->reuse_btns);
5215 layout_data->reuse_btns = NULL;
5216 XtFree((char *)layout_data->manage);
5217 layout_data->manage = NULL;
5219 XtFree((char *)layout_data);
5223 /************************************************************************
5226 * Unmanage a subset of the file icons.
5228 ************************************************************************/
5230 void UnmanageFileIcons(
5231 FileMgrRec *file_mgr_rec,
5232 FileMgrData *file_mgr_data,
5233 FileViewData *file_view_data)
5235 XmManagerWidget file_window;
5236 FileViewData **order_list;
5244 /* Set the size of the file window BIG so that it does not */
5245 /* try to force positioning on its children. */
5247 file_window = (XmManagerWidget) file_mgr_rec->file_window;
5248 XtResizeWidget ((Widget)file_window, 32767, 32767, 0);
5251 /* Set the scrolled window and file window appropriately */
5252 /* to prevent a lot of gyrations. */
5254 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmSTATIC);
5255 XtSetValues (file_mgr_rec->scroll_window, args, 1);
5257 order_list = ((IconLayoutData *)file_mgr_data->layout_data)->order_list;
5258 order_count = ((IconLayoutData *)file_mgr_data->layout_data)->order_count;
5260 unmanage = (Widget *)XtMalloc(2*order_count*sizeof(Widget));
5262 for (i = 0; i < order_count; i++)
5264 if (order_list[i]->filtered)
5267 if ((n > 0 || order_list[i] == file_view_data) &&
5268 !order_list[i]->need_update)
5270 unmanage[n++] = order_list[i]->widget;
5271 if (order_list[i]->treebtn)
5272 unmanage[n++] = order_list[i]->treebtn;
5276 /* remember which icon currently has the focus */
5277 if (XtIsManaged(file_mgr_rec->file_window))
5279 /* see if the focus is inside the file window */
5280 child = XmGetFocusWidget(file_mgr_rec->file_window);
5281 if (child != NULL && XtParent(child) == file_mgr_rec->file_window)
5282 file_mgr_rec->focus_widget = child;
5285 /* unmanage the selected children */
5287 XtUnmanageChildren(unmanage, n);
5289 XtFree((char *)unmanage);
5293 /************************************************************************
5296 * Create or reuse a set of file icons used to get the files
5297 * displayed. This is never called for the desktop.
5299 ************************************************************************/
5303 FileMgrRec *file_mgr_rec,
5304 FileMgrData *file_mgr_data,
5305 Boolean new_directory)
5307 _UpdateFileIcons(file_mgr_rec, file_mgr_data, new_directory, NULL);
5312 FileMgrRec *file_mgr_rec,
5313 FileMgrData *file_mgr_data,
5314 DirectorySet * add_dir_set)
5316 _UpdateFileIcons(file_mgr_rec, file_mgr_data, False, add_dir_set);
5320 /*--------------------------------------------------------------------
5323 * Background information:
5324 * After a refresh on a directory we want to reuse old icon and tree
5325 * button widgets instead of destroying the old widgets and creating
5326 * new ones. Fourthermore, we want to reuse the same widgets for the
5327 * same files, so that if the icon and/or label didn't change, less
5328 * work needs to be done in _UpdateFileIcons().
5329 * For this reason, after a refresh the GetFileData() routine copies
5330 * Widgets from the old FileViewData list to the new FileViewData list
5331 * for files that are both on the old and new list (i.e., files that
5332 * already existed before the refresh and are still there after the
5333 * refresh). This allows _UpdateFileIcons() to reuse the old
5336 * The purpose of MakeReuseList() is to find widgets that are no
5337 * longer found in the new FileViewData list. These are widgets
5338 * from files that disappeared after the refresh (either because the
5339 * file was deleted or because file is now filtered out). These
5340 * widgets can then be reused by _UpdateFileIcons()for new files that
5341 * just appeared after the refresh.
5343 *------------------------------------------------------------------*/
5345 /* compare function for qsort and bsearch */
5347 WidgetCmp(Widget *w1, Widget *w2)
5356 FileViewData **order_list,
5358 Widget **reuse_icons,
5359 Widget **reuse_btns)
5362 int n_old, n_filtered, del_icon, del_btn;
5364 Widget *sorted_chilren = NULL;
5365 Boolean *reuse = NULL;
5372 /* allocate widget arrays */
5373 *reuse_icons = (Widget *)XtMalloc((num_children + 1)*sizeof(Widget));
5374 *reuse_btns = (Widget *)XtMalloc((num_children + 1)*sizeof(Widget));
5375 icon_count = btn_count = 0;
5377 /* only figure things out if we already have children */
5378 if (num_children > 0) {
5379 /* create a sorted list of children */
5380 sorted_chilren = (Widget *)XtMalloc(num_children * sizeof(Widget));
5381 memcpy(sorted_chilren, children, num_children * sizeof(Widget));
5382 qsort(sorted_chilren, num_children, sizeof(Widget), (int (*)())WidgetCmp);
5384 /* create reuse flags; initially assume all children can be reused */
5385 reuse = (Boolean *)XtMalloc(num_children * sizeof(Boolean));
5386 for (i = 0; i < num_children; i++)
5389 /* reset reuse flag for all widgets found in order_list */
5391 n_old = n_filtered = del_icon = del_btn = 0;
5393 for (i = 0; i < order_count; i++)
5395 if (order_list[i]->filtered &&
5396 strcmp(order_list[i]->file_data->file_name, ".") != 0)
5398 /* don't reuse this widget later */
5401 if (order_list[i]->widget)
5403 if (order_list[i]->treebtn)
5406 order_list[i]->widget =
5407 order_list[i]->treebtn = NULL;
5411 if (order_list[i]->widget)
5413 p = bsearch(&order_list[i]->widget,
5414 sorted_chilren, num_children, sizeof(Widget),
5415 (int (*)())WidgetCmp);
5418 /* don't reuse this widget for any other file */
5419 reuse[p - sorted_chilren] = False;
5426 /* don't reuse this widget later */
5427 order_list[i]->widget = NULL;
5434 if (order_list[i]->treebtn)
5436 p = bsearch(&order_list[i]->treebtn,
5437 sorted_chilren, num_children, sizeof(Widget),
5438 (int (*)())WidgetCmp);
5441 /* don't reuse this widget for any other file */
5442 reuse[p - sorted_chilren] = False;
5446 /* don't reuse this widget later */
5447 order_list[i]->treebtn = NULL;
5456 /* copy reusable widgets into widget arrays */
5457 for (i = 0; i < num_children; i++)
5461 /* this widget can be reused for new files */
5462 w = sorted_chilren[i];
5463 if (XtClass(w) == dtIconGadgetClass)
5465 #ifndef DELAYED_UNREGISTER
5468 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
5469 XtRemoveAllCallbacks(w, XmNdropCallback);
5470 XtSetValues (w, args, 1);
5472 (*reuse_icons)[icon_count++] = w;
5474 else if (XtClass(w) == xmPushButtonGadgetClass)
5475 (*reuse_btns)[btn_count++] = w;
5480 /* null-terminate the arrays */
5481 (*reuse_icons)[icon_count] = NULL;
5482 (*reuse_btns)[btn_count] = NULL;
5485 XtFree((char *)sorted_chilren);
5486 XtFree((char *)reuse);
5488 DPRINTF(("MakeReuseList: count %d (%d new, %d old, %d filtered)\n",
5489 order_count, order_count - n_filtered - n_old, n_old, n_filtered));
5490 DPRINTF((" reuse %d + %d, del %d + %d\n",
5491 icon_count, btn_count, del_icon, del_btn));
5495 /*--------------------------------------------------------------------
5496 * UpdateOneIconLabel
5497 *------------------------------------------------------------------*/
5501 FileMgrData *file_mgr_data,
5502 FileViewData *file_view_data)
5507 /* Get the label and icon to be used for the widget */
5508 if (file_mgr_data->view != BY_ATTRIBUTES)
5510 if (strcmp(file_view_data->file_data->file_name, "..") == 0)
5512 /* label = ".. (go up)" */
5513 s = GetSharedMessage(UP_ONE_LEVEL_LABEL);
5514 label = (char *)XtMalloc(2 + strlen(s) + 1);
5515 strcpy(label, "..");
5518 else if (file_mgr_data->view == BY_NAME &&
5519 file_view_data->file_data->physical_type == DtDIRECTORY &&
5520 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
5522 /* label = "name/" */
5523 label = (char *)XtMalloc(
5524 strlen(file_view_data->file_data->file_name) + 2);
5525 strcpy(label, file_view_data->file_data->file_name);
5528 else if (file_mgr_data->view == BY_NAME &&
5529 file_view_data->file_data->physical_type == DtEXECUTABLE)
5531 /* label = "name*" */
5532 label = (char *)XtMalloc(
5533 strlen(file_view_data->file_data->file_name) + 2);
5534 strcpy(label, file_view_data->file_data->file_name);
5537 else if(file_view_data->file_data->action_name != NULL)
5538 /* label = action name */
5539 label = XtNewString(file_view_data->file_data->action_name);
5541 /* label = file name */
5542 label = XtNewString(file_view_data->file_data->file_name);
5544 else /* file_mgr_data->view == BY_ATTRIBUTES */
5546 /* label = file name + attributes */
5547 label = GetLongName(file_view_data->file_data);
5548 if (strcmp(file_view_data->file_data->file_name, "..") == 0)
5550 s = GetSharedMessage(UP_ONE_LEVEL_LABEL);
5551 label = (char *)XtRealloc(label, strlen(label) + strlen(s) + 1);
5556 /* store new label */
5557 XtFree(file_view_data->label);
5558 file_view_data->label = label;
5562 /*--------------------------------------------------------------------
5564 *------------------------------------------------------------------*/
5568 FileMgrRec *file_mgr_rec,
5569 FileMgrData *file_mgr_data,
5570 FileViewData *file_view_data)
5572 XmString icon_label;
5574 PixmapData *pixmapData;
5577 Boolean is_instance_icon;
5578 Boolean instance_icon_changed;
5584 XmManagerWidget file_window = (XmManagerWidget) file_mgr_rec->file_window;
5585 DirectorySet *directory_set = (DirectorySet *)file_view_data->directory_set;
5586 IconLayoutData *layout_data = (IconLayoutData *)file_mgr_data->layout_data;
5588 /* Get the label and icon to be used for the widget */
5589 if (!file_view_data->label)
5590 UpdateOneIconLabel(file_mgr_data, file_view_data);
5592 icon_label = XmStringCreateLocalized(file_view_data->label);
5594 /* Get the icon name based on the file type */
5596 logical_type = file_view_data->file_data->logical_type;
5598 if (file_mgr_data->view == BY_NAME)
5600 else if (openDirType == NEW &&
5601 file_view_data->file_data->physical_type == DtDIRECTORY)
5603 pixmapData = CheckForOpenDirectory(file_view_data,
5610 if (file_mgr_data->view == BY_NAME_AND_ICON)
5611 pixmapData = _DtRetrievePixmapData(
5613 file_view_data->file_data->file_name,
5614 directory_set->name,
5615 (Widget) file_window,
5618 pixmapData = _DtRetrievePixmapData(
5620 file_view_data->file_data->file_name,
5621 directory_set->name,
5622 (Widget) file_window,
5626 /* check if this is an instance icon */
5627 is_instance_icon = False;
5628 if (pixmapData != NULL)
5632 strcpy(tmp, directory_set->name);
5634 strcat(tmp, file_view_data->file_data->file_name);
5635 if (strcmp(pixmapData->iconFileName, tmp) == 0)
5636 is_instance_icon = True;
5639 /* check if instance icon was modified */
5640 instance_icon_changed = False;
5641 if (is_instance_icon)
5643 if (file_view_data->icon_mtime != file_view_data->file_data->stat.st_mtime)
5645 if (file_view_data->icon_mtime != 0)
5646 instance_icon_changed = True;
5647 file_view_data->icon_mtime = file_view_data->file_data->stat.st_mtime;
5651 file_view_data->icon_mtime = 0;
5653 /* Build the arg list for color resources. */
5655 XtSetArg (args[n], XmNarmColor, white_pixel); n++;
5657 if (layout_data->background == white_pixel)
5659 if (file_view_data->selected)
5661 XtSetArg (args[n], XmNbackground, black_pixel); n++;
5662 XtSetArg (args[n], XmNforeground, white_pixel); n++;
5666 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5667 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5669 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5670 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5672 else if (layout_data->background == black_pixel)
5674 if (file_view_data->selected)
5676 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5677 XtSetArg (args[n], XmNforeground, black_pixel); n++;
5681 XtSetArg (args[n], XmNbackground, black_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++;
5689 if (file_view_data->selected)
5691 XtSetArg (args[n], XmNbackground, white_pixel); n++;
5692 XtSetArg (args[n], XmNforeground, black_pixel); n++;
5693 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
5694 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
5698 XtSetArg (args[n], XmNbackground, layout_data->background); n++;
5699 XtSetArg (args[n], XmNforeground, layout_data->foreground); n++;
5700 XtSetArg (args[n], XmNpixmapBackground, layout_data->pixmap_back); n++;
5701 XtSetArg (args[n], XmNpixmapForeground, layout_data->pixmap_fore); n++;
5707 /* Build the rest of the arg list and either create or reuse the widget. */
5709 XtSetArg (args[n], XmNstring, icon_label); n++;
5712 XtSetArg (args[n], XmNimageName, pixmapData->iconFileName);
5714 XtSetArg (args[n], XmNimageName, NULL);
5716 XtSetArg (args[n], XmNmaxPixmapWidth, layout_data->pixmap_width); n++;
5717 XtSetArg (args[n], XmNmaxPixmapHeight, layout_data->pixmap_height); n++;
5718 XtSetArg (args[n], XmNuserData, directory_set); n++;
5719 XtSetArg (args[n], XmNunderline, False); n++;
5720 XtSetArg (args[n], XmNfillMode, XmFILL_TRANSPARENT); n++;
5721 if (file_mgr_data->view == BY_NAME_AND_ICON &&
5722 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
5723 XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_TOP);
5725 XtSetArg (args[n], XmNpixmapPosition, XmPIXMAP_LEFT); n++;
5727 /* See if we can re-use the same or some other icon gadget */
5728 if (file_view_data->widget)
5729 icon_widget = file_view_data->widget;
5730 else if (*layout_data->next_icon_to_use)
5731 icon_widget = *layout_data->next_icon_to_use++;
5735 /* See if we found an available icon gadget */
5738 /* reuse the icon gadget */
5739 if (icon_widget != file_view_data->widget || file_mgr_data->newSize)
5741 XtSetArg (args[n], XmNdropSiteOperations, XmDROP_NOOP);n++;
5742 XtRemoveAllCallbacks(icon_widget, XmNdropCallback);
5743 file_view_data->registered = False;
5745 XtRemoveAllCallbacks (icon_widget, XmNcallback);
5747 /* if instance_icon_changed, force destroy of old pixmap */
5748 if (instance_icon_changed)
5749 XtSetArg (args[argi_imageName], XmNimageName, NULL);
5752 * Move the gadget off the visible area; this avoids unnecessary
5753 * redraw events at the old position when the gadget is moved to
5754 * the correct position once it is determined in LayoutFileIcons.
5756 icon_widget->core.x = -999;
5757 icon_widget->core.y = -999;
5758 XtSetValues (icon_widget, args, n);
5760 if (instance_icon_changed && pixmapData)
5762 XtSetArg (args[0], XmNimageName, pixmapData->iconFileName);
5763 XtSetValues (icon_widget, args, 1);
5768 /* create a new or duplicate an existing widget */
5769 XtSetArg (args[n], XmNshadowThickness, 2); n++;
5770 XtSetArg (args[n], XmNdropSiteOperations, XmDROP_NOOP);n++;
5771 XtSetArg (args[n], XmNfontList, user_font); n++;
5772 if( keybdFocusPolicy == XmEXPLICIT)
5774 XtSetArg (args[n], XmNtraversalOn, True); n++;
5778 XtSetArg (args[n], XmNtraversalOn, False); n++;
5779 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
5781 XtSetArg (args[n], XmNborderType, DtNON_RECTANGLE); n++;
5783 if (layout_data->dup_icon_widget == NULL)
5785 #ifdef HARDCODED_ICON_MARGINS
5786 XtSetArg (args[n], XmNmarginWidth, 0); n++;
5787 XtSetArg (args[n], XmNmarginHeight, 0); n++;
5789 XtSetArg (args[n], XmNx, -999); n++;
5790 XtSetArg (args[n], XmNy, -999); n++;
5791 icon_widget = layout_data->dup_icon_widget =
5792 _DtCreateIcon ((Widget)file_window, "icon", args, n);
5797 int i = n_color_args;
5799 icon_widget = _DtDuplicateIcon ((Widget)file_window,
5800 layout_data->dup_icon_widget,
5802 (pixmapData? pixmapData->iconFileName: NULL),
5803 (XtPointer)directory_set, /* userData */
5804 False); /* underline */
5805 g = (DtIconGadget)icon_widget;
5806 g->gadget.highlighted = False;
5807 g->gadget.highlight_drawn = False;
5810 * Move the gadget off the visible area; this avoids unnecessary
5811 * redraw events at the old position when the gadget is moved to
5812 * the correct position once it is determined in LayoutFileIcons.
5814 icon_widget->core.x = -999;
5815 icon_widget->core.y = -999;
5817 /* make sure colors, drop operations, and clipping are right */
5818 XtSetArg(args[i], XmNdropSiteOperations, XmDROP_NOOP); i++;
5819 XtSetArg(args[i], XmNmaxPixmapWidth, layout_data->pixmap_width); i++;
5820 XtSetArg(args[i], XmNmaxPixmapHeight, layout_data->pixmap_height); i++;
5821 XtSetValues (icon_widget, args, i);
5823 XtAddCallback(icon_widget, XmNhelpCallback,
5824 (XtCallbackProc)HelpRequestCB, NULL);
5825 file_view_data->registered = False;
5828 if (file_mgr_data->view != BY_NAME)
5829 _DtCheckAndFreePixmapData(logical_type,
5830 (Widget) file_window,
5831 (DtIconGadget) icon_widget,
5835 if (file_view_data->file_data->link != 0)
5837 XtSetArg (args[0], XmNforeground, layout_data->topshadow);
5838 XtSetValues (icon_widget, args, 1);
5843 * If viewing by attributes, adjust spacing between the icon pixmap and
5844 * the file name so that all file names are aligned.
5846 if (file_mgr_data->view != BY_NAME_AND_ICON ||
5847 file_mgr_data->show_type == MULTIPLE_DIRECTORY)
5849 Dimension pixmap_width = ((DtIconGadget)icon_widget)->icon.pixmap_width;
5851 if (pixmap_width < layout_data->pixmap_width)
5853 XtSetArg (args[0], XmNspacing,
5854 layout_data->spacing + layout_data->pixmap_width - pixmap_width);
5855 XtSetValues (icon_widget, args, 1);
5860 file_view_data->file_data->is_broken = False;
5861 file_view_data->widget = icon_widget;
5862 XtAddCallback (icon_widget, XmNcallback, (XtCallbackProc)IconCallback,
5865 XmStringFree (icon_label);
5867 /* Check if we need a button for tree branch expand */
5869 if (file_mgr_data->show_type != MULTIPLE_DIRECTORY ||
5870 !file_view_data->file_data->is_subdir)
5872 /* no tree branch expand button needed */
5873 file_view_data->treebtn = NULL;
5877 /* create a tree branch expand button */
5878 Pixmap px = GetTreebtnPixmap(file_mgr_data, file_view_data);
5881 XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
5882 XtSetArg(args[n], XmNlabelPixmap, px); n++;
5883 XtSetArg(args[n], XmNbackground, layout_data->background); n++;
5884 XtSetArg(args[n], XmNtraversalOn, False); n++;
5885 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
5886 XtSetArg(args[n], XmNshadowThickness, 0); n++;
5887 XtSetArg(args[n], XmNmarginWidth, 0); n++;
5888 XtSetArg(args[n], XmNmarginHeight, 0); n++;
5889 XtSetArg(args[n], XmNuserData, file_mgr_data); n++;
5890 XtSetArg(args[n], XmNx, -999); n++;
5891 XtSetArg(args[n], XmNy, -999); n++;
5893 /* See if we can re-use the same or some other button gadget */
5894 if (file_view_data->treebtn)
5895 btn_widget = file_view_data->treebtn;
5896 else if (*layout_data->next_btn_to_use)
5897 btn_widget = *(layout_data->next_btn_to_use)++;
5901 /* See if we found an available button gadget */
5903 XtRemoveAllCallbacks (btn_widget, XmNactivateCallback);
5904 XtSetValues (btn_widget, args, n);
5908 btn_widget = XmCreatePushButtonGadget((Widget)file_window,
5909 "tree_button", args, n);
5911 XtAddCallback(btn_widget, XmNactivateCallback,
5912 (XtCallbackProc)TreeBtnCallback, file_view_data);
5914 file_view_data->treebtn = btn_widget;
5917 /* this entry is now up-to-date */
5918 file_view_data->need_update = False;
5922 /*--------------------------------------------------------------------
5924 *------------------------------------------------------------------*/
5928 FileMgrRec *file_mgr_rec,
5929 FileMgrData *file_mgr_data,
5930 Boolean new_directory,
5931 DirectorySet * add_dir_set)
5933 XmManagerWidget file_window;
5934 FileViewData **order_list;
5938 IconLayoutData *layout_data;
5941 #ifdef DT_PERFORMANCE
5942 struct timeval update_time_s;
5943 struct timeval update_time_f;
5946 DPRINTF(("_UpdateFileIcons(\"%s\", new_dir %c, add_dir_set %p) ...\n",
5947 file_mgr_data->current_directory,
5948 new_directory? 'T': 'F', add_dir_set));
5950 /* Set the size of the file window BIG so that it does not */
5951 /* try to force positioning on its children. */
5952 file_window = (XmManagerWidget) file_mgr_rec->file_window;
5953 XtResizeWidget ((Widget)file_window, 32767, 32767, 0);
5955 /* Set the scrolled window and file window appropriately */
5956 /* to prevent a lot of gyrations. */
5958 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmSTATIC);
5959 XtSetValues (file_mgr_rec->scroll_window, args, 1);
5961 /* For faster updates, unmanage all the icons */
5962 if (XtIsManaged(file_mgr_rec->file_window))
5964 /* see if the focus is inside the file window */
5965 child = XmGetFocusWidget(file_mgr_rec->file_window);
5970 file_mgr_rec->focus_widget = file_mgr_rec->file_window;
5972 else if( XtParent(child) == file_mgr_rec->file_window )
5974 /* remember which widget had the focus */
5975 file_mgr_rec->focus_widget = child;
5979 DPRINTF((" focus_widget = %p (%s)\n",
5980 file_mgr_rec->focus_widget,
5981 file_mgr_rec->focus_widget?
5982 XtName(file_mgr_rec->focus_widget): "nil"));
5983 XtUnmanageChild(file_mgr_rec->file_window);
5986 XtUnmanageChildren(file_window->composite.children,
5987 file_window->composite.num_children);
5989 /* if this is a new directory, scroll to the top */
5992 XtSetArg (args[0], XmNx, 0);
5993 XtSetArg (args[1], XmNy, 0);
5994 XtSetValues ((Widget)file_window, args, 2);
5998 * Don't leave the view in a munged state for too long.
5999 * Only do if we are not creating a new view. This is because the
6000 * view is not yet in the 'view_list', and so the redisplay code
6001 * may not use the correct redisplay function.
6003 if (ReturnDesktopPtr(file_mgr_rec->file_window))
6005 UpdateHeaders(file_mgr_rec, file_mgr_data, False);
6006 XFlush (XtDisplay (file_window));
6007 XmUpdateDisplay ((Widget)file_window);
6010 /* free any old layout data */
6011 FreeLayoutData(file_mgr_data->layout_data);
6012 file_mgr_data->layout_data = NULL;
6014 /* if directory-read still in progress, don't do anything more now */
6015 if (file_mgr_data->busy_status != not_busy)
6017 DPRINTF(("done (busy)\n"));
6021 #ifdef DT_PERFORMANCE
6022 printf(" Beginning UpdateFileIcons\n");
6023 gettimeofday(&update_time_s, NULL);
6026 _DtPerfChkpntMsgSend("Begin Update Icons");
6030 /* set up new layout data */
6031 layout_data = (IconLayoutData *)XtCalloc(1, sizeof(IconLayoutData));
6032 file_mgr_data->layout_data = (XtPointer)layout_data;
6034 FlattenTree(file_mgr_data, &order_list, &order_count);
6035 layout_data->order_list = order_list;
6036 layout_data->order_count = order_count;
6038 MakeReuseList(file_window->composite.children,
6039 file_window->composite.num_children,
6040 order_list, order_count,
6041 &layout_data->reuse_icons,
6042 &layout_data->reuse_btns);
6043 layout_data->next_icon_to_use = layout_data->reuse_icons;
6044 layout_data->next_btn_to_use = layout_data->reuse_btns;
6046 layout_data->manage = (Widget *)XtMalloc(2*order_count*sizeof(Widget));
6047 layout_data->manage_count = 0;
6049 layout_data->i_do_next_vis = 0;
6050 layout_data->i_do_next_all = 0;
6053 * Iterate through the file list and mark all entries to be in
6054 * need of update. We also construct icon labels at this time,
6055 * since they are need by LayoutFileIcons to estimate icon gadget
6061 /* only need to iterate throught the new entries */;
6062 order_list = add_dir_set->order_list;
6063 order_count = add_dir_set->file_count;
6066 for (i = 0; i < order_count; i++)
6068 order_list[i]->need_update = True;
6069 order_list[i]->selected = False;
6070 UpdateOneIconLabel(file_mgr_data, order_list[i]);
6073 /* set selected flag on all files in selection_list */
6074 for (i = 0; i < file_mgr_data->selected_file_count; i++)
6075 file_mgr_data->selection_list[i]->selected = True;
6077 #ifdef DT_PERFORMANCE
6078 gettimeofday(&update_time_f, NULL);
6079 if (update_time_s.tv_usec > update_time_f.tv_usec) {
6080 update_time_f.tv_usec += 1000000;
6081 update_time_f.tv_sec--;
6083 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);
6086 _DtPerfChkpntMsgSend("Done Update Icons");
6089 DPRINTF(("done\n"));
6095 /************************************************************************
6098 * Create icons for tree-branch-expand buttons.
6100 ************************************************************************/
6103 CreateTreeIcons(Widget w)
6106 Pixel background_color = 0;
6107 Pixel foreground_color = 0;
6111 unsigned int width, height, dummy;
6113 XtSetArg (args[0], XmNbackground, &background_color);
6114 XtSetArg (args[1], XmNforeground, &foreground_color);
6115 XtGetValues (w, args, 2);
6117 for (i = 0; i < 3; i++)
6121 for (j = 0; j < tpxN; j++)
6123 strcpy(pxname, TreePxTab[j].name);
6124 strcat(pxname, TreePxSuffix[i]);
6125 TreePxTab[j].px[i] = _DtGetPixmap(XtScreen(w), pxname,
6126 foreground_color, background_color);
6128 XGetGeometry(XtDisplay(w), TreePxTab[j].px[i],
6129 (Window *) &dummy, /* returned root window */
6130 (int *) &dummy, (int *) &dummy, /* x, y of pixmap */
6131 &width, &height, /* pixmap width, height */
6132 &dummy, &dummy); /* border width, depth */
6135 TreeNilWd[i] = width;
6136 TreeNilHt[i] = height;
6140 if (width > TreeBtnWd[i])
6141 TreeBtnWd[i] = width;
6142 if (height > TreeBtnHt[i])
6143 TreeBtnHt[i] = height;
6150 /************************************************************************
6153 * Get icon for tree-branch-expand buttons.
6155 ************************************************************************/
6157 Pixmap GetTreebtnPixmap(
6158 FileMgrData *file_mgr_data,
6159 FileViewData *file_view_data)
6163 /* if not yet done, create tree button icons */
6164 /* @@@ do this earlier from main? */
6165 if (TreeBtnWd[0] == 0)
6166 CreateTreeIcons(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
6168 if (file_view_data->ts == tsNotRead)
6170 else if (file_view_data->ts == tsError)
6172 else if (file_view_data->ndir == 0 &&
6173 (file_view_data->nfile == 0 ||
6174 file_mgr_data->tree_files == TREE_FILES_NEVER)
6175 && (file_view_data->ts == tsNone || !showEmptySet))
6177 else if (file_view_data->ts == tsNone)
6179 else if (file_view_data->ts == tsDirs)
6180 pxid = (file_view_data->nfile == 0 ||
6181 file_mgr_data->tree_files == TREE_FILES_NEVER)? tpxLess:
6182 (file_view_data->ndir == 0)? tpxMore:
6184 else if (file_view_data->ts == tsAll)
6187 if (file_mgr_data->view == BY_NAME)
6188 return TreePxTab[pxid].px[0]; /* small pixmap */
6189 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6190 return TreePxTab[pxid].px[2]; /* large pixmap */
6192 return TreePxTab[pxid].px[1]; /* medium pixmap */
6196 /************************************************************************
6199 * Compute maximum icon size.
6201 ************************************************************************/
6205 FileMgrRec *file_mgr_rec,
6206 FileMgrData *file_mgr_data,
6209 DirectorySet *directory_set;
6211 FileViewData **file_list;
6215 Dimension shadowThickness;
6216 Dimension marginWidth;
6217 Dimension maxWidth = ld->pixmap_width;
6218 Dimension gadgetWidth;
6220 /* determine pixmap size */
6221 if (file_mgr_data->view == BY_NAME)
6224 ld->pixmap_width = 0;
6225 ld->pixmap_height = 0;
6227 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6230 ld->pixmap_width = largeIconWidth;
6231 ld->pixmap_height = largeIconHeight;
6236 ld->pixmap_width = smallIconWidth;
6237 ld->pixmap_height = smallIconHeight;
6240 /* find the icon gadget for "." */
6241 directory_set = file_mgr_data->directory_set[0];
6242 file_count = directory_set->file_count;
6243 file_list = directory_set->file_view_data;
6246 for (i = 0; i < file_count; i++)
6248 if (strcmp(file_list[i]->file_data->file_name, ".") == 0)
6250 g = (DtIconGadget)file_list[i]->widget;
6255 /* get layout parameters from "." */
6258 XtSetArg(args[0], XmNhighlightThickness, &ld->highlight);
6259 XtSetArg(args[1], XmNshadowThickness, &shadowThickness);
6260 XtSetArg(args[2], XmNmarginWidth, &marginWidth);
6261 XtSetArg(args[3], XmNspacing, &ld->spacing);
6262 XtSetArg(args[4], XmNalignment, &ld->alignment);
6263 XtSetArg(args[5], XmNpixmapPosition, &ld->pixmap_position);
6264 XtGetValues((Widget)g, args, 6);
6266 if (g->icon.pixmap_width < maxWidth)
6267 ld->spacing = ld->spacing - (maxWidth - g->icon.pixmap_width);
6269 ld->width = ((Widget)g)->core.width +
6270 ld->pixmap_width - g->icon.pixmap_width;
6271 ld->height = ((Widget)g)->core.height +
6272 ld->pixmap_height - g->icon.pixmap_height;
6274 ld->char_width = (g->icon.string_width)/strlen(file_list[i]->label);
6275 if (ld->pixmap_position != XmPIXMAP_TOP)
6276 ld->width -= g->icon.string_width;
6277 ld->margin = ld->highlight + shadowThickness + marginWidth;
6281 /* No icon gadget for "." found: strange! Guess some defaults. */
6283 ld->margin = 2 + 1 + 1;
6285 ld->highlight = (keybdFocusPolicy == XmEXPLICIT)? 2: 0;
6286 ld->alignment = XmALIGNMENT_END;
6287 if (file_mgr_data->view == BY_NAME_AND_ICON &&
6288 file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6290 ld->pixmap_position = XmPIXMAP_TOP;
6291 ld->width = 2*ld->margin + ld->pixmap_width;
6292 ld->height = 2*ld->margin + ld->pixmap_height + ld->spacing + 14;
6296 ld->pixmap_position = XmPIXMAP_LEFT;
6297 ld->width = 2*ld->margin + ld->pixmap_width +
6298 ld->spacing + ld->char_width;
6299 ld->height = 2*ld->margin + ld->pixmap_height;
6303 /* determine which size tree buttons to use */
6304 if (file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6305 ld->treebtn_size = 0; /* no tree buttons needed */
6306 else if (file_mgr_data->view == BY_NAME)
6307 ld->treebtn_size = 0; /* small size */
6308 else if (file_mgr_data->view == BY_NAME_AND_ICON)
6309 ld->treebtn_size = 2; /* large size */
6311 ld->treebtn_size = 1; /* medium size */
6317 FileMgrRec *file_mgr_rec,
6318 FileMgrData *file_mgr_data,
6319 IconLayoutData *layout_data,
6320 FileViewData *file_view_data,
6327 if (file_view_data == NULL)
6329 else if (file_view_data->label == NULL)
6330 label_len = strlen(file_view_data->file_data->file_name);
6332 label_len = strlen(file_view_data->label);
6334 if (layout_data->pixmap_position == XmPIXMAP_TOP)
6336 label_width = 2*layout_data->margin + label_len*layout_data->char_width;
6337 if ((Dimension)label_width > layout_data->width)
6338 *width = label_width;
6340 *width = layout_data->width;
6343 *width = layout_data->width + (label_len) * layout_data->char_width;
6344 *height = layout_data->height;
6348 /************************************************************************
6351 * Compute extra height for drawing nil symbol for empty tree branches.
6353 ************************************************************************/
6357 FileMgrData *file_mgr_data,
6358 FileViewData *file_view_data,
6362 file_view_data->file_data->is_subdir &&
6363 file_view_data->ts >= tsDirs &&
6364 file_view_data->ndir == 0 &&
6365 (file_view_data->nfile == 0 ||
6366 file_mgr_data->tree_files == TREE_FILES_NEVER))
6368 return YSPACING(file_mgr_data) + TreeNilHt[treebtn_size];
6375 /************************************************************************
6378 * Erase connecting lines in tree mode from a specified icon widget
6379 * on down; called when a tree branch is expanded or collapsed to
6380 * erase previous tree lines before drawing new icons and tree lines.
6382 ************************************************************************/
6386 FileMgrRec *file_mgr_rec,
6387 FileMgrData *file_mgr_data,
6388 FileViewData *file_view_data)
6390 XmManagerWidget file_window;
6391 Dimension fw_width, fw_height;
6394 file_window = (XmManagerWidget) file_mgr_rec->file_window;
6395 if (!XtIsManaged((Widget)file_window))
6398 /* get upper left corner of grid space for the icon widget */
6399 x = file_view_data->x;
6400 y = file_view_data->y - file_mgr_data->grid_height;
6402 /* Get file window width and height */
6403 fw_width = file_window->core.width;
6404 fw_height = file_window->core.height;
6406 DPRINTF2(("EraseTreeLines(\"%s\"): x/y %d/%d (widget %d/%d)\n",
6407 file_view_data->file_data->file_name, x, y,
6408 file_view_data->widget->core.x,
6409 file_view_data->widget->core.y));
6411 /* clear area from icon widget to bottom of file window */
6412 XClearArea(XtDisplay(file_window), XtWindow(file_window),
6413 x, y, fw_width - x, fw_height - y, False);
6416 * clear area to the right and above the icon widget
6417 * (necessary if there are multiple columns, which happens if
6418 * there are more icons than fit into a single column of
6419 * maximum height 32767)
6421 if (y > 0 && (Dimension)(x + file_mgr_data->grid_width) < fw_width)
6423 x += file_mgr_data->grid_width;
6424 XClearArea(XtDisplay(file_window), XtWindow(file_window),
6425 x, 0, fw_width - x, y, False);
6430 /************************************************************************
6433 * Redraw connecting lines in tree mode.
6435 ************************************************************************/
6440 int ex, int ey, int ewidth, int eheight, int ecount,
6441 FileMgrRec *file_mgr_rec,
6442 FileMgrData *file_mgr_data)
6444 static char *empty_msg = NULL;
6446 FileViewData *file_view_data;
6447 IconLayoutData *layout_data;
6448 Dimension grid_width, grid_height;
6449 Dimension extra_height, e_height;
6451 FileViewData **order_list;
6453 GC solid_gc, dash_gc;
6459 XFontSetExtents *extents;
6464 if (!XtIsManaged(w))
6467 /* get layout parameters */
6468 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
6469 order_list = layout_data->order_list;
6470 order_count = layout_data->order_count;
6471 grid_width = file_mgr_data->grid_width;
6472 grid_height = file_mgr_data->grid_height;
6473 sz = layout_data->treebtn_size;
6475 DPRINTF2(("RedrawTreeLines(x %d, y %d, wd %d, ht %d, count %d)\n",
6476 ex, ey, ewidth, eheight, ecount));
6478 if (grid_width == 0 || grid_height == 0)
6479 /* layout probably not yet done */
6482 /* if not yet done, create tree button icons */
6483 /* @@@ do this earlier from main? */
6484 if (TreeBtnWd[0] == 0)
6485 CreateTreeIcons(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window);
6487 /* select line styles */
6488 if (file_mgr_data->view == BY_NAME) {
6489 solid_gc = file_mgr_data->tree_solid_thin_gc;
6490 dash_gc = file_mgr_data->tree_dash_thin_gc;
6492 solid_gc = file_mgr_data->tree_solid_thick_gc;
6493 dash_gc = file_mgr_data->tree_dash_thick_gc;
6499 for (k = 0; k < order_count; k++)
6501 if (!order_list[k]->displayed)
6504 /* determine the height of this item */
6505 file_view_data = order_list[k];
6506 extra_height = GetExtraHeight(file_mgr_data, file_view_data, sz);
6507 GetLevel(file_view_data, &level);
6509 /* check if we need to go to the next column */
6510 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
6511 if (tmp + MARGIN > MAXWINSIZE)
6513 /* window would exceed height limit; go to the next column */
6514 x += grid_width + XSPACING;
6516 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
6519 /* check if current item intersects the exposed region */
6520 y0 = y - YSPACING(file_mgr_data)
6522 + (Dimension)(grid_height - TreeBtnHt[sz])/(Dimension)2
6524 y1 = y + grid_height + extra_height + YSPACING(file_mgr_data);
6525 if (x <= ex + ewidth && x + TreeWd(level, sz) > ex &&
6526 y0 <= ey + eheight && y1 > ey)
6528 GetAncestorInfo(file_mgr_data, file_view_data, NULL, NULL, more);
6530 /* draw vertical connecting lines for upper tree levels */
6531 for (i = 0; i < level; i++) {
6533 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6534 x + TreeLX(i, sz), y0,
6535 x + TreeLX(i, sz), y1);
6538 /* draw vertical connecting line for this tree level */
6539 xl = x + TreeLX(level, sz);
6541 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6543 xl, more[level]? y1: y + grid_height/2);
6545 if (file_view_data->file_data->is_subdir || !more[level]) {
6546 /* draw horizontal line */
6547 XDrawLine(XtDisplay(w), XtWindow(w),
6548 (file_view_data->file_data->is_subdir &&
6549 file_view_data->ts == tsNotRead)? dash_gc: solid_gc,
6550 xl, y + grid_height/2,
6551 xl + TreeOffset, y + grid_height/2);
6555 /* draw nil symbol for empty subdirs */
6558 xl += TreeOneWd(sz);
6559 y0 += grid_height + YSPACING(file_mgr_data);
6560 y1 = y + grid_height + YSPACING(file_mgr_data);
6561 e_height = extra_height - YSPACING(file_mgr_data);
6563 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6565 xl, y1 + e_height/2);
6567 XDrawLine(XtDisplay(w), XtWindow(w), solid_gc,
6568 xl, y1 + e_height/2,
6569 xl + TreeOffset, y1 + e_height/2);
6571 xl = x + TreeWd(level, sz) + TreeBtnWd[sz];
6572 XCopyArea(XtDisplay(w), TreePxTab[tpxNil].px[sz],
6573 XtWindow(w), solid_gc,
6574 0, 0, TreeNilWd[sz], TreeNilHt[sz],
6577 if (empty_msg == NULL)
6578 empty_msg = XtNewString("(empty)");
6580 if (file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET)
6582 extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
6583 font_yoffset = extents->max_logical_extent.y;
6584 font_height = extents->max_logical_extent.height;
6588 font_yoffset = file_mgr_data->cd_font->ascent;
6589 font_height = file_mgr_data->cd_font->ascent +
6590 file_mgr_data->cd_font->descent;
6593 XDrawImageString(XtDisplay(w), XtWindow(w), solid_gc,
6594 xl + TreeNilWd[sz] + 2,
6595 y1 + (TreeNilHt[sz] - font_height)/2 + font_yoffset,
6596 empty_msg, strlen(empty_msg));
6601 /* goto next item */
6607 /************************************************************************
6610 * Check if any incons or widgets in the area given by ex, ey, ewd,
6611 * and eht need to be updated.
6613 ************************************************************************/
6616 static int g_workCount1 = 0;
6617 static int g_workCount2 = 0;
6618 static int g_callCount = 0;
6623 IconLayoutData *layout_data,
6624 FileViewData *file_view_data)
6628 for (i = 0; i < layout_data->manage_count; i++)
6629 if (layout_data->manage[i] == file_view_data->widget)
6638 FileMgrRec *file_mgr_rec,
6639 FileMgrData *file_mgr_data,
6640 int ex, int ey, int ewd, int eht,
6644 #ifdef DT_PERFORMANCE
6645 struct timeval update_time_s;
6646 struct timeval update_time_f;
6648 XmManagerWidget file_window;
6649 FileViewData **order_list;
6652 Arg args_dso_get[1];
6653 Arg args_dso_set[1];
6654 IconLayoutData *layout_data;
6655 FileViewData **change;
6661 Dimension grid_width, grid_height;
6662 Dimension icon_width, icon_height;
6663 Dimension extra_height;
6666 FileViewData *file_view_data;
6671 unsigned char operations;
6673 ObjectPosition *position_data;
6674 XRectangle textExtent;
6676 /* Get a list of icon and button widgets we can re-use */
6677 file_window = (XmManagerWidget) file_mgr_rec->file_window;
6678 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
6679 order_list = layout_data->order_list;
6680 order_count = layout_data->order_count;
6681 manage = layout_data->manage + layout_data->manage_count;
6683 /* allocate storage for list of changed icons */
6684 change = (FileViewData **)XtMalloc(order_count * sizeof(FileViewData *));
6686 /* Find the maximum values for the icon heights and widths */
6687 grid_width = file_mgr_data->grid_width;
6688 grid_height = file_mgr_data->grid_height;
6691 #ifdef DT_PERFORMANCE
6692 printf(" Begin Part 1, DisplaySomeIcons (update icons)\n");
6693 gettimeofday(&update_time_s, NULL);
6696 _DtPerfChkpntMsgSend("Begin Display Icons");
6700 "DisplaySomeIcons(\"%s\", x/y %d/%d, wd/ht %d/%d, i %d:%d) ...\n",
6701 file_mgr_data->current_directory, ex, ey, ewd, eht,
6702 layout_data->i_do_next_vis,
6703 layout_data->i_do_next_all));
6705 /* set up args for querying/unregistering drop sites */
6706 XtSetArg (args_dso_get[0], XmNdropSiteOperations, &operations);
6707 XtSetArg (args_dso_set[0], XmNdropSiteOperations, XmDROP_NOOP);
6710 * Iterate through the list of files and create/update and position
6711 * all visible icon gadgets for which this work hasn't been done yet
6712 * (need_update flag set).
6720 k = layout_data->i_do_next_all;
6722 k = layout_data->i_do_next_vis;
6723 for ( ; k < order_count && workCount1 < workLimit; k++)
6726 * Process focus widget before everything else so that we can restore
6727 * the focus when we manage the file_window again. If a file was
6728 * being renamed, we do that one first.
6730 if (!layout_data->focus_done)
6732 /* search for focus widget in order_list and see if still displayed */
6733 file_view_data = NULL;
6734 if (file_mgr_rec->focus_widget != NULL)
6736 if (file_mgr_rec->focus_widget == file_mgr_rec->file_window)
6738 for (i = 0; i < order_count; i++)
6739 if (order_list[i]->displayed)
6741 file_view_data = order_list[i];
6747 for (i = 0; i < order_count; i++)
6748 if (order_list[i]->widget == file_mgr_rec->focus_widget)
6750 if (order_list[i]->displayed)
6751 file_view_data = order_list[i];
6757 /* if not found, focus could be on a rename text widget */
6758 if (file_view_data == NULL)
6759 file_view_data = file_mgr_data->renaming;
6761 layout_data->focus_done = True;
6766 /* decrement loop index, so that the entry that was supposed to be
6767 processed here will be looked at again in the next iteration
6774 /* ignore files that are filtered */
6775 file_view_data = order_list[k];
6776 if (file_view_data->filtered &&
6777 strcmp(file_view_data->file_data->file_name, ".") != 0)
6783 * If the file is not currenly displayed (collapsed tree branch) or
6784 * is currenly scrolled out of view, we don't need to do anything
6785 * at this time. Except ...
6787 if (!file_view_data->displayed ||
6788 ((int)file_view_data->x + (int)grid_width) < ex ||
6789 file_view_data->x >= ex + ewd ||
6790 file_view_data->y < ey ||
6791 ((int)file_view_data->y - (int)grid_height) >= (ey + eht))
6794 * ... if this file still has an old icon widget, AND if the
6795 * old icon position is visible, AND if the icon was registered
6796 * as a drop site, we will have a "ghost drop zone" showing up where
6797 * the icon used to be. The old icon gadget is unmanaged and will
6798 * remain unmanaged until later when we update it and move it to the
6799 * correct positon (happens only when the user scrolls to the new
6800 * position). In the meantime, even though the gadget is unmanged,
6801 * its old position still remains registered as a drop site,
6802 * so we have to either unregister it or move the gadget to
6803 * its new position now.
6805 child = file_view_data->widget;
6806 if (child != NULL &&
6807 (Position)(child->core.x + child->core.width) >= (Position)ex &&
6808 child->core.x < ex + ewd &&
6809 (Position)(child->core.y + child->core.height) >= (Position)ey &&
6810 child->core.y < ey + eht)
6812 if (!file_view_data->displayed)
6814 XtGetValues (child, args_dso_get, 1);
6815 if (operations != XmDROP_NOOP)
6817 XtSetValues (child, args_dso_set, 1);
6819 file_view_data->registered = False;
6830 * If not yet done, create/update the icon gadget for this file
6832 if (file_view_data->need_update)
6834 UpdateOneFileIcon(file_mgr_rec, file_mgr_data, file_view_data);
6835 child = file_view_data->widget;
6838 * We may need to adjust the icon position based on the difference
6839 * between estimated size and actual size.
6841 if (layout_data->alignment == XmALIGNMENT_CENTER &&
6842 file_mgr_data->view == BY_NAME_AND_ICON)
6844 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data,
6845 file_view_data, &icon_width, &icon_height);
6847 if (child->core.width != icon_width)
6849 file_view_data->x = file_view_data->x
6850 - (Dimension)(grid_width - icon_width)/(Dimension)2
6851 + (Dimension)(grid_width - child->core.width)/(Dimension)2;
6855 if (PositioningEnabledInView(file_mgr_data))
6857 position_data = file_view_data->position_info;
6858 if (position_data->late_bind)
6861 * When new objects are dropped on the random placement window,
6862 * they do not yet have a widget, so the drop_y could not be
6863 * adjusted to take into account the height of the icon;
6864 * this must be done now, after the object has an icon.
6867 position_data->y -= child->core.height/2;
6869 position_data->late_bind = False;
6870 file_view_data->y = position_data->y + child->core.height;
6872 else if (child->core.height != grid_height)
6875 * Not quite right: have to distinguish two cases:
6876 * (1) position_data->y read from .!xxx file
6877 * file_view_data->y computed by adding grid_height
6878 * (2) file_view_data->y from layout
6879 * position_data->y computed by subtracting grid_height
6880 * In case (1) have to recompute file_view_data->y; in case
6881 * (2) have to recompute position_data->y. Code below only
6882 * works for case (2).
6885 position_data->y = file_view_data->y - child->core.height;
6896 /* if focus is supposed to be in the file window, focus on this widget */
6897 if (file_mgr_rec->focus_widget == file_mgr_rec->file_window)
6898 file_mgr_rec->focus_widget = file_view_data->widget;
6901 /* determine desired icon postition */
6902 child = file_view_data->widget;
6904 if (PositioningEnabledInView(file_mgr_data))
6906 x = file_view_data->position_info->x;
6907 y = file_view_data->position_info->y;
6909 else if (file_mgr_data->show_type != MULTIPLE_DIRECTORY)
6911 x = file_view_data->x;
6912 y = file_view_data->y - child->core.height;
6914 else /* file_mgr_data->show_type == MULTIPLE_DIRECTORY */
6916 GetLevel(file_view_data, &level);
6917 extra_height = GetExtraHeight(file_mgr_data, file_view_data,
6918 layout_data->treebtn_size);
6920 /* check position of tree button, if any */
6921 if (file_view_data->treebtn)
6923 child = file_view_data->treebtn;
6925 x = file_view_data->x
6926 + TreeLX(level, layout_data->treebtn_size) + TreeOffset;
6927 y = file_view_data->y
6929 + (Dimension)(grid_height - child->core.height)/(Dimension)2;
6931 if (child->core.x != x || child->core.y != y)
6932 XmeConfigureObject(child, x, y, child->core.width,
6933 child->core.height, child->core.border_width);
6935 child = file_view_data->widget;
6938 if (child->core.height < grid_height)
6940 x = file_view_data->x + TreeWd(level, layout_data->treebtn_size);
6941 y = file_view_data->y
6943 +(Dimension)(grid_height - child->core.height)/(Dimension)2;
6947 x = file_view_data->x + TreeWd(level, layout_data->treebtn_size);
6948 y = file_view_data->y - grid_height;
6952 if (child->core.x != x || child->core.y != y)
6954 XmeConfigureObject(child, x, y, child->core.width,
6955 child->core.height, child->core.border_width);
6959 /* make sure the icon gadget and tree button, if any, are managed */
6960 if (!XtIsManaged(child) && !ToBeManaged(layout_data, file_view_data))
6962 manage[manageCount++] = child;
6963 if (file_view_data->treebtn)
6964 manage[manageCount++] = file_view_data->treebtn;
6970 /* remember which icons were changed */
6971 change[changeCount++] = file_view_data;
6975 * If the icon we just changed was being renamed, make sure
6976 * the corresponding text widget is positioned correctly.
6978 if (file_view_data == file_mgr_data->renaming)
6980 for (i = 0; i < file_window->composite.num_children; i++)
6982 child = file_window->composite.children[i];
6983 if (XmIsTextField(child))
6985 /* Check if the text field is still needed */
6986 if (!child->core.being_destroyed)
6988 /* move to the correct position */
6989 _DtIconGetTextExtent_r(file_view_data->widget,
6993 (Dimension)(child->core.height - textExtent.height)/(Dimension)2;
6994 XmeConfigureObject(child, x, y, child->core.width,
6996 child->core.border_width);
6999 manage[manageCount++] = child;
7008 /* remember where we left off ... */
7010 layout_data->i_do_next_all = k;
7012 layout_data->i_do_next_vis = k;
7014 #ifdef DT_PERFORMANCE
7015 gettimeofday(&update_time_f, NULL);
7016 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7017 update_time_f.tv_usec += 1000000;
7018 update_time_f.tv_sec--;
7020 printf(" done Part 1, DisplaySomeIcons, time: %ld.%ld\n\n",
7021 update_time_f.tv_sec - update_time_s.tv_sec,
7022 update_time_f.tv_usec - update_time_s.tv_usec);
7024 /* the following message send call added by Rafi */
7025 _DtPerfChkpntMsgSend("Done Display Icons");
7028 #ifdef DT_PERFORMANCE
7029 printf(" Begin Part 2, DisplaySomeIcons (register drop sites)\n");
7030 gettimeofday(&update_time_s, NULL);
7033 _DtPerfChkpntMsgSend("Begin Register drop sites");
7036 /* unregister drop sites of unused icon gadgets */
7038 #ifdef DELAYED_UNREGISTER
7039 for (wp = layout_data->next_icon_to_use;
7040 (child = *wp) != NULL;
7043 if ((Position)(child->core.x + child->core.width) >= (Position)ex &&
7044 child->core.x < ex + ewd &&
7045 (Position)(child->core.y + child->core.height) >= (Position)ey &&
7046 child->core.y < ey + eht)
7048 XtGetValues (child, args_dso_get, 1);
7049 if (operations != XmDROP_NOOP)
7051 XtSetValues (child, args_dso_set, 1);
7054 if (workCount2/2 >= workLimit)
7062 * Register drop sites
7064 * Note: in "as placed" mode, we defer this work and do it in
7065 * CommitWorkProcUpdates instead. Reason: need to re-register
7066 * all drop sites in top-to-bottom stacking order at that time.
7068 if (! PositioningEnabledInView(file_mgr_data) &&
7069 file_mgr_data != trashFileMgrData)
7071 for (k = 0; k < changeCount; k++)
7073 SetHotRects(change[k],
7074 (XtCallbackProc) DropOnObject,
7075 (XtPointer) change[k]);
7080 XtFree((char *)change);
7083 /* update count of children to be managed */
7084 layout_data->manage_count += manageCount;
7087 #ifdef DT_PERFORMANCE
7088 gettimeofday(&update_time_f, NULL);
7089 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7090 update_time_f.tv_usec += 1000000;
7091 update_time_f.tv_sec--;
7093 printf(" done Part 2 DisplaySomeIcons, time: %ld.%ld\n\n",
7094 update_time_f.tv_sec - update_time_s.tv_sec,
7095 update_time_f.tv_usec - update_time_s.tv_usec);
7097 /* the following message send call added by Rafi */
7098 _DtPerfChkpntMsgSend("Done Register drop sites");
7101 DPRINTF2((" ... %d+%d changed (%d managed)\n",
7102 workCount1, workCount2, manageCount));
7105 g_workCount1 += workCount1;
7106 g_workCount2 += workCount2;
7110 return (workCount1 >= workCount2)? workCount1: workCount2;
7114 /************************************************************************
7116 * Display work procedure
7118 ************************************************************************/
7121 CommitWorkProcUpdates(
7122 FileMgrRec *file_mgr_rec,
7123 FileMgrData * file_mgr_data,
7126 XmManagerWidget file_window;
7127 IconLayoutData *layout_data;
7131 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7132 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7134 if (layout_data == NULL)
7138 "CommitWorkProcUpdates: %d+%d updates (m %d, n %d, i %d:%d, reset %d)\n",
7141 layout_data->manage_count,
7143 layout_data->i_do_next_vis,
7144 layout_data->i_do_next_all,
7155 layout_data->i_do_next_vis = 0;
7156 layout_data->i_do_next_all = 0;
7159 /* if work proc no longer active, everything should already be commited */
7160 if (layout_data->work_id == 0)
7163 /* manage new children */
7164 if (layout_data->manage_count > 0)
7166 if (PositioningEnabledInView(file_mgr_data))
7167 OrderChildrenList(file_mgr_data);
7168 XtManageChildren(layout_data->manage, layout_data->manage_count);
7172 * In "as placed" mode, need to register drop sites now.
7173 * (If not "as placed" mode, this was already done in DisplaySomeIcons.)
7175 if (PositioningEnabledInView(file_mgr_data))
7176 RegisterDesktopHotspots(file_mgr_data, file_mgr_rec);
7178 /* commit drop site updates */
7179 XmDropSiteEndUpdate(layout_data->drop_site_w);
7181 /* If not managed yet, manage the file window again */
7182 if (!XtIsManaged((Widget)file_window))
7187 XtManageChild ((Widget)file_window);
7188 XtVaGetValues(file_mgr_rec->vertical_scroll_bar,XmNuserData,&incr,NULL);
7189 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7190 file_mgr_rec->scroll_window)
7193 XtSetArg (args[0], XmNincrement,incr);
7194 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 1);
7196 XmUpdateDisplay ((Widget)file_window);
7199 /* Try to preserve the focus */
7200 if (file_mgr_rec->focus_widget)
7202 /* see if the widget that previously had the focus was just managed */
7204 for (i = 0; i < layout_data->manage_count; i++)
7206 if (layout_data->manage[i] == file_mgr_rec->focus_widget)
7208 w = file_mgr_rec->focus_widget;
7213 /* if focus widget not found, set focus on file_window */
7215 w = (Widget)file_window;
7217 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
7219 file_mgr_rec->focus_widget = NULL;
7222 layout_data->manage_count = 0;
7224 /* start new update */
7225 XmDropSiteStartUpdate(layout_data->drop_site_w);
7231 XtPointer client_data)
7233 FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
7234 DialogData * dialog_data;
7235 FileMgrData * file_mgr_data;
7236 XmManagerWidget file_window;
7237 IconLayoutData *layout_data;
7238 int ex, ey, ewd, eht;
7239 ObjectPosition *bottom;
7242 Boolean commit_updates = False;
7247 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
7248 if (dialog_data == NULL)
7251 file_mgr_data = (FileMgrData *) dialog_data->data;
7252 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7253 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7255 /* get the position and size of the currently visible area */
7256 ex = -file_window->core.x;
7257 ey = -file_window->core.y;
7258 ewd = XtParent(file_window)->core.width;
7259 eht = XtParent(file_window)->core.height;
7261 /* check if the window scrolled */
7262 if (ex != layout_data->ex || ey != layout_data->ey)
7264 layout_data->i_do_next_vis = layout_data->i_do_next_all;
7265 layout_data->visible_done = False;
7268 /* first work on icons in the currently visible area */
7269 if (layout_data->visible_done)
7273 n = DisplaySomeIcons(file_mgr_rec, file_mgr_data, ex, ey, ewd, eht, n1, False);
7276 /* we just finished updating all visible icons */
7277 DPRINTF(("DisplayWorkProc: visible done.\n"));
7278 layout_data->visible_done = True;
7279 commit_updates = True;
7283 /* if we still have some time left, work on other icons */
7284 if (layout_data->visible_done && n < n2)
7286 n = DisplaySomeIcons(file_mgr_rec, file_mgr_data,
7287 0, 0, 32767, 32767, n2 - n, True);
7289 /* check if we are done */
7292 layout_data->all_done = True;
7293 commit_updates = True;
7295 else if (layout_data->manage_count >= 100)
7296 commit_updates = True;
7301 /* manage new children and commit drop site updates */
7302 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, False);
7305 * In "as placed" mode, icons may overlap.
7306 * Force redraw in bottom to top stacking order.
7308 if (PositioningEnabledInView(file_mgr_data))
7310 for (bottom = GetBottomOfStack(file_mgr_data);
7312 bottom = (ObjectPosition *)bottom->prev)
7314 if (bottom->file_view_data != NULL &&
7315 bottom->file_view_data->displayed &&
7316 !bottom->file_view_data->need_update)
7318 child = bottom->file_view_data->widget;
7319 if ((Position)(child->core.x + child->core.width) >= (Position)ex &&
7320 child->core.x < ex + ewd &&
7321 (Position)(child->core.y + child->core.height) >= (Position)ey &&
7322 child->core.y < ey + eht)
7324 RedrawOneGadget(child, NULL, NULL);
7331 if (layout_data->all_done)
7333 /* all work is done; all icons are up-to-date */
7334 file_mgr_data->newSize = False;
7335 layout_data->work_id = 0;
7336 XmDropSiteEndUpdate(layout_data->drop_site_w);
7338 DPRINTF(("DisplayWorkProc: all done.\n"));
7340 /* returning True will end the work proc */
7345 /* remember current scroll position */
7346 layout_data->ex = ex;
7347 layout_data->ey = ey;
7353 /************************************************************************
7356 * Position and size the full set of icons for the file mgr data.
7358 ************************************************************************/
7362 FileMgrRec *file_mgr_rec,
7363 FileMgrData *file_mgr_data,
7364 Boolean update_scrolling_position,
7365 Boolean turn_off_hourglass )
7367 #ifdef DT_PERFORMANCE
7368 struct timeval update_time_s;
7369 struct timeval update_time_f;
7371 XmManagerWidget file_window;
7372 FileViewData ** order_list;
7374 int total_icon_count;
7375 IconLayoutData *layout_data;
7376 Dimension file_window_width, file_window_height;
7377 Dimension scrolled_window_width, scrolled_window_height;
7378 Dimension vert_scrollbar_width, horiz_scrollbar_height;
7379 Dimension grid_width, grid_height;
7380 Dimension icon_width, icon_height;
7381 Dimension extra_height;
7382 Dimension sw_shadow_thickness, sb_highlight_thickness, space;
7384 int level, max_level;
7385 FileViewData *file_view_data;
7386 Boolean overflow = False;
7395 unsigned char operations = 0L;
7396 static XtCallbackRec dropCB[] = { {DropOnFileWindow, NULL}, {NULL, NULL} };
7399 /* if directory-read still in progress, don't do anything now */
7400 if (file_mgr_data->busy_status != not_busy)
7403 DPRINTF(("LayoutFileIcons(\"%s\", u_s_p %c, t_o_h %c) ...\n",
7404 file_mgr_data->current_directory,
7405 update_scrolling_position? 'T': 'F',
7406 turn_off_hourglass? 'T': 'F'));
7408 #ifdef DT_PERFORMANCE
7409 printf(" Begin LayoutFileIcons\n");
7410 gettimeofday(&update_time_s, NULL);
7413 _DtPerfChkpntMsgSend("Begin Layout Icons");
7417 * Just in case a previous update work proc is still active,
7418 * we commit pending updates made by the work proc before we
7419 * start making changes.
7421 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, True);
7423 file_window = (XmManagerWidget) file_mgr_rec->file_window;
7424 layout_data = (IconLayoutData *)file_mgr_data->layout_data;
7426 fileType = GetDirectoryLogicalType(file_mgr_data,
7427 file_mgr_data->current_directory);
7428 operations = TypeToDropOperations(fileType);
7430 if (!file_mgr_data->dropSite)
7432 dropCB[0].closure = (XtPointer)file_mgr_data;
7434 DtDndVaDropRegister((Widget)file_mgr_rec->file_window,
7435 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
7438 DtNdropAnimateCallback, dropCB,
7439 DtNregisterChildren, True,
7440 DtNtextIsBuffer, True,
7441 XmNanimationStyle, XmDRAG_UNDER_SHADOW_IN,
7443 file_mgr_data->dropSite = True;
7447 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
7448 XmDropSiteUpdate((Widget)file_mgr_rec->file_window, args, 1);
7454 XtSetArg (args[0], XmNdropSiteOperations, operations);
7456 XtSetArg (args[0], XmNdropSiteOperations, XmDROP_NOOP);
7457 XmDropSiteUpdate((Widget)file_mgr_rec->file_window, args, 1);
7460 /* Get the count of the total icon to be displayed. */
7461 order_list = layout_data->order_list;
7462 order_count = layout_data->order_count;
7463 total_icon_count = 0;
7464 for (i = 0; i < order_count; i++)
7466 if (order_list[i]->displayed)
7470 /* Get the colors to be used for drawing the icons */
7471 XtSetArg (args[0], XmNbackground, &layout_data->background);
7472 XtSetArg (args[1], XmNforeground, &layout_data->foreground);
7474 XtSetArg (args[2], XmNtopShadowColor, &layout_data->topshadow);
7475 XtGetValues (file_mgr_rec->file_window, args, 3);
7477 XtGetValues (file_mgr_rec->file_window, args, 2);
7479 XtSetArg (args[0], XmNtopShadowColor, &layout_data->pixmap_back);
7480 XtSetArg (args[1], XmNbottomShadowColor, &layout_data->pixmap_fore);
7481 XtGetValues (file_mgr_rec->main, args, 2);
7484 * Create/update icon gadget for ".".
7485 * This gadget may not actually be displayed (depends of filter settings;
7486 * by default it is filtered out), but we need at least one gadget
7487 * created here so we can figure out fonts and margins used by icon
7488 * gadgets. This is necessary to compute the grid spacing.
7490 for (i = 0; i < order_count; i++)
7491 if (strcmp(order_list[i]->file_data->file_name, ".") == 0)
7493 UpdateOneFileIcon(file_mgr_rec, file_mgr_data, order_list[i]);
7494 order_list[i]->need_update = True;
7498 /* Find the icon with the longest label */
7500 file_view_data = NULL;
7501 for (i = 0; i < order_count; i++)
7503 if (!order_list[i]->filtered &&
7504 (len = strlen(order_list[i]->label)) > max_len)
7506 file_view_data = order_list[i];
7511 /* get the size of the icon with the longest label */
7512 GetIconLayoutParms(file_mgr_rec, file_mgr_data, layout_data);
7513 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data, file_view_data,
7514 &grid_width, &grid_height);
7516 /* for tree view add space for tree lines and buttons */
7518 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
7520 for (i = 0; i < order_count; i++)
7522 if (order_list[i]->displayed)
7524 GetLevel(order_list[i], &level);
7525 if (level > max_level)
7529 grid_width += TreeWd(max_level, layout_data->treebtn_size);
7532 file_mgr_data->grid_height = grid_height;
7533 file_mgr_data->grid_width = grid_width;
7536 * If positioning is enabled in this view, then we need to use the other
7537 * layout function, which is capable of handling overlapping icons and
7540 if (PositioningEnabledInView(file_mgr_data))
7542 if (file_mgr_data->object_positions)
7544 LayoutDesktopIcons(file_mgr_rec, file_mgr_data,
7545 order_list, order_count, turn_off_hourglass);
7546 /* RepairFileWindow(file_mgr_data); *OBSOLETE* */
7552 * Position and size the icons according to the show and view types.
7555 scrolled_window_width = file_mgr_rec->scroll_window->core.width;
7556 scrolled_window_height = file_mgr_rec->scroll_window->core.height;
7557 vert_scrollbar_width = file_mgr_rec->vertical_scroll_bar->core.width;
7558 horiz_scrollbar_height = file_mgr_rec->horizontal_scroll_bar->core.height;
7560 if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
7562 /* if not yet done, create tree button icons */
7563 if (TreeBtnWd[0] == 0)
7564 CreateTreeIcons(file_mgr_rec->file_window);
7566 /* layout for tree mode */
7569 file_window_width = MARGIN + grid_width - TreeOffset + XSPACING;
7571 for (k = 0; k < order_count; k++)
7573 if (!order_list[k]->displayed)
7576 /* make sure window height won't exceed limit */
7577 extra_height = GetExtraHeight(file_mgr_data, order_list[k],
7578 layout_data->treebtn_size);
7579 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
7580 if (tmp + MARGIN > MAXWINSIZE)
7582 /* window would exceed height limit; start a new column */
7583 x += grid_width + XSPACING;
7585 file_window_width += grid_width + XSPACING;
7586 tmp = (int)y + grid_height + extra_height + YSPACING(file_mgr_data);
7590 order_list[k]->x = x;
7591 order_list[k]->y = y + grid_height;
7598 file_window_height = MAXWINSIZE;
7600 file_window_height = y + MARGIN;
7602 else if (file_mgr_data->view == BY_ATTRIBUTES)
7604 /* layout for details view, no tree mode */
7607 file_window_width = 2*MARGIN + grid_width;
7609 for (k = 0; k < order_count; k++)
7611 if (!order_list[k]->displayed)
7614 /* make sure window height won't exceed limit */
7615 tmp = (int)y + grid_height + YSPACING(file_mgr_data);
7616 if (tmp + MARGIN > MAXWINSIZE)
7618 /* window would exceed height limit; start a new column */
7619 x += grid_width + XSPACING;
7621 file_window_width += grid_width + XSPACING;
7622 tmp = (int)y + grid_height + YSPACING(file_mgr_data);
7626 order_list[k]->x = x;
7627 order_list[k]->y = y + grid_height;
7634 file_window_height = MAXWINSIZE;
7636 file_window_height = y + MARGIN;
7638 else /* show_type == SINGLE_DIRECTORY, view != BY_ATTRIBUTES */
7640 /* layout for "normal" views (no tree mode, no details) */
7642 /* calculate how many columns fit in the window width */
7643 column_count = ((int)scrolled_window_width - 4 - 2*MARGIN + XSPACING) /
7644 ((int)grid_width + XSPACING);
7645 if (column_count == 0)
7646 column_count = 1; /* need at least one column */
7649 * Calculate the window height. Need to do calculation in int's
7650 * rather than short (Dimension) because of possible overflow.
7652 row_count = (total_icon_count + column_count - 1) / column_count;
7653 tmp = 2*MARGIN - YSPACING(file_mgr_data) +
7654 row_count * ((int)grid_height + YSPACING(file_mgr_data));
7656 /* check if the height is larger than the scrolled window */
7657 if (tmp >= (int)scrolled_window_height - 2*MARGIN)
7659 /* need to recompute everything because of space for vert scrollbar */
7660 column_count = ((int)scrolled_window_width - 4 - 2*MARGIN + XSPACING
7661 - (int)vert_scrollbar_width)
7662 / ((int)grid_width + XSPACING);
7663 if (column_count == 0)
7665 row_count = (total_icon_count + column_count - 1) / column_count;
7666 tmp = 2*MARGIN - YSPACING(file_mgr_data) +
7667 row_count * ((int)grid_height + YSPACING(file_mgr_data));
7670 /* check if the window height is within the limit */
7671 if (tmp <= MAXWINSIZE)
7672 file_window_height = (Dimension)tmp;
7675 /* window height too large; use more columns */
7677 row_count = (int)(MAXWINSIZE - 2*MARGIN + YSPACING(file_mgr_data)) /
7678 (int)((int)grid_height + YSPACING(file_mgr_data));
7679 column_count = (total_icon_count + row_count - 1) / row_count;
7680 row_count = (total_icon_count + column_count - 1) / column_count;
7681 file_window_height = (Dimension) (2*MARGIN - YSPACING(file_mgr_data) +
7682 row_count * ((int)grid_height + YSPACING(file_mgr_data)));
7685 DPRINTF((" %d columns, %d rows (scroll_window width %d)\n",
7686 column_count, row_count,
7687 scrolled_window_width));
7689 /* assign positions to all icons */
7691 file_window_width = (Dimension)
7692 (2*MARGIN - XSPACING + column_count*((int)grid_width + XSPACING));
7695 for (i = 0; i < row_count; i++)
7699 for (j = 0; j < column_count && k < order_count;)
7701 /* find the next icon to display */
7702 while (k < order_count && !order_list[k]->displayed)
7704 if (k == order_count)
7707 if (layout_data->alignment == XmALIGNMENT_CENTER &&
7708 file_mgr_data->view == BY_NAME_AND_ICON)
7710 EstimateIconSize(file_mgr_rec, file_mgr_data, layout_data,
7711 order_list[k], &icon_width, &icon_height);
7712 order_list[k]->x = x +
7713 (Dimension)(grid_width - icon_width)/(Dimension)2;
7716 order_list[k]->x = x;
7717 order_list[k]->y = y + grid_height;
7719 x += grid_width + XSPACING;
7724 y += grid_height + YSPACING(file_mgr_data);
7728 DPRINTF((" file_window size: width %d, height %d\n",
7729 file_window_width, file_window_height));
7731 /* Manage/unmanage the scrollbars as needed. */
7733 XtSetArg (args[0], XmNwidth, file_window_width);
7734 XtSetArg (args[1], XmNheight, file_window_height);
7735 XtSetValues ((Widget)file_window, args, 2);
7737 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
7738 XtSetValues (file_mgr_rec->scroll_window, args, 1);
7741 /* Unmanage the horizontal scrollbar if it is not needed */
7742 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7743 file_mgr_rec->scroll_window))
7745 if (file_window_width >= (Dimension)(scrolled_window_width - 4 -
7746 vert_scrollbar_width))
7747 XtManageChild (file_mgr_rec->horizontal_scroll_bar);
7750 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
7751 XtSetArg (args[0], XmNx, 0);
7752 XtSetValues ((Widget)file_window, args, 1);
7755 else if (file_window_width >= (Dimension)(scrolled_window_width - 4))
7756 XtManageChild (file_mgr_rec->horizontal_scroll_bar);
7759 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
7760 XtSetArg (args[0], XmNx, 0);
7761 XtSetValues ((Widget)file_window, args, 1);
7764 XSync (XtDisplay (file_window), False);
7766 /* Set the file window width and height to be at least */
7767 /* the size of the scrolled window. */
7769 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
7770 file_mgr_rec->scroll_window))
7772 if(file_window_width <= (Dimension)(scrolled_window_width -
7773 (vert_scrollbar_width + 4)))
7775 file_window_width = scrolled_window_width -
7776 (vert_scrollbar_width + 4);
7780 if(file_window_width < (Dimension)(scrolled_window_width - 4))
7781 file_window_width = scrolled_window_width - 4;
7784 if (HorizontalScrollbarIsVisible(file_mgr_rec->horizontal_scroll_bar,
7785 file_mgr_rec->scroll_window))
7789 XtSetArg (args[0], XmNhighlightThickness, &sb_highlight_thickness);
7790 XtGetValues ((Widget)file_mgr_rec->horizontal_scroll_bar, args, 1);
7792 XtSetArg (args[0], XmNshadowThickness, &sw_shadow_thickness);
7793 XtSetArg (args[1], XmNspacing, &space);
7794 XtGetValues ((Widget)file_mgr_rec->scroll_window, args, 2);
7796 pad = (int)(((sb_highlight_thickness + sw_shadow_thickness) * 2) + space);
7798 if(file_window_height < (Dimension)(scrolled_window_height -
7799 (horiz_scrollbar_height + pad)))
7800 file_window_height = scrolled_window_height -
7801 (horiz_scrollbar_height + pad);
7805 if (file_window_height < (Dimension)(scrolled_window_height - 4))
7806 file_window_height = scrolled_window_height - 4;
7810 XtSetArg (args[0], XmNwidth, file_window_width);
7811 XtSetArg (args[1], XmNheight, file_window_height);
7812 XtSetValues ((Widget)file_window, args, 2);
7814 if( file_mgr_data->scrollToThisFile == NULL )
7816 if (update_scrolling_position)
7818 XtSetArg (args[0], XmNx, 0);
7819 XtSetArg (args[1], XmNy, 0);
7820 XtSetValues ((Widget)file_window, args, 2);
7823 /* Set the vertical scrollbar's increment to icon height */
7824 XtSetArg (args[0], XmNincrement, grid_height + YSPACING(file_mgr_data));
7825 XtSetArg (args[1], XmNuserData, grid_height + YSPACING(file_mgr_data));
7826 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 2);
7829 if (PositioningEnabledInView(file_mgr_data))
7831 BuildObjectPositions(file_mgr_data);
7832 /* RepairFileWindow(file_mgr_data); *OBSOLETE* */
7836 * Don't keep up the hourglass; this helps the user to get the impression
7837 * that all of the work is done.
7839 if (turn_off_hourglass && !overflow)
7840 _DtTurnOffHourGlass(file_mgr_rec->shell);
7847 * Start up a work proc that will update the display.
7849 layout_data->visible_done = False;
7850 layout_data->all_done = False;
7851 if (layout_data->work_id == 0)
7853 XtAppContext app_context =
7854 XtWidgetToApplicationContext(file_mgr_rec->shell);
7856 DPRINTF(("LayoutFileIcons: starting workproc\n"));
7857 layout_data->drop_site_w = (Widget)file_mgr_rec->shell;
7858 XmDropSiteStartUpdate(layout_data->drop_site_w);
7860 layout_data->work_id =
7861 XtAppAddWorkProc(app_context, DisplayWorkProc, file_mgr_rec);
7865 if( file_mgr_data->scrollToThisFile )
7868 DirectorySet * directory_set = NULL;
7870 file_view_data = NULL;
7872 for( i = 0; i < file_mgr_data->directory_count; ++i)
7874 if( strcmp( ((DirectorySet *)file_mgr_data->directory_set[i])->name, file_mgr_data->scrollToThisDirectory ) == 0 )
7876 directory_set = (DirectorySet *)file_mgr_data->directory_set[i];
7883 for( i = 0; i < directory_set->file_count; ++i )
7885 if( strcmp( directory_set->order_list[i]->file_data->file_name,
7886 file_mgr_data->scrollToThisFile ) == 0 )
7888 file_view_data = directory_set->order_list[i];
7895 && file_view_data->filtered == False )
7897 FileMgrRec * file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
7899 DeselectAllFiles( file_mgr_data );
7900 SelectFile( file_mgr_data, file_view_data );
7901 ActivateSingleSelect( file_mgr_rec,
7902 file_mgr_data->selection_list[0]->file_data->logical_type );
7904 PositionFileView(file_view_data, file_mgr_data);
7908 if (update_scrolling_position)
7910 XtSetArg (args[0], XmNx, 0);
7911 XtSetArg (args[1], XmNy, 0);
7912 XtSetValues ((Widget)file_window, args, 2);
7915 /* Set the vertical scrollbar's increment to icon height */
7916 XtSetArg (args[0], XmNincrement, grid_height + YSPACING(file_mgr_data));
7917 XtSetArg (args[1], XmNuserData, grid_height + YSPACING(file_mgr_data));
7918 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 2);
7921 XtFree( file_mgr_data->scrollToThisFile );
7922 file_mgr_data->scrollToThisFile = NULL;
7923 XtFree( file_mgr_data->scrollToThisDirectory );
7924 file_mgr_data->scrollToThisDirectory = NULL;
7927 #ifdef DT_PERFORMANCE
7928 gettimeofday(&update_time_f, NULL);
7929 if (update_time_s.tv_usec > update_time_f.tv_usec) {
7930 update_time_f.tv_usec += 1000000;
7931 update_time_f.tv_sec--;
7933 printf(" done LayoutFileIcons, time: %ld.%ld\n\n",
7934 update_time_f.tv_sec - update_time_s.tv_sec,
7935 update_time_f.tv_usec - update_time_s.tv_usec);
7937 /* the following message send call added by Rafi */
7938 _DtPerfChkpntMsgSend("Done LayoutFileIcons");
7941 DPRINTF(("... done\n"));
7946 /************************************************************************
7949 * Callback function invoked upon clicking the tree-branch-expand button.
7951 ************************************************************************/
7956 XtPointer clientData,
7957 XmAnyCallbackStruct *callData )
7959 FileMgrRec *file_mgr_rec;
7960 FileMgrData *file_mgr_data;
7961 FileViewData *file_view_data = (FileViewData *)clientData;
7965 /* check which mouse button was pressed */
7966 if ((callData->event->type == ButtonPress ||
7967 callData->event->type == ButtonRelease) &&
7968 ((XButtonEvent *)callData->event)->button != Button1)
7974 /* get file mgr data and record */
7975 XtSetArg (args[0], XmNuserData, &file_mgr_data);
7976 XtGetValues (w, args, 1);
7977 file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
7979 XmDropSiteStartUpdate(file_mgr_rec->file_window);
7980 CommitWorkProcUpdates(file_mgr_rec, file_mgr_data, True);
7981 DirTreeExpand(file_mgr_data, file_view_data, expand);
7982 DrawCurrentDirectory (file_mgr_rec->current_directory,
7983 file_mgr_rec, file_mgr_data);
7984 LayoutFileIcons(file_mgr_rec, file_mgr_data, False, True);
7985 XmDropSiteEndUpdate(file_mgr_rec->file_window);
7986 RedrawTreeLines(file_mgr_rec->file_window,
7987 -file_mgr_rec->file_window->core.x,
7988 -file_mgr_rec->file_window->core.y,
7989 XtParent(file_mgr_rec->file_window)->core.width,
7990 XtParent(file_mgr_rec->file_window)->core.height,
7991 0, file_mgr_rec, file_mgr_data);
7996 * When a drop occurs on a File Manger window, which now
7997 * support random placement, what is dropped may not ultimately be what
7998 * is displayed. Since the dissolve transition effect has been disabled
7999 * for drops on the desktop, we can sometimes end up with garbage left on
8000 * the desktop. This function will attempt to clear up the leftover garbage,
8001 * by resetting all areas of the desktop which are not covered by an icon
8002 * to the background color for the file window.
8004 * This function is OBSOLETE (?).
8009 FileMgrData * file_mgr_data)
8012 FileMgrRec * file_mgr_rec;
8015 Region redrawRegion;
8020 XmManagerWidget file_window;
8025 file_mgr_rec = (FileMgrRec *) file_mgr_data->file_mgr_rec;
8026 file_window = (XmManagerWidget)file_mgr_rec->file_window;
8028 /* Initialize the clip region to that of the file window */
8031 rect.height = file_window->core.height;
8032 rect.width = file_window->core.width;
8033 clipList = XCreateRegion();
8034 XUnionRectWithRegion(&rect, clipList, clipList);
8036 /* Subtract out the hotspots associated with each icon */
8037 num_children = file_window->composite.num_children;
8038 children = file_window->composite.children;
8039 hotspot = XCreateRegion();
8041 for (i = 0; i < num_children; i++)
8043 if (XtIsManaged(children[i]) &&
8044 XtIsSubclass(children[i], dtIconGadgetClass))
8046 WidgetRectToRegion(file_mgr_data, children[i], hotspot);
8047 XSubtractRegion(clipList, hotspot, clipList);
8051 /* Create a GC for doing our drawing */
8052 mask = GCForeground;
8053 values.foreground = file_window->core.background_pixel;
8054 gc = XCreateGC(XtDisplay(file_window), XtWindow(file_window), mask, &values);
8055 XSetRegion(XtDisplay(file_window), gc, clipList);
8057 /* Restore the window */
8058 XFillRectangle(XtDisplay(file_window), XtWindow(file_window), gc, 0, 0,
8059 file_window->core.width, file_window->core.height);
8062 * Force all icons to redraw, since we are only able to repair the
8063 * areas where icons are not; the drop image may have extended onto
8064 * some of the icons.
8068 rect.height = file_window->core.height;
8069 rect.width = file_window->core.width;
8070 redrawRegion = XCreateRegion();
8071 XUnionRectWithRegion(&rect, redrawRegion, redrawRegion);
8072 (*file_window->core.widget_class->core_class.expose)
8073 ((Widget)file_window, NULL, redrawRegion);
8076 XFreeGC(XtDisplay(file_window), gc);
8077 XDestroyRegion(clipList);
8078 XDestroyRegion(hotspot);
8079 XDestroyRegion(redrawRegion);
8086 * Compress the stacking order values, anytime an item is removed.
8090 CompressObjectList (
8091 ObjectPosition ** object_positions,
8097 for (i = 0; i < num_objects; i++)
8099 if (object_positions[i]->stacking_order > starting_index)
8100 object_positions[i]->stacking_order--;
8106 /************************************************************************
8108 * LayoutDesktopIcons
8109 * Position and size the full set of icons for the file mgr data.
8111 ************************************************************************/
8114 LayoutDesktopIcons (
8115 FileMgrRec * file_mgr_rec,
8116 FileMgrData * file_mgr_data,
8117 FileViewData ** order_list,
8119 Boolean turn_off_hourglass )
8122 XmManagerWidget file_window;
8123 int directory_count, largest_x, largest_y;
8124 int value, size, increment, page;
8125 Dimension current_wd;
8126 Dimension current_ht;
8127 Dimension file_window_width;
8128 Dimension grid_height;
8129 Dimension grid_width;
8130 FileViewData * object;
8131 ObjectPosition * position_data;
8132 ObjectPosition * bottom;
8135 Boolean set_size = False;
8141 /* Get the grid block size */
8142 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8143 grid_height = file_mgr_data->grid_height;
8144 grid_width = file_mgr_data->grid_width;
8146 file_window_width = file_mgr_rec->scroll_window->core.width - 4;
8147 current_ht = file_mgr_rec->file_window->core.height;
8148 current_wd = file_mgr_rec->file_window->core.width;
8151 /* Before positioning, mark all position entries as 'not used' */
8152 for (i = 0; i < file_mgr_data->num_objects; i++)
8154 file_mgr_data->object_positions[i]->in_use = False;
8155 file_mgr_data->object_positions[i]->file_view_data = NULL;
8159 * Before attempting to place new icons, we need to make sure that
8160 * all of the existing object_positions entries have had their
8161 * file_view_data field filled in. This is so that during placement,
8162 * we can get the height and width of the associated icons, to help
8165 for (i = 0; i < order_count; i++)
8167 object = order_list[i];
8168 if (object->displayed)
8170 if (position_data = GetPositionalData(file_mgr_data, object, 0, False))
8172 /* Save; used later during redraw */
8173 position_data->file_view_data = object;
8174 object->position_info = (ObjectPtr)position_data;
8177 else if (position_data = GetPositionalData(file_mgr_data, object, 0,
8181 * If an object has position information, but is currently
8182 * filtered, don't discard its position info; mark it as in-use.
8184 position_data->file_view_data = object;
8185 object->position_info = (ObjectPtr)position_data;
8189 /* Remove any unused position data entries */
8190 for (i = 0; i < file_mgr_data->num_objects; )
8192 if (!file_mgr_data->object_positions[i]->in_use)
8194 /* If this object had a text field, delete it */
8195 for (k = 0; k < file_window->composite.num_children; k++)
8197 if (XmIsTextField(file_window->composite.children[k]) &&
8198 !file_window->composite.children[k]->core.being_destroyed)
8200 XtSetArg(args[0], XmNuserData, &edit_name);
8201 XtGetValues(file_window->composite.children[k], args, 1);
8202 if (strcmp(edit_name,file_mgr_data->object_positions[i]->name)
8206 XtUnmanageChild(file_window->composite.children[k]);
8207 XtDestroyWidget(file_window->composite.children[k]);
8213 /* Free up the entry; bump up the other array entries */
8214 /* Update the linked list */
8215 if (file_mgr_data->object_positions[i]->prev)
8217 file_mgr_data->object_positions[i]->prev->next = (ObjectPtr)
8218 file_mgr_data->object_positions[i]->next;
8220 if (file_mgr_data->object_positions[i]->next)
8222 file_mgr_data->object_positions[i]->next->prev = (ObjectPtr)
8223 file_mgr_data->object_positions[i]->prev;
8225 sorder = file_mgr_data->object_positions[i]->stacking_order;
8226 XtFree(file_mgr_data->object_positions[i]->name);
8227 file_mgr_data->object_positions[i]->name = NULL;
8228 XtFree((char *)file_mgr_data->object_positions[i]);
8229 file_mgr_data->object_positions[i] = NULL;
8230 for (j = i; j < file_mgr_data->num_objects - 1; j++)
8232 file_mgr_data->object_positions[j] =
8233 file_mgr_data->object_positions[j+1];
8235 file_mgr_data->num_objects--;
8236 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8237 (char *)file_mgr_data->object_positions,
8238 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8239 CompressObjectList(file_mgr_data->object_positions,
8240 file_mgr_data->num_objects, sorder);
8246 /* Now, it is safe to position any unplaced objects */
8247 for (i = 0; i < order_count; i++)
8249 object = order_list[i];
8250 if (object->displayed)
8252 position_data = GetPositionalData(file_mgr_data, object,
8253 file_window_width, True);
8255 /* Save; used later during redraw */
8256 position_data->file_view_data = object;
8257 object->position_info = (ObjectPtr)position_data;
8259 /* record position of bottom left corner for DisplaySomeIcons */
8260 object->x = position_data->x;
8261 object->y = position_data->y +
8262 (object->need_update? grid_height: object->widget->core.height);
8266 /* Get largest x value */
8269 bottom = GetBottomOfStack(file_mgr_data);
8272 if (bottom->file_view_data != NULL && bottom->file_view_data->displayed)
8274 if (bottom->file_view_data->position_info->x > largest_x)
8275 largest_x = bottom->file_view_data->position_info->x;
8276 if (bottom->file_view_data->position_info->y > largest_y)
8277 largest_y = bottom->file_view_data->position_info->y;
8279 bottom = (ObjectPosition *)bottom->prev;
8281 largest_x += grid_width;
8282 largest_y += grid_height;
8284 /* if necessary, shrink the width & height to what we need */
8285 if (current_wd == 32767)
8287 current_wd = largest_x;
8291 if (current_ht == 32767)
8293 current_ht = largest_y;
8297 /* Get the horizontal and vertical scrollbars. */
8298 XtSetArg (args[0], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
8299 XtSetValues (file_mgr_rec->scroll_window, args, 1);
8302 * Typically, dtfile does everything possible to prevent a horizontal
8303 * scrollbar from being displayed. However, when random placement is
8304 * enabled, we don't mind having a horizontal scrollbar, when needed.
8305 * We need to manually manage this, since the normal dtfile layout
8306 * code may have forcably unmanaged the scrollbar earlier.
8308 if (XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8310 /* get scroll bar values */
8311 (void)XmScrollBarGetValues(file_mgr_rec->horizontal_scroll_bar,
8312 &value, &size, &increment, &page);
8315 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
8316 file_mgr_rec->scroll_window))
8318 if ((Dimension)largest_x >= (Dimension)(file_mgr_rec->scroll_window->core.width -
8319 (file_mgr_rec->vertical_scroll_bar->core.width + 4)))
8321 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8325 /* set scroll bar values changing its position */
8326 if(value != 0 && XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8327 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8330 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
8331 XtSetArg (args[0], XmNx, 0);
8332 XtSetValues ((Widget)file_window, args, 1);
8336 else if ((Dimension)largest_x >= (Dimension)(file_mgr_rec->scroll_window->core.width - 4))
8337 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8340 /* set scroll bar values changing its position */
8341 if(value != 0 && XtIsManaged(file_mgr_rec->horizontal_scroll_bar))
8342 XtManageChild(file_mgr_rec->horizontal_scroll_bar);
8345 XtUnmanageChild (file_mgr_rec->horizontal_scroll_bar);
8346 XtSetArg (args[0], XmNx, 0);
8347 XtSetValues ((Widget)file_window, args, 1);
8351 /* Set the file window width and height to be at least */
8352 /* the size of the scrolled window. */
8353 if ((Dimension)(current_wd) < (Dimension)(file_mgr_rec->scroll_window->core.width - 4))
8355 if (VerticalScrollbarIsVisible(file_mgr_rec->vertical_scroll_bar,
8356 file_mgr_rec->scroll_window))
8357 current_wd = file_mgr_rec->scroll_window->core.width -
8358 (file_mgr_rec->vertical_scroll_bar->core.width + 4);
8360 current_wd = file_mgr_rec->scroll_window->core.width - 4;
8364 if ((Dimension)(current_ht) < (Dimension)(file_mgr_rec->scroll_window->core.height - 4))
8366 current_ht = file_mgr_rec->scroll_window->core.height - 4;
8372 XtSetArg (args[0], XmNwidth, current_wd);
8373 XtSetArg (args[1], XmNheight, current_ht);
8374 XtSetValues (file_mgr_rec->file_window, args, 2);
8377 /* Set the vertical scrollbar's increment to icon height */
8378 XtSetArg (args[0], XmNincrement, file_mgr_data->grid_height + 2);
8379 XtSetValues (file_mgr_rec->vertical_scroll_bar, args, 1);
8382 * Don't keep up the hourglass; this helps the user to get the impression
8383 * that all of the work is done.
8385 if (turn_off_hourglass)
8386 _DtTurnOffHourGlass(file_mgr_rec->shell);
8390 /***************************************************
8392 * Given a desktop object, see if it has already been assigned a position;
8393 * if not, then try to fit it into the next available grid position.
8395 **************************************************/
8409 int srcABot, srcBBot;
8410 int srcARight, srcBRight;
8414 srcABot = y1 + h1 - 1;
8415 srcBBot = y2 + h2 - 1;
8416 srcARight = x1 + w1 - 1;
8417 srcBRight = x2 + w2 - 1;
8429 if (srcARight >= srcBRight)
8430 dw = srcBRight - dx + 1;
8432 dw = srcARight - dx + 1;
8434 if (srcABot > srcBBot)
8435 dh = srcBBot - dy + 1;
8437 dh = srcABot - dy + 1;
8439 if (dw <= 0 || dh <= 0)
8445 static ObjectPosition *
8447 FileMgrData * file_mgr_data,
8448 FileViewData * object,
8449 Dimension max_width,
8454 ObjectPosition *entry, *top;
8457 Dimension grid_height;
8458 Dimension grid_width;
8460 ObjectPosition * oP;
8461 Dimension objWidth, objHeight;
8462 Dimension oWidth, oHeight;
8464 /* If object already has positional data, then use it */
8465 for (i = 0; i < file_mgr_data->num_objects; i++)
8467 if (strcmp(object->file_data->file_name,
8468 file_mgr_data->object_positions[i]->name) == 0)
8471 file_mgr_data->object_positions[i]->in_use = True;
8472 return(file_mgr_data->object_positions[i]);
8479 /* Create a new entry, and place into the grid on the top of the stack */
8480 entry = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8481 entry->name = XtNewString(object->file_data->file_name);
8482 entry->in_use = True;
8483 entry->late_bind = False;
8484 entry->stacking_order = 2;
8487 entry->file_view_data = NULL;
8489 if(file_mgr_data->num_objects == 1)
8491 top = file_mgr_data->object_positions[0];
8492 top->next = (ObjectPtr)entry;
8493 entry->prev = (ObjectPtr)top;
8498 /* Push all other objects down in the stack */
8499 for (i = 0; i < file_mgr_data->num_objects; i++)
8501 /* Find the previous top of the stack */
8502 if (file_mgr_data->object_positions[i]->stacking_order == 1)
8504 top = file_mgr_data->object_positions[i];
8507 else if (file_mgr_data->object_positions[i]->stacking_order == 2)
8510 top = GetTopOfStack(file_mgr_data);
8511 top->next = (ObjectPtr)entry;
8512 entry->next = (ObjectPtr)file_mgr_data->object_positions[i];
8513 entry->prev = (ObjectPtr)top;
8514 file_mgr_data->object_positions[i]->prev = (ObjectPtr)entry;
8516 file_mgr_data->object_positions[i]->stacking_order++;
8520 grid_height = file_mgr_data->grid_height;
8521 grid_width = file_mgr_data->grid_width;
8525 if (object->widget && !object->need_update)
8527 objWidth = object->widget->core.width;
8528 objHeight = object->widget->core.height;
8532 objWidth = grid_width;
8533 objHeight = grid_height;
8536 /* Find the first open spot, which will not cause any overlap */
8541 for (i = 0; i < file_mgr_data->num_objects; i++)
8543 oP = file_mgr_data->object_positions[i];
8544 if (oP->file_view_data->widget && !oP->file_view_data->need_update)
8546 oWidth = oP->file_view_data->widget->core.width;
8547 oHeight = oP->file_view_data->widget->core.height;
8551 oWidth = grid_width;
8552 oHeight = grid_height;
8554 if (oP->file_view_data->displayed &&
8555 IntersectRects(x, y, objWidth, objHeight,
8556 oP->x, oP->y, oWidth, oHeight))
8558 /* Try next grid spot */
8559 x += grid_width + XSPACING;
8561 if ((Dimension)(x + objWidth) >= max_width)
8563 /* Go to next row */
8564 y += grid_height + YSPACING(file_mgr_data);
8573 /* Add to the end of the list */
8576 file_mgr_data->num_objects++;
8577 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8578 (char *)file_mgr_data->object_positions,
8579 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8581 /* Force the ordered list to be maintained */
8582 for (i = 0; i < file_mgr_data->num_objects - 1; i++)
8584 if ((entry->y < file_mgr_data->object_positions[i]->y) ||
8585 ((entry->y == file_mgr_data->object_positions[i]->y) &&
8586 (entry->x < file_mgr_data->object_positions[i]->x)))
8588 /* Fits here; slide later entries down */
8589 for (k = file_mgr_data->num_objects - 1; k > i; k--)
8591 file_mgr_data->object_positions[k] =
8592 file_mgr_data->object_positions[k-1];
8599 file_mgr_data->object_positions[i] = entry;
8600 return(file_mgr_data->object_positions[i]);
8604 /*******************************************************************
8606 * BuildObjectPositons - builds up the object positions for directories
8607 * which have now object position information.
8609 *********************************************************************/
8611 BuildObjectPositions(
8612 FileMgrData *file_mgr_data)
8615 FileViewData * file_view_data;
8616 ObjectPosition * ptr;
8618 file_mgr_data->object_positions = (ObjectPosition **)XtMalloc(
8619 sizeof(ObjectPosition *) *
8620 file_mgr_data->directory_set[0]->file_count);
8622 for (i = 0, j = 0; i < file_mgr_data->directory_set[0]->file_count; i++)
8624 file_view_data = file_mgr_data->directory_set[0]->order_list[i];
8626 if (file_view_data->filtered)
8629 ptr = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8630 ptr->name = XtNewString(file_view_data->file_data->file_name);
8631 ptr->x = file_view_data->x;
8632 ptr->y = file_view_data->y -
8633 (file_view_data->need_update? file_mgr_data->grid_height:
8634 file_view_data->widget->core.height);
8636 ptr->late_bind = False;
8637 ptr->stacking_order = j+1;
8638 ptr->file_view_data = file_view_data;
8639 file_view_data->position_info = (ObjectPtr)ptr;
8643 /* Sort according to left-to-right, top-to-bottom */
8644 for (k = 0; k < j; k++)
8646 if ((ptr->y < file_mgr_data->object_positions[k]->y) ||
8647 ((ptr->y == file_mgr_data->object_positions[k]->y) &&
8648 (ptr->x < file_mgr_data->object_positions[k]->x)))
8650 /* Shift others down, to open up a spot */
8651 for (l = j; l > k; l--)
8653 file_mgr_data->object_positions[l] =
8654 file_mgr_data->object_positions[l - 1];
8659 file_mgr_data->object_positions[k] = ptr;
8663 file_mgr_data->num_objects = j;
8665 /* Repair all of the next and prev pointers */
8666 RepairStackingPointers(file_mgr_data);
8667 OrderChildrenList(file_mgr_data);
8671 /***********************************
8673 * When items are dragged around on a random placement window, they will be
8674 * repositioned at the point where they were dropped. Multiple drop items
8675 * will be positioned 'around' where the drop occurred.
8677 **********************************/
8681 FileMgrData * file_mgr_data,
8686 Boolean late_binding_needed)
8695 ObjectPosition * save_object;
8697 FileMgrRec * file_mgr_rec;
8698 XmManagerWidget file_window;
8703 int newEntryCount = 0;
8704 char dot_dir[3] = ".";
8705 char dotdot_dir[3] = "..";
8707 /* if random placement is not enabled, positioning doesn't matter */
8708 if(file_mgr_data->positionEnabled == RANDOM_OFF)
8711 file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
8714 * For directory views, no positional data may be present if positioning
8715 * was disabled for this view. So ... we must create some now.
8717 if ((file_mgr_data->num_objects == 0) &&
8718 (file_mgr_data->directory_set[0]->file_count > 0))
8720 BuildObjectPositions(file_mgr_data);
8724 * Update to the new position.
8725 * The position needs to be adjusted so that the icon actually ends
8726 * up where the user dropped it. This is because the drag icon includes
8727 * margins and shadow area, but not the highlight area of the icon gadget
8728 * that was dragged. Coordinates drop_x, drop_y are the upper left corner
8729 * of the drag icon when it was dropped. To convert to icon gadget
8730 * coordinates we need to subtract the highlight thickness.
8732 if (file_mgr_data->layout_data != NULL)
8733 adj = ((IconLayoutData *)file_mgr_data->layout_data)->highlight;
8738 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8740 /* Process each of the dropped files */
8741 /* Go from bottom to top, to retain stacking order */
8742 for (i = file_count - 1; i >= 0; i--)
8747 * The names typically come in as complete paths; we only want
8748 * the filename portion.
8749 * fdt: this check will break for root (/)
8751 if( strcmp(file_mgr_data->current_directory, file_list[i]) == 0)
8753 else if(strncmp(file_mgr_data->current_directory, file_list[i], strlen(file_list[i]) ) == 0 )
8757 if ((name = strrchr(file_list[i], '/')) == NULL)
8758 name = file_list[i];
8763 /* Try to gracefully handle root (/) */
8771 /* Find the positional data for this object, if any */
8772 for (j = 0; j < file_mgr_data->num_objects; j++)
8774 if (strcmp(name, file_mgr_data->object_positions[j]->name) == 0)
8776 /* Find the associated widget */
8777 for (k = 0; strcmp(name,
8778 file_mgr_data->directory_set[0]->file_view_data[k]->file_data-> file_name); k++);
8782 /* If this object has a text field, then move it also */
8783 for (l = 0; l < file_window->composite.num_children; l++)
8785 if (XmIsTextField(file_window->composite.children[l]) &&
8786 !file_window->composite.children[l]->core.being_destroyed)
8788 XtSetArg(args[0], XmNuserData, &edit_name);
8789 XtGetValues(file_window->composite.children[l], args, 1);
8790 if (strcmp(edit_name, name) == 0)
8792 textWidget = file_window->composite.children[l];
8803 ObjectPosition * data;
8805 /* Create positional data at the top of the ordered array */
8808 data = (ObjectPosition *) XtMalloc(sizeof(ObjectPosition));
8809 data->name = XtNewString(name);
8812 data->in_use = True;
8813 data->late_bind = True;
8814 data->stacking_order = 1;
8815 data->file_view_data = NULL;
8819 /* Push all other objects down in the stack */
8820 for (i2 = 0; i2 < file_mgr_data->num_objects; i2++)
8822 /* Find the previous top of the stack */
8823 if (file_mgr_data->object_positions[i2]->stacking_order == 1)
8825 data->next = (ObjectPtr)file_mgr_data->object_positions[i2];
8826 file_mgr_data->object_positions[i2]->prev = (ObjectPtr)data;
8828 file_mgr_data->object_positions[i2]->stacking_order++;
8831 file_mgr_data->num_objects++;
8832 file_mgr_data->object_positions = (ObjectPosition **) XtRealloc(
8833 (char *)file_mgr_data->object_positions,
8834 sizeof(ObjectPosition *) * file_mgr_data->num_objects);
8836 /* Add entry to the top of the ordered array */
8837 for (j = file_mgr_data->num_objects - 1; j > 0; j--)
8839 file_mgr_data->object_positions[j] =
8840 file_mgr_data->object_positions[j - 1];
8843 file_mgr_data->object_positions[0] = data;
8847 /* Move item upto top of the stack */
8848 RepositionUpInStack(file_mgr_data,
8849 file_mgr_data->object_positions[j]->stacking_order, 1);
8852 orig_x = file_mgr_data->object_positions[j]->x;
8853 orig_y = file_mgr_data->object_positions[j]->y;
8854 file_mgr_data->object_positions[j]->x = x;
8855 file_mgr_data->object_positions[j]->y = y;
8856 save_object = file_mgr_data->object_positions[j];
8858 /* Move the object */
8861 /* We need to force a geometry request */
8862 XtSetArg(args[0], XmNx, x);
8863 XtSetArg(args[1], XmNy, y);
8864 XtSetValues(file_mgr_data->directory_set[0]->file_view_data[k]->widget,
8867 /* Move associated text widget, if there is one */
8872 t_x = textWidget->core.x + x - orig_x;
8873 t_y = textWidget->core.y + y - orig_y;
8875 /* We need to force a geometry request */
8876 XtSetArg(args[0], XmNx, t_x);
8877 XtSetArg(args[1], XmNy, t_y);
8878 XtSetValues(textWidget, args, 2);
8883 * Reorder the positional array, so that it remains ordered.
8884 * Bubble down toward the end of the list if the object has moved
8885 * farther from the origin; bubble up if it has moved closer to
8888 if ((y > orig_y) || ((y == orig_y) && (x > orig_x)))
8891 for (k = j + 1; k < file_mgr_data->num_objects; k++)
8893 if ((y < file_mgr_data->object_positions[k]->y) ||
8894 ((y == file_mgr_data->object_positions[k]->y) &&
8895 (x < file_mgr_data->object_positions[k]->x)))
8897 /* We fit right here */
8898 file_mgr_data->object_positions[k - 1] = save_object;
8904 file_mgr_data->object_positions[k - 1] =
8905 file_mgr_data->object_positions[k];
8909 /* See if it goes at the end */
8910 if (k == file_mgr_data->num_objects)
8911 file_mgr_data->object_positions[k - 1] = save_object;
8916 for (k = j - 1; k >= 0; k--)
8918 if ((y > file_mgr_data->object_positions[k]->y) ||
8919 ((y == file_mgr_data->object_positions[k]->y) &&
8920 (x > file_mgr_data->object_positions[k]->x)))
8922 /* We fit right here */
8923 file_mgr_data->object_positions[k + 1] = save_object;
8929 file_mgr_data->object_positions[k + 1] =
8930 file_mgr_data->object_positions[k];
8934 /* See if it goes at the end */
8936 file_mgr_data->object_positions[0] = save_object;
8939 /* Create position for the next file to be processed */
8944 * Reregister the desktop hotspots.
8945 * Even if the caller told us that late binding was needed, if no new
8946 * objects were specified, then we need to register hotspots now, because
8947 * the layout function will never be called because the directory never
8948 * really changed. This situation can occur when an icon is dropped on
8949 * the desktop from a regular dtfile view, but that icon is already on
8950 * the desktop (it thus is just a reposition).
8952 if (!late_binding_needed ||
8953 (late_binding_needed && (newEntryCount == 0)))
8955 RegisterDesktopHotspots(file_mgr_data, file_mgr_rec);
8960 RegisterDesktopHotspots (
8961 FileMgrData * file_mgr_data,
8962 FileMgrRec * file_mgr_rec)
8964 XmManagerWidget file_window;
8965 FileViewData * file_view_data;
8966 int ex, ey, ewd, eht;
8971 file_window = (XmManagerWidget) file_mgr_rec->file_window;
8972 ex = -file_window->core.x;
8973 ey = -file_window->core.y;
8974 ewd = XtParent(file_window)->core.width;
8975 eht = XtParent(file_window)->core.height;
8977 /* Set up the icon location information with the drag handler */
8978 /* Register in top to bottom stacking order */
8979 top = GetTopOfStack(file_mgr_data);
8983 file_view_data = top->file_view_data;
8985 if (file_view_data != NULL &&
8986 file_view_data->displayed &&
8987 !file_view_data->need_update)
8989 icon = file_view_data->widget;
8990 if ((Position)(icon->core.x + icon->core.width) >= (Position)ex &&
8991 icon->core.x < ex + ewd &&
8992 (Position)(icon->core.y + icon->core.height) >= (Position)ey &&
8993 icon->core.y < ey + eht)
8995 SetHotRects(file_view_data,
8996 (XtCallbackProc) DropOnObject,
8997 (XtPointer) file_view_data);
9007 * Dtfile used to try to determine if the vertical scrollbar was visible
9008 * by checking to see if it was managed; the assumption here was that the
9009 * scrolled window widget unmanaged the scrollbar, when it was not needed.
9010 * Unfortunately, it turns out that instead of unmanaging the scrollbar,
9011 * the scrolled window simply moves the scrollbar out of sight; it is moved
9012 * such that the X for the scrollbar is the same as the width of the
9013 * scrolled window. So ... in order for us to really determine if the
9014 * scrollbar is visible, we need to see whether or not its X falls within
9015 * the visible area of the scrolled window.
9019 VerticalScrollbarIsVisible(
9024 if (vertSB && XtIsManaged(vertSB) &&
9025 (vertSB->core.x < (Position)scrolledWin->core.width))
9034 HorizontalScrollbarIsVisible(
9039 if (hortSB && XtIsManaged(hortSB) &&
9040 (hortSB->core.y <= (Position)scrolledWin->core.height))