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 /* $XConsortium: IconicPath.c /main/9 1996/10/15 10:08:03 mustafa $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 * COMPONENT_NAME: Desktop File Manager (dtfile)
31 * Description: Contains routines to handle the Iconic Path.
33 * FUNCTIONS: ButtonCallback
58 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
59 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
60 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
61 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
63 ****************************************************************************
64 ************************************<+>*************************************/
66 /* Copied from Xm/XmI.h */
67 #define GMode(g) ((g)->request_mode)
68 #define IsWidth(g) (GMode (g) & CWWidth)
69 #define IsHeight(g) (GMode (g) & CWHeight)
70 #define IsBorder(g) (GMode (g) & CWBorderWidth)
71 #define IsQueryOnly(g) (GMode (g) & XtCWQueryOnly)
73 #include <Xm/TransltnsP.h>
74 #include <Xm/LabelG.h>
75 #include <Xm/PushBG.h>
76 #include <Xm/DragDrop.h>
79 #include <Dt/DtNlUtils.h>
80 #include <Dt/Connect.h>
84 #include "SharedProcs.h"
89 #include "ChangeDir.h"
91 #include "IconicPathP.h"
94 #define defaultTranslations _XmManager_defaultTranslations
95 #define traversalTranslations _XmManager_managerTraversalTranslations
98 /******** Static Function Declarations ********/
100 static void ClassInitialize( void ) ;
101 static void ClassPartInitialize(
102 WidgetClass w_class) ;
103 static void Initialize(
107 Cardinal *num_args) ;
110 static void Redisplay(
116 static XtGeometryResult GeometryManager(
118 XtWidgetGeometry *request,
119 XtWidgetGeometry *reply) ;
120 static void ChangeManaged(
122 static Boolean SetValues(
127 Cardinal *num_args) ;
128 static XtGeometryResult QueryGeometry(
130 XtWidgetGeometry *intended,
131 XtWidgetGeometry *desired) ;
132 static XmNavigability WidgetNavigable(
135 /******** End Static Function Declarations ********/
138 /*--------------------------------------------------------------------
140 *------------------------------------------------------------------*/
142 #define MWD(ip) ((ip)->iconic_path.margin_width)
143 #define MHT(ip) ((ip)->iconic_path.margin_height)
144 #define SPC(ip) ((ip)->iconic_path.spacing)
145 #define MIN_WD(ip) ((ip)->iconic_path.large_icons? \
146 (ip)->iconic_path.large_min_width: \
147 (ip)->iconic_path.small_min_width)
148 #define ICON_HT(ip) ((ip)->iconic_path.large_icons? 32: 16)
150 #define DESIRED_WIDTH(ip) \
151 (MWD(ip) + (ip)->iconic_path.dotdot_button->core.width + MWD(ip) \
152 + ((ip)->iconic_path.dropzone? \
153 ((ip)->iconic_path.dropzone_icon->core.width + MWD(ip)): 0) \
154 + ((ip)->iconic_path.status_msg? \
155 ((ip)->iconic_path.status_label->core.width + MWD(ip)): 0))
157 #define DESIRED_HEIGHT(ip) \
158 (MHT(ip) + ICON_HT(ip) + SPC(ip) + \
159 (ip)->iconic_path.dotdot_button->core.height + MHT(ip))
162 /*--------------------------------------------------------------------
163 * Resource definitions for IconicPath
164 *------------------------------------------------------------------*/
166 static XmSyntheticResource syn_resources[] =
170 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_width),
171 XmeFromHorizontalPixels,
172 XmeToHorizontalPixels
177 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_height),
178 XmeFromVerticalPixels,
184 static XtResource resources[] =
187 XmCMarginWidth, XmRHorizontalDimension, sizeof (Dimension),
188 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_width),
189 XmRImmediate, (XtPointer) 5
193 XmCMarginHeight, XmRVerticalDimension, sizeof (Dimension),
194 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_height),
195 XmRImmediate, (XtPointer) 2
199 XmCSpacing, XmRVerticalDimension, sizeof (Dimension),
200 XtOffsetOf( struct _DtIconicPathRec, iconic_path.spacing),
201 XmRImmediate, (XtPointer) 4
205 XmCMinWidth, XmRHorizontalDimension, sizeof (Dimension),
206 XtOffsetOf( struct _DtIconicPathRec,
207 iconic_path.small_min_width),
208 XmRImmediate, (XtPointer) 25
212 XmCMinWidth, XmRHorizontalDimension, sizeof (Dimension),
213 XtOffsetOf( struct _DtIconicPathRec,
214 iconic_path.large_min_width),
215 XmRImmediate, (XtPointer) 45
218 { DtNforceSmallIcons,
219 DtCForceSmallIcons, XmRBoolean, sizeof (Boolean),
220 XtOffsetOf( struct _DtIconicPathRec,
221 iconic_path.force_small_icons),
222 XmRImmediate, (XtPointer) False
225 { DtNforceLargeIcons,
226 DtCForceLargeIcons, XmRBoolean, sizeof (Boolean),
227 XtOffsetOf( struct _DtIconicPathRec,
228 iconic_path.force_large_icons),
229 XmRImmediate, (XtPointer) False
233 "Buttons", XmRBoolean, sizeof (Boolean),
234 XtOffsetOf( struct _DtIconicPathRec, iconic_path.buttons),
235 XmRImmediate, (XtPointer) False
239 "DropZone", XmRBoolean, sizeof (Boolean),
240 XtOffsetOf( struct _DtIconicPathRec, iconic_path.dropzone),
241 XmRImmediate, (XtPointer) False
245 "StatusMsg", XmRBoolean, sizeof (Boolean),
246 XtOffsetOf( struct _DtIconicPathRec, iconic_path.status_msg),
247 XmRImmediate, (XtPointer) True
251 DtCfileMgrRec, XmRString, sizeof (char *),
252 XtOffsetOf( struct _DtIconicPathRec, iconic_path.file_mgr_rec),
253 XmRImmediate, (XtPointer) NULL
256 { DtNcurrentDirectory,
257 DtCCurrentDirectory, XmRString, sizeof (char *),
258 XtOffsetOf( struct _DtIconicPathRec,
259 iconic_path.current_directory),
260 XmRImmediate, (XtPointer) NULL
264 DtCLargeIcons, XmRBoolean, sizeof (Boolean),
265 XtOffsetOf( struct _DtIconicPathRec, iconic_path.large_icons),
266 XmRImmediate, (XtPointer) True
270 DtCIconsChanged, XmRBoolean, sizeof (Boolean),
271 XtOffsetOf( struct _DtIconicPathRec, iconic_path.icons_changed),
272 XmRImmediate, (XtPointer) True
279 /*--------------------------------------------------------------------
281 * Full class record constant
283 *------------------------------------------------------------------*/
285 static XmBaseClassExtRec baseClassExtRec = {
288 XmBaseClassExtVersion,
289 sizeof(XmBaseClassExtRec),
290 NULL, /* InitializePrehook */
291 NULL, /* SetValuesPrehook */
292 NULL, /* InitializePosthook */
293 NULL, /* SetValuesPosthook */
294 NULL, /* secondaryObjectClass */
295 NULL, /* secondaryCreate */
296 NULL, /* getSecRes data */
297 { 0 }, /* fastSubclass flags */
298 NULL, /* getValuesPrehook */
299 NULL, /* getValuesPosthook */
300 NULL, /* classPartInitPrehook */
301 NULL, /* classPartInitPosthook*/
302 NULL, /* ext_resources */
303 NULL, /* compiled_ext_resources*/
304 0, /* num_ext_resources */
305 FALSE, /* use_sub_resources */
306 WidgetNavigable, /* widgetNavigable */
307 NULL /* focusChange */
310 externaldef( dticonicpathclassrec) DtIconicPathClassRec dtIconicPathClassRec =
312 { /* core_class fields */
313 (WidgetClass) &xmManagerClassRec, /* superclass */
314 "DtIconicPath", /* class_name */
315 sizeof(DtIconicPathRec), /* widget_size */
316 ClassInitialize, /* class_initialize */
317 ClassPartInitialize, /* class_part_init */
318 FALSE, /* class_inited */
319 Initialize, /* initialize */
320 NULL, /* initialize_hook */
321 XtInheritRealize, /* realize */
324 resources, /* resources */
325 XtNumber(resources), /* num_resources */
326 NULLQUARK, /* xrm_class */
327 TRUE, /* compress_motion */
328 FALSE, /* compress_exposure */
329 TRUE, /* compress_enterlv */
330 FALSE, /* visible_interest */
331 Destroy, /* destroy */
333 Redisplay, /* expose */
334 SetValues, /* set_values */
335 NULL, /* set_values_hook */
336 XtInheritSetValuesAlmost, /* set_values_almost */
337 NULL, /* get_values_hook */
338 NULL, /* accept_focus */
339 XtVersion, /* version */
340 NULL, /* callback_private */
341 defaultTranslations, /* tm_table */
342 QueryGeometry, /* query_geometry */
343 NULL, /* display_accelerator*/
344 (XtPointer)&baseClassExtRec, /* extension */
346 { /* composite_class fields */
347 GeometryManager, /* geometry_manager */
348 ChangeManaged, /* change_managed */
349 XtInheritInsertChild, /* insert_child */
350 XtInheritDeleteChild, /* delete_child */
351 NULL, /* extension */
354 { /* constraint_class fields */
355 NULL, /* resource list */
356 0, /* num resources */
357 0, /* constraint size */
358 NULL, /* init proc */
359 NULL, /* destroy proc */
360 NULL, /* set values proc */
361 NULL, /* extension */
364 { /* manager_class fields */
365 traversalTranslations, /* translations */
366 syn_resources, /* syn_resources */
367 XtNumber (syn_resources), /* num_get_resources */
368 NULL, /* syn_cont_resources */
369 0, /* num_get_cont_resources */
370 XmInheritParentProcess, /* parent_process */
371 NULL, /* extension */
374 { /* drawingArea class - none */
379 externaldef( dticonicpathwidgetclass) WidgetClass dtIconicPathWidgetClass
380 = (WidgetClass) &dtIconicPathClassRec ;
383 /*--------------------------------------------------------------------
384 * Activate Callback for iconic path buttons and double click on icons
385 *------------------------------------------------------------------*/
390 XtPointer client_data,
391 XtPointer call_data )
393 DtIconicPathWidget ip = (DtIconicPathWidget)client_data;
394 FileMgrRec *file_mgr_rec = (FileMgrRec *) ip->iconic_path.file_mgr_rec;
395 DialogData *dialog_data;
396 FileMgrData *file_mgr_data;
397 char host_name[MAX_PATH];
400 if (XtClass(w) == dtIconGadgetClass)
402 if (((XmAnyCallbackStruct *)call_data)->reason != XmCR_DEFAULT_ACTION)
406 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
408 file_mgr_data = (FileMgrData *) dialog_data->data;
409 strcpy(host_name, file_mgr_data->host);
411 if (w == ip->iconic_path.dotdot_button)
412 i = ip->iconic_path.left_component - 1;
415 for (i = 0; i < ip->iconic_path.num_components; i++)
416 if (w == ip->iconic_path.components[i].button ||
417 w == ip->iconic_path.components[i].icon)
423 if (i == ip->iconic_path.num_components - 1)
424 FileMgrReread (file_mgr_rec);
426 else if (i < ip->iconic_path.num_components)
427 ShowNewDirectory (file_mgr_data, host_name,
428 ip->iconic_path.components[i].path);
432 /*--------------------------------------------------------------------
433 * Iconic path update function
434 *------------------------------------------------------------------*/
438 DtIconicPathWidget ip,
439 FileMgrRec *file_mgr_rec,
440 FileMgrData *file_mgr_data)
442 static Pixmap change_view_pixmap = XmUNSPECIFIED_PIXMAP;
446 Dimension iwidth, iheight;
448 Pixel foreground, background;
450 char *ptr, *path, *name;
458 PixmapData *pixmapData;
459 char msg_buf[21+MAX_PATH];
461 /* macro that updates the change count */
462 # define INC_N_CHANGES() \
463 if (n_changes++ == 0) \
464 { /* first change: unmanage all children and clear the window */ \
465 XtUnmanageChildren(ip->composite.children, ip->composite.num_children); \
466 if (XtIsRealized((Widget)ip)) \
467 XClearWindow(XtDisplay(ip), XtWindow(ip)); \
470 /* macro that moves a child and updates the change count */
471 # define MOVE_OBJECT(w,_x,_y) \
472 if ((w)->core.x != (_x) || (w)->core.y != (_y)) \
475 XmeConfigureObject(w, _x, _y, (w)->core.width, (w)->core.height, (w)->core.border_width); \
480 "IconicPath.Update: cur_dir '%s', dir_shown '%s', icons_changed %d\n",
481 ip->iconic_path.current_directory,
482 ip->iconic_path.directory_shown? ip->iconic_path.directory_shown: "(nil)",
483 ip->iconic_path.icons_changed));
485 /* enforce the forceSmallIconsor forceLargeIcons resources */
486 if (ip->iconic_path.force_small_icons)
487 ip->iconic_path.large_icons = False;
488 else if (ip->iconic_path.force_large_icons)
489 ip->iconic_path.large_icons = True;
491 /* create "..." button, if necessary */
492 if (ip->iconic_path.dotdot_button == NULL)
494 xm_string = XmStringCreateLocalized("...");
496 XtSetArg (args[n], XmNlabelString, xm_string); n++;
497 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
498 XtSetArg (args[n], XmNmarginHeight, 0); n++;
499 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
500 if (ip->iconic_path.buttons)
502 XtSetArg (args[n], XmNshadowThickness, 1); n++;
503 XtSetArg (args[n], XmNtraversalOn, False); n++;
504 ip->iconic_path.dotdot_button =
505 XmCreatePushButtonGadget((Widget)ip, "iconic_path_button", args, n);
506 XtAddCallback(ip->iconic_path.dotdot_button,
507 XmNactivateCallback, ButtonCallback, ip);
511 ip->iconic_path.dotdot_button =
512 XmCreateLabelGadget((Widget)ip, "iconic_path_label", args, n);
514 XmStringFree(xm_string);
515 if (ip->iconic_path.dotdot_button->core.width < (Dimension)((Dimension)MIN_WD(ip)/(Dimension)2))
517 XmeConfigureObject(ip->iconic_path.dotdot_button,
518 ip->iconic_path.dotdot_button->core.x,
519 ip->iconic_path.dotdot_button->core.y,
520 (Dimension)MIN_WD(ip)/(Dimension)2,
521 ip->iconic_path.dotdot_button->core.height, 0);
524 else if (ip->iconic_path.large_shown != ip->iconic_path.large_icons)
526 xm_string = XmStringCreateLocalized("...");
527 XtSetArg (args[0], XmNlabelString, xm_string);
528 XtSetValues(ip->iconic_path.dotdot_button, args, 1);
529 XmStringFree(xm_string);
530 if (ip->iconic_path.dotdot_button->core.width < (Dimension)((Dimension)MIN_WD(ip)/(Dimension)2))
532 XmeConfigureObject(ip->iconic_path.dotdot_button,
533 ip->iconic_path.dotdot_button->core.x,
534 ip->iconic_path.dotdot_button->core.y,
535 (Dimension)MIN_WD(ip)/(Dimension)2,
536 ip->iconic_path.dotdot_button->core.height, 0);
540 /* create StatuMsg, if necessary */
541 if (ip->iconic_path.status_msg && ip->iconic_path.status_label == NULL)
543 /* create StatuMsg */
545 XtSetArg (args[n], XmNmarginHeight, 0); n++;
546 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
547 ip->iconic_path.status_label =
548 XmCreateLabelGadget((Widget)ip, "status_label", args, n);
551 foreground = ip->manager.foreground;
552 background = ip->core.background_pixel;
554 /* create DropZone, if necessary */
555 if (ip->iconic_path.dropzone && ip->iconic_path.dropzone_icon == NULL)
557 /* create DropZone */
558 if (change_view_pixmap == XmUNSPECIFIED_PIXMAP)
560 foreground = ip->manager.foreground;
561 background = ip->core.background_pixel;
562 change_view_pixmap = _DtGetPixmap(XtScreen(ip), CHANGE_VIEW_ICON_M,
563 foreground, background);
566 XtSetArg (args[n], XmNstring, NULL); n++;
567 XtSetArg (args[n], XmNshadowThickness, 2); n++;
568 XtSetArg (args[n], XmNfillOnArm, False); n++;
569 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
570 XtSetArg (args[n], XmNpixmap, change_view_pixmap); n++;
571 XtSetArg (args[n], XmNtraversalOn, False); n++;
572 XtSetArg (args[n], XmNdropSiteOperations,
573 XmDROP_MOVE | XmDROP_COPY | XmDROP_LINK); n++;
574 ip->iconic_path.dropzone_icon =
575 _DtCreateIcon ((Widget)ip, "change_view", args, n);
577 XtAddCallback (ip->iconic_path.dropzone_icon, XmNdropCallback,
578 DropOnChangeView, (XtPointer) file_mgr_rec);
579 XtAddCallback (ip->iconic_path.dropzone_icon, XmNcallback,
580 CurrentDirDropCallback, file_mgr_rec);
583 /* if the current directory changed, update component list */
584 if (file_mgr_data != NULL && ip->iconic_path.current_directory != NULL &&
585 ip->iconic_path.current_directory[0] == '/' &&
586 (ip->iconic_path.directory_shown == NULL ||
587 strcmp(ip->iconic_path.directory_shown,
588 ip->iconic_path.current_directory) != 0 ||
589 ip->iconic_path.large_shown != ip->iconic_path.large_icons ||
590 ip->iconic_path.icons_changed))
592 /* store the new directory */
593 XtFree(ip->iconic_path.directory_shown);
594 ip->iconic_path.directory_shown =
595 XtNewString(ip->iconic_path.current_directory);
597 /* for restricted directory: compute length of unshown path */
598 if (file_mgr_data->restricted_directory)
600 ptr = strrchr(file_mgr_data->restricted_directory, '/');
601 if( ptr == file_mgr_data->restricted_directory )
604 restricted_len = ptr? ptr - file_mgr_data->restricted_directory: 0;
610 /* get all path components */
612 ptr = ip->iconic_path.directory_shown;
615 /* extract the next path component */
618 if (ip->iconic_path.directory_shown[0] == '\0')
622 path = ip->iconic_path.directory_shown;
623 name = strrchr(path, '/') + 1;
626 /* don't show path components above a restricted directory */
627 path_len = strlen(path);
628 if (restricted_len && path_len <= restricted_len)
631 /* in restricted mode: check if this component is above $HOME */
632 forbidden = restrictMode
633 && strncmp(path, users_home_dir, path_len) == 0
635 users_home_dir[path_len] == '/' &&
636 users_home_dir[path_len + 1] != '\0');
638 /* check if we need to add or update the path component */
639 if (i >= ip->iconic_path.num_components)
641 /* create new component */
644 ip->iconic_path.components = (struct _IconicPathComponent *)
645 XtRealloc((char *)ip->iconic_path.components,
646 (i + 1)*sizeof(struct _IconicPathComponent));
648 ip->iconic_path.components[i].path = XtNewString(path);
649 pixmapData = GetPixmapData(file_mgr_rec,
652 ip->iconic_path.large_icons);
655 XtSetArg (args[n], XmNstring, NULL); n++;
658 XtSetArg (args[n], XmNimageName, pixmapData->iconFileName);
659 ip->iconic_path.components[i].icon_name =
660 XtNewString(pixmapData->iconFileName);
664 XtSetArg (args[n], XmNimageName, NULL);
665 ip->iconic_path.components[i].icon_name = NULL;
670 if ( background == white_pixel )
672 XtSetArg (args[n], XmNbackground, white_pixel); n++;
673 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
674 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
676 else if ( background == black_pixel )
678 XtSetArg (args[n], XmNbackground, black_pixel); n++;
679 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
680 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
684 XtSetArg (args[n], XmNbackground, background); n++;
688 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
689 XtSetArg (args[n], XmNmarginHeight, 0); n++;
690 XtSetArg (args[n], XmNmarginWidth, 0); n++;
691 XtSetArg (args[n], XmNtraversalOn, False); n++;
692 ip->iconic_path.components[i].icon =
693 _DtCreateIcon ((Widget)ip, "iconic_path_icon", args, n);
695 _DtCheckAndFreePixmapData(
696 GetDirectoryLogicalType(file_mgr_data, path),
698 (DtIconGadget) ip->iconic_path.components[i].icon,
701 XtAddCallback (ip->iconic_path.components[i].icon, XmNcallback,
704 if (fileLabel = DtDtsDataTypeToAttributeValue(
705 GetDirectoryLogicalType(file_mgr_data, path),
709 xm_string = XmStringCreateLocalized(fileLabel);
710 DtDtsFreeAttributeValue(fileLabel);
714 xm_string = XmStringCreateLocalized(name);
718 XtSetArg (args[n], XmNlabelString, xm_string); n++;
719 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
720 XtSetArg (args[n], XmNmarginHeight, 0); n++;
721 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
722 if (ip->iconic_path.buttons)
724 XtSetArg (args[n], XmNshadowThickness, 1); n++;
725 XtSetArg (args[n], XmNtraversalOn, False); n++;
726 XtSetArg (args[n], XmNsensitive, !forbidden); n++;
727 ip->iconic_path.components[i].button =
728 XmCreatePushButtonGadget ((Widget)ip, "iconic_path_button",
730 XtAddCallback(ip->iconic_path.components[i].button,
731 XmNactivateCallback, ButtonCallback, ip);
735 ip->iconic_path.components[i].button =
736 XmCreateLabelGadget((Widget)ip, "iconic_path_label", args, n);
738 XmStringFree(xm_string);
743 /* check if the existing component needs to be updated */
745 /* check if the path has changed */
746 if (strcmp(ip->iconic_path.components[i].path, path) != 0 ||
747 ip->iconic_path.large_shown != ip->iconic_path.large_icons)
751 XtFree(ip->iconic_path.components[i].path);
752 ip->iconic_path.components[i].path = XtNewString(path);
755 if (fileLabel = DtDtsDataTypeToAttributeValue(
756 GetDirectoryLogicalType(file_mgr_data, path),
760 xm_string = XmStringCreateLocalized(fileLabel);
761 DtDtsFreeAttributeValue(fileLabel);
765 xm_string = XmStringCreateLocalized(name);
767 XtSetArg (args[0], XmNlabelString, xm_string);
768 XtSetArg (args[1], XmNsensitive, !forbidden);
769 XtSetValues(ip->iconic_path.components[i].button, args, 2);
770 XmStringFree(xm_string);
772 /* check if the icon has changed */
773 pixmapData = GetPixmapData(file_mgr_rec,
776 ip->iconic_path.large_icons);
780 if ((pixmapData->iconFileName == NULL) !=
781 (ip->iconic_path.components[i].icon_name == NULL) ||
782 pixmapData->iconFileName != NULL &&
783 strcmp(pixmapData->iconFileName,
784 ip->iconic_path.components[i].icon_name) != 0)
788 XtFree(ip->iconic_path.components[i].icon_name);
789 ip->iconic_path.components[i].icon_name =
790 XtNewString(pixmapData->iconFileName);
792 XtSetArg (args[0], XmNimageName, pixmapData->iconFileName);
793 XtSetValues(ip->iconic_path.components[i].icon, args, 1);
795 _DtCheckAndFreePixmapData(
796 GetDirectoryLogicalType(file_mgr_data, path),
798 (DtIconGadget) ip->iconic_path.components[i].icon,
804 XtFree(ip->iconic_path.components[i].icon_name);
805 ip->iconic_path.components[i].icon_name = NULL;
806 XtSetArg (args[0], XmNimageName, NULL);
807 XtSetValues(ip->iconic_path.components[i].icon, args, 1);
811 /* update component count */
815 /* go to the next path component */
822 /* find next component */
823 if (strcmp(ptr, "/") == 0)
825 ptr = DtStrchr(ptr + 1, '/');
828 /* free any leftover components */
829 for (j = i; j < ip->iconic_path.num_components; j++)
833 XtFree(ip->iconic_path.components[j].path);
834 ip->iconic_path.components[j].path = NULL;
835 XtFree(ip->iconic_path.components[j].icon_name);
836 ip->iconic_path.components[j].icon_name = NULL;
837 XtDestroyWidget(ip->iconic_path.components[j].icon);
838 XtDestroyWidget(ip->iconic_path.components[j].button);
841 ip->iconic_path.num_components = i;
842 ip->iconic_path.large_shown = ip->iconic_path.large_icons;
845 /* update component widths */
846 for (i = 0; i < ip->iconic_path.num_components; i++)
848 /* determine width for this component */
850 if (ip->iconic_path.components[i].icon->core.width > (Dimension)twidth)
851 twidth = ip->iconic_path.components[i].icon->core.width;
852 if (ip->iconic_path.components[i].button->core.width > (Dimension)twidth)
853 twidth = ip->iconic_path.components[i].button->core.width;
855 if (ip->iconic_path.components[i].button->core.width < (Dimension)twidth)
857 /* increment the change count */
861 XmeConfigureObject(ip->iconic_path.components[i].button,
862 ip->iconic_path.components[i].button->core.x,
863 ip->iconic_path.components[i].button->core.y,
865 ip->iconic_path.components[i].button->core.height,
869 ip->iconic_path.components[i].width = twidth;
872 /* update the status message */
873 if (file_mgr_data && ip->iconic_path.status_msg)
874 GetStatusMsg(file_mgr_data, msg_buf);
878 if (ip->iconic_path.msg_text == NULL ||
879 strcmp(msg_buf, ip->iconic_path.msg_text) != 0)
881 /* remember the new status message text */
882 XtFree(ip->iconic_path.msg_text);
883 ip->iconic_path.msg_text = XtNewString(msg_buf);
885 if (ip->iconic_path.status_label)
887 /* clear the area under the old status message text */
888 if (XtIsRealized((Widget)ip) &&
889 ip->iconic_path.status_label->core.x > 0)
890 XClearArea(XtDisplay(ip), XtWindow(ip),
891 ip->iconic_path.status_label->core.x,
892 ip->iconic_path.status_label->core.y,
893 ip->iconic_path.status_label->core.width,
894 ip->iconic_path.status_label->core.height, False);
896 /* set a new status message text */
897 xm_string = XmStringCreateLocalized(msg_buf);
898 XtSetArg (args[0], XmNlabelString, xm_string);
899 XtSetValues(ip->iconic_path.status_label, args, 1);
900 XmStringFree(xm_string);
904 /* set widget size, if necessary */
905 if (ip->core.width == 0)
906 ip->core.width = DESIRED_WIDTH(ip);
907 if (ip->core.height == 0)
908 ip->core.height = DESIRED_HEIGHT(ip);
910 /* for the layout: check how much of the path will fit */
911 twidth = MWD(ip) + ip->iconic_path.dotdot_button->core.width + MWD(ip);
912 if (ip->iconic_path.status_msg && ip->iconic_path.dropzone)
914 if (ip->iconic_path.status_label->core.width
915 >= ip->iconic_path.dropzone_icon->core.width)
916 twidth += ip->iconic_path.status_label->core.width + MWD(ip);
918 twidth += ip->iconic_path.dropzone_icon->core.width + MWD(ip);
920 else if (ip->iconic_path.status_msg)
921 twidth += ip->iconic_path.status_label->core.width + MWD(ip);
922 else if (ip->iconic_path.dropzone)
923 twidth += ip->iconic_path.dropzone_icon->core.width + MWD(ip);
926 for (i = ip->iconic_path.num_components; i > 0; i--)
928 twidth += SPC(ip) + ip->iconic_path.components[i - 1].width;
929 if ((Dimension)twidth > ip->core.width)
933 if (i == 1 && (Dimension)(twidth - ip->iconic_path.dotdot_button->core.width - SPC(ip))
939 if (i != ip->iconic_path.left_component)
942 ip->iconic_path.left_component = i;
945 /* allocate list of to-be-managed children */
947 XtMalloc((2*(ip->iconic_path.num_components - i) + 2)*sizeof(Widget));
950 /* position & manage the path components */
952 y = ip->core.height - MHT(ip) - ip->iconic_path.dotdot_button->core.height
957 MOVE_OBJECT(ip->iconic_path.dotdot_button, x, y + SPC(ip));
958 manage[nmanage++] = ip->iconic_path.dotdot_button;
959 x += ip->iconic_path.dotdot_button->core.width + SPC(ip);
962 for (j = i; j < ip->iconic_path.num_components; j++)
964 MOVE_OBJECT(ip->iconic_path.components[j].icon,
966 y - ip->iconic_path.components[j].icon->core.height);
967 MOVE_OBJECT(ip->iconic_path.components[j].button, x, y + SPC(ip));
969 x += ip->iconic_path.components[j].width + SPC(ip);
971 manage[nmanage++] = ip->iconic_path.components[j].icon;
972 manage[nmanage++] = ip->iconic_path.components[j].button;
975 /* position & manage the status message label */
976 if (ip->iconic_path.status_msg)
978 x = ip->core.width - MWD(ip) -
979 (int)ip->iconic_path.status_label->core.width;
982 y = ip->core.height - MHT(ip) -
983 (int)ip->iconic_path.status_label->core.height;
987 if (ip->iconic_path.status_label->core.x != x ||
988 ip->iconic_path.status_label->core.y != y)
990 XmeConfigureObject(ip->iconic_path.status_label, x, y,
991 ip->iconic_path.status_label->core.width,
992 ip->iconic_path.status_label->core.height,
993 ip->iconic_path.status_label->core.border_width);
996 manage[nmanage++] = ip->iconic_path.status_label;
1001 y = ip->core.height;
1003 /* position & manage the drop zone icon */
1004 if (ip->iconic_path.dropzone)
1006 x = ip->core.width - MWD(ip) -
1007 (int)ip->iconic_path.dropzone_icon->core.width;
1010 y = (y - (int)ip->iconic_path.dropzone_icon->core.height + 1)/2;
1014 MOVE_OBJECT(ip->iconic_path.dropzone_icon, x, y);
1016 manage[nmanage++] = ip->iconic_path.dropzone_icon;
1020 /* if all icons are there, manage the children */
1021 for (i = 0; i < ip->iconic_path.num_components; i++)
1022 if (ip->iconic_path.components[i].icon_name == NULL)
1024 if (file_mgr_data != NULL && i == ip->iconic_path.num_components)
1026 DPRINTF2(("IconicPath.Update: manage %d children\n", nmanage));
1027 XtManageChildren(manage, nmanage);
1029 XtFree((char *)manage);
1031 /* reset icons_changed flag */
1032 ip->iconic_path.icons_changed = False;
1038 /*--------------------------------------------------------------------
1039 * Iconic path redraw function
1040 *------------------------------------------------------------------*/
1044 DtIconicPathWidget ip)
1046 FileMgrRec *file_mgr_rec = (FileMgrRec *)ip->iconic_path.file_mgr_rec;
1047 DialogData * dialog_data;
1048 FileMgrData *file_mgr_data;
1052 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1054 file_mgr_data = (FileMgrData *) dialog_data->data;
1056 if (ip->iconic_path.gc == None)
1058 XGCValues gc_values;
1060 gc_values.foreground = ip->manager.foreground;
1061 gc_values.line_width = 2;
1063 ip->iconic_path.gc = XCreateGC(XtDisplay(ip), XtWindow(ip),
1064 GCForeground | GCLineWidth, &gc_values);
1068 y = ip->core.height - MHT(ip) - ip->iconic_path.dotdot_button->core.height
1069 - SPC(ip) - ICON_HT(ip)/2;
1071 if (ip->iconic_path.left_component > 0)
1073 XSetLineAttributes(XtDisplay(ip), ip->iconic_path.gc,
1074 2, LineOnOffDash, CapNotLast, JoinMiter);
1075 XSetDashes(XtDisplay(ip), ip->iconic_path.gc, 0, "\04", 1);
1077 l = ip->iconic_path.dotdot_button->core.width + SPC(ip) - 3;
1079 XDrawLine(XtDisplay(ip), XtWindow(ip), ip->iconic_path.gc,
1080 x + 2 + l, y, x + 2, y);
1081 x += ip->iconic_path.dotdot_button->core.width + SPC(ip);
1082 XSetLineAttributes(XtDisplay(ip), ip->iconic_path.gc,
1083 2, LineSolid, CapNotLast, JoinMiter);
1086 for (i = ip->iconic_path.left_component;
1087 i < ip->iconic_path.num_components - 1;
1090 if (ip->iconic_path.components[i].icon_name != NULL &&
1091 ip->iconic_path.components[i+1].icon_name != NULL)
1093 XDrawLine(XtDisplay(ip), XtWindow(ip), ip->iconic_path.gc,
1095 ip->iconic_path.components[i].icon->core.width + 1,
1098 ip->iconic_path.components[i].width + SPC(ip) - 1,
1101 x += ip->iconic_path.components[i].width + SPC(ip);
1107 /*--------------------------------------------------------------------
1109 *------------------------------------------------------------------*/
1112 ClassInitialize( void )
1114 baseClassExtRec.record_type = XmQmotif ;
1119 ClassPartInitialize(
1120 WidgetClass w_class )
1122 _XmFastSubclassInit( w_class, XmDRAWING_AREA_BIT) ;
1127 /*--------------------------------------------------------------------
1128 * Instance initialize
1129 *------------------------------------------------------------------*/
1136 Cardinal *num_args )
1138 DtIconicPathWidget new_w = (DtIconicPathWidget) nw ;
1139 FileMgrRec *file_mgr_rec = (FileMgrRec *)new_w->iconic_path.file_mgr_rec;
1141 new_w->iconic_path.msg_text = NULL;
1142 new_w->iconic_path.current_directory = NULL;
1143 new_w->iconic_path.directory_shown = NULL;
1144 new_w->iconic_path.large_shown = False;
1145 new_w->iconic_path.status_label = NULL;
1146 new_w->iconic_path.dotdot_button = NULL;
1147 new_w->iconic_path.dropzone_icon = NULL;
1148 new_w->iconic_path.num_components = 0;
1149 new_w->iconic_path.components = NULL;
1150 new_w->iconic_path.left_component = 0;
1151 new_w->iconic_path.gc = None;
1153 Update(new_w, file_mgr_rec, NULL);
1159 /*--------------------------------------------------------------------
1161 *------------------------------------------------------------------*/
1167 DtIconicPathWidget ip = (DtIconicPathWidget) w;
1171 XtFree(ip->iconic_path.current_directory);
1173 ip->iconic_path.current_directory = NULL;
1174 XtFree(ip->iconic_path.msg_text);
1175 ip->iconic_path.msg_text = NULL;
1176 XtFree(ip->iconic_path.directory_shown);
1177 ip->iconic_path.directory_shown = NULL;
1179 for (i = 0; i < ip->iconic_path.num_components; i++)
1181 XtFree(ip->iconic_path.components[i].path);
1182 ip->iconic_path.components[i].path = NULL;
1185 XtFree((char *)ip->iconic_path.components);
1186 ip->iconic_path.components = NULL;
1192 /*--------------------------------------------------------------------
1193 * General redisplay function called on exposure events
1194 *------------------------------------------------------------------*/
1202 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1204 IconicPathRedraw (ip);
1206 XmeRedisplayGadgets( (Widget) ip, event, region);
1211 /*--------------------------------------------------------------------
1213 *------------------------------------------------------------------*/
1219 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1220 FileMgrRec *file_mgr_rec = (FileMgrRec *)ip->iconic_path.file_mgr_rec;
1221 DialogData *dialog_data;
1222 FileMgrData *file_mgr_data;
1224 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1226 file_mgr_data = (FileMgrData *) dialog_data->data;
1228 Update(ip, file_mgr_rec, file_mgr_data);
1234 /*--------------------------------------------------------------------
1236 *------------------------------------------------------------------*/
1238 static XtGeometryResult
1241 XtWidgetGeometry *request,
1242 XtWidgetGeometry *reply )
1244 DtIconicPathWidget ip;
1246 ip = (DtIconicPathWidget) w->core.parent;
1248 if (IsQueryOnly(request)) return XtGeometryYes;
1250 if (IsWidth(request)) w->core.width = request->width;
1251 if (IsHeight(request)) w->core.height = request->height;
1252 if (IsBorder(request)) w->core.border_width = request->border_width;
1254 /* @@@ adjust layout ? */
1256 return XtGeometryYes;
1260 /*--------------------------------------------------------------------
1261 * Re-layout children
1262 *------------------------------------------------------------------*/
1268 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1269 XtWidgetProc manager ;
1271 XmeNavigChangeManaged((Widget) ip) ;
1277 /*--------------------------------------------------------------------
1279 *------------------------------------------------------------------*/
1287 Cardinal *num_args )
1289 DtIconicPathWidget current = (DtIconicPathWidget) cw ;
1290 DtIconicPathWidget ip = (DtIconicPathWidget) nw ;
1291 FileMgrRec *file_mgr_rec = (FileMgrRec *)ip->iconic_path.file_mgr_rec;
1292 DialogData *dialog_data;
1293 FileMgrData *file_mgr_data;
1296 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1297 file_mgr_data = dialog_data? (FileMgrData *) dialog_data->data: NULL;
1299 redisplay = (Update(ip, file_mgr_rec, file_mgr_data) > 0);
1301 if (XtHeight(ip) != DESIRED_HEIGHT(ip)
1302 || (Dimension)XtWidth(ip) < (Dimension)DESIRED_WIDTH(ip))
1304 XtWidgetGeometry request;
1305 XtWidgetGeometry reply;
1307 request.request_mode = 0;
1308 if (XtHeight(ip) != DESIRED_HEIGHT(ip))
1310 request.request_mode |= CWHeight;
1311 request.height = DESIRED_HEIGHT(ip);
1313 if ((Dimension)XtWidth(ip) < (Dimension)DESIRED_WIDTH(ip))
1315 request.request_mode |= CWWidth;
1316 request.width = DESIRED_WIDTH(ip);
1319 if (XtMakeGeometryRequest(nw, &request, &reply) != XtGeometryNo)
1320 Update(ip, file_mgr_rec, file_mgr_data);
1329 /*--------------------------------------------------------------------
1331 *------------------------------------------------------------------*/
1333 static XtGeometryResult
1336 XtWidgetGeometry *intended,
1337 XtWidgetGeometry *desired )
1339 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1341 desired->width = DESIRED_WIDTH(ip);
1342 desired->height = DESIRED_HEIGHT(ip);
1344 /* deal with user initial size setting */
1345 if (!XtIsRealized(wid))
1347 if (XtWidth(wid) != 0) desired->width = XtWidth(wid) ;
1348 if (XtHeight(wid) != 0) desired->height = XtHeight(wid) ;
1351 return XmeReplyToQueryGeometry(wid, intended, desired) ;
1354 static XmNavigability
1358 if( wid->core.sensitive
1359 && wid->core.ancestor_sensitive
1360 && ((XmManagerWidget) wid)->manager.traversal_on )
1362 XmNavigationType nav_type
1363 = ((XmManagerWidget) wid)->manager.navigation_type ;
1365 if( (nav_type == XmSTICKY_TAB_GROUP)
1366 || (nav_type == XmEXCLUSIVE_TAB_GROUP)
1367 || ( (nav_type == XmTAB_GROUP)
1368 && !_XmShellIsExclusive( wid)) )
1370 return XmDESCENDANTS_TAB_NAVIGABLE ;
1373 return XmNOT_NAVIGABLE ;
1377 /*--------------------------------------------------------------------
1378 * _DtCreateIconicPath: creates and returns a IconicPath widget.
1379 *------------------------------------------------------------------*/
1382 _DtCreateIconicPath(
1388 return( XtCreateWidget( name, dtIconicPathWidgetClass, p, args, n)) ;
1392 /*--------------------------------------------------------------------
1393 * UpdateIconicPath: update IconicPath widget.
1394 *------------------------------------------------------------------*/
1398 FileMgrRec *file_mgr_rec,
1399 FileMgrData *file_mgr_data,
1400 Boolean icons_changed)
1404 XtSetArg (args[0], DtNfileMgrRec, file_mgr_rec);
1405 XtSetArg (args[1], DtNcurrentDirectory, file_mgr_data->current_directory);
1406 XtSetArg (args[2], DtNlargeIcons, file_mgr_data->view == BY_NAME_AND_ICON);
1407 XtSetArg (args[3], DtNiconsChanged, icons_changed);
1408 XtSetArg (args[4], "statusMsg", !file_mgr_data->show_status_line);
1409 XtSetValues(file_mgr_rec->iconic_path_da, args, 5);