2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $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"
86 #include <Xm/XmPrivate.h> /* _XmShellIsExclusive */
91 #include "ChangeDir.h"
93 #include "IconicPathP.h"
96 #define defaultTranslations _XmManager_defaultTranslations
97 #define traversalTranslations _XmManager_managerTraversalTranslations
100 /******** Static Function Declarations ********/
102 static void ClassInitialize( void ) ;
103 static void ClassPartInitialize(
104 WidgetClass w_class) ;
105 static void Initialize(
109 Cardinal *num_args) ;
112 static void Redisplay(
118 static XtGeometryResult GeometryManager(
120 XtWidgetGeometry *request,
121 XtWidgetGeometry *reply) ;
122 static void ChangeManaged(
124 static Boolean SetValues(
129 Cardinal *num_args) ;
130 static XtGeometryResult QueryGeometry(
132 XtWidgetGeometry *intended,
133 XtWidgetGeometry *desired) ;
134 static XmNavigability WidgetNavigable(
137 /******** End Static Function Declarations ********/
140 /*--------------------------------------------------------------------
142 *------------------------------------------------------------------*/
144 #define MWD(ip) ((ip)->iconic_path.margin_width)
145 #define MHT(ip) ((ip)->iconic_path.margin_height)
146 #define SPC(ip) ((ip)->iconic_path.spacing)
147 #define MIN_WD(ip) ((ip)->iconic_path.large_icons? \
148 (ip)->iconic_path.large_min_width: \
149 (ip)->iconic_path.small_min_width)
150 #define ICON_HT(ip) ((ip)->iconic_path.large_icons? 32: 16)
152 #define DESIRED_WIDTH(ip) \
153 (MWD(ip) + (ip)->iconic_path.dotdot_button->core.width + MWD(ip) \
154 + ((ip)->iconic_path.dropzone? \
155 ((ip)->iconic_path.dropzone_icon->core.width + MWD(ip)): 0) \
156 + ((ip)->iconic_path.status_msg? \
157 ((ip)->iconic_path.status_label->core.width + MWD(ip)): 0))
159 #define DESIRED_HEIGHT(ip) \
160 (MHT(ip) + ICON_HT(ip) + SPC(ip) + \
161 (ip)->iconic_path.dotdot_button->core.height + MHT(ip))
164 /*--------------------------------------------------------------------
165 * Resource definitions for IconicPath
166 *------------------------------------------------------------------*/
168 static XmSyntheticResource syn_resources[] =
172 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_width),
173 XmeFromHorizontalPixels,
174 XmeToHorizontalPixels
179 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_height),
180 XmeFromVerticalPixels,
186 static XtResource resources[] =
189 XmCMarginWidth, XmRHorizontalDimension, sizeof (Dimension),
190 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_width),
191 XmRImmediate, (XtPointer) 5
195 XmCMarginHeight, XmRVerticalDimension, sizeof (Dimension),
196 XtOffsetOf( struct _DtIconicPathRec, iconic_path.margin_height),
197 XmRImmediate, (XtPointer) 2
201 XmCSpacing, XmRVerticalDimension, sizeof (Dimension),
202 XtOffsetOf( struct _DtIconicPathRec, iconic_path.spacing),
203 XmRImmediate, (XtPointer) 4
207 XmCMinWidth, XmRHorizontalDimension, sizeof (Dimension),
208 XtOffsetOf( struct _DtIconicPathRec,
209 iconic_path.small_min_width),
210 XmRImmediate, (XtPointer) 25
214 XmCMinWidth, XmRHorizontalDimension, sizeof (Dimension),
215 XtOffsetOf( struct _DtIconicPathRec,
216 iconic_path.large_min_width),
217 XmRImmediate, (XtPointer) 45
220 { DtNforceSmallIcons,
221 DtCForceSmallIcons, XmRBoolean, sizeof (Boolean),
222 XtOffsetOf( struct _DtIconicPathRec,
223 iconic_path.force_small_icons),
224 XmRImmediate, (XtPointer) False
227 { DtNforceLargeIcons,
228 DtCForceLargeIcons, XmRBoolean, sizeof (Boolean),
229 XtOffsetOf( struct _DtIconicPathRec,
230 iconic_path.force_large_icons),
231 XmRImmediate, (XtPointer) False
235 "Buttons", XmRBoolean, sizeof (Boolean),
236 XtOffsetOf( struct _DtIconicPathRec, iconic_path.buttons),
237 XmRImmediate, (XtPointer) False
241 "DropZone", XmRBoolean, sizeof (Boolean),
242 XtOffsetOf( struct _DtIconicPathRec, iconic_path.dropzone),
243 XmRImmediate, (XtPointer) False
247 "StatusMsg", XmRBoolean, sizeof (Boolean),
248 XtOffsetOf( struct _DtIconicPathRec, iconic_path.status_msg),
249 XmRImmediate, (XtPointer) True
253 DtCfileMgrRec, XmRString, sizeof (char *),
254 XtOffsetOf( struct _DtIconicPathRec, iconic_path.file_mgr_rec),
255 XmRImmediate, (XtPointer) NULL
258 { DtNcurrentDirectory,
259 DtCCurrentDirectory, XmRString, sizeof (char *),
260 XtOffsetOf( struct _DtIconicPathRec,
261 iconic_path.current_directory),
262 XmRImmediate, (XtPointer) NULL
266 DtCLargeIcons, XmRBoolean, sizeof (Boolean),
267 XtOffsetOf( struct _DtIconicPathRec, iconic_path.large_icons),
268 XmRImmediate, (XtPointer) True
272 DtCIconsChanged, XmRBoolean, sizeof (Boolean),
273 XtOffsetOf( struct _DtIconicPathRec, iconic_path.icons_changed),
274 XmRImmediate, (XtPointer) True
281 /*--------------------------------------------------------------------
283 * Full class record constant
285 *------------------------------------------------------------------*/
287 static XmBaseClassExtRec baseClassExtRec = {
290 XmBaseClassExtVersion,
291 sizeof(XmBaseClassExtRec),
292 NULL, /* InitializePrehook */
293 NULL, /* SetValuesPrehook */
294 NULL, /* InitializePosthook */
295 NULL, /* SetValuesPosthook */
296 NULL, /* secondaryObjectClass */
297 NULL, /* secondaryCreate */
298 NULL, /* getSecRes data */
299 { 0 }, /* fastSubclass flags */
300 NULL, /* getValuesPrehook */
301 NULL, /* getValuesPosthook */
302 NULL, /* classPartInitPrehook */
303 NULL, /* classPartInitPosthook*/
304 NULL, /* ext_resources */
305 NULL, /* compiled_ext_resources*/
306 0, /* num_ext_resources */
307 FALSE, /* use_sub_resources */
308 WidgetNavigable, /* widgetNavigable */
309 NULL /* focusChange */
312 externaldef( dticonicpathclassrec) DtIconicPathClassRec dtIconicPathClassRec =
314 { /* core_class fields */
315 (WidgetClass) &xmManagerClassRec, /* superclass */
316 "DtIconicPath", /* class_name */
317 sizeof(DtIconicPathRec), /* widget_size */
318 ClassInitialize, /* class_initialize */
319 ClassPartInitialize, /* class_part_init */
320 FALSE, /* class_inited */
321 Initialize, /* initialize */
322 NULL, /* initialize_hook */
323 XtInheritRealize, /* realize */
326 resources, /* resources */
327 XtNumber(resources), /* num_resources */
328 NULLQUARK, /* xrm_class */
329 TRUE, /* compress_motion */
330 FALSE, /* compress_exposure */
331 TRUE, /* compress_enterlv */
332 FALSE, /* visible_interest */
333 Destroy, /* destroy */
335 Redisplay, /* expose */
336 SetValues, /* set_values */
337 NULL, /* set_values_hook */
338 XtInheritSetValuesAlmost, /* set_values_almost */
339 NULL, /* get_values_hook */
340 NULL, /* accept_focus */
341 XtVersion, /* version */
342 NULL, /* callback_private */
343 defaultTranslations, /* tm_table */
344 QueryGeometry, /* query_geometry */
345 NULL, /* display_accelerator*/
346 (XtPointer)&baseClassExtRec, /* extension */
348 { /* composite_class fields */
349 GeometryManager, /* geometry_manager */
350 ChangeManaged, /* change_managed */
351 XtInheritInsertChild, /* insert_child */
352 XtInheritDeleteChild, /* delete_child */
353 NULL, /* extension */
356 { /* constraint_class fields */
357 NULL, /* resource list */
358 0, /* num resources */
359 0, /* constraint size */
360 NULL, /* init proc */
361 NULL, /* destroy proc */
362 NULL, /* set values proc */
363 NULL, /* extension */
366 { /* manager_class fields */
367 traversalTranslations, /* translations */
368 syn_resources, /* syn_resources */
369 XtNumber (syn_resources), /* num_get_resources */
370 NULL, /* syn_cont_resources */
371 0, /* num_get_cont_resources */
372 XmInheritParentProcess, /* parent_process */
373 NULL, /* extension */
376 { /* drawingArea class - none */
381 externaldef( dticonicpathwidgetclass) WidgetClass dtIconicPathWidgetClass
382 = (WidgetClass) &dtIconicPathClassRec ;
385 /*--------------------------------------------------------------------
386 * Activate Callback for iconic path buttons and double click on icons
387 *------------------------------------------------------------------*/
392 XtPointer client_data,
393 XtPointer call_data )
395 DtIconicPathWidget ip = (DtIconicPathWidget)client_data;
396 FileMgrRec *file_mgr_rec = (FileMgrRec *) ip->iconic_path.file_mgr_rec;
397 DialogData *dialog_data;
398 FileMgrData *file_mgr_data;
399 char host_name[MAX_PATH];
402 if (XtClass(w) == dtIconGadgetClass)
404 if (((XmAnyCallbackStruct *)call_data)->reason != XmCR_DEFAULT_ACTION)
408 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
410 file_mgr_data = (FileMgrData *) dialog_data->data;
411 strcpy(host_name, file_mgr_data->host);
413 if (w == ip->iconic_path.dotdot_button)
414 i = ip->iconic_path.left_component - 1;
417 for (i = 0; i < ip->iconic_path.num_components; i++)
418 if (w == ip->iconic_path.components[i].button ||
419 w == ip->iconic_path.components[i].icon)
425 if (i == ip->iconic_path.num_components - 1)
426 FileMgrReread (file_mgr_rec);
428 else if (i < ip->iconic_path.num_components)
429 ShowNewDirectory (file_mgr_data, host_name,
430 ip->iconic_path.components[i].path);
434 /*--------------------------------------------------------------------
435 * Iconic path update function
436 *------------------------------------------------------------------*/
440 DtIconicPathWidget ip,
441 FileMgrRec *file_mgr_rec,
442 FileMgrData *file_mgr_data)
444 static Pixmap change_view_pixmap = XmUNSPECIFIED_PIXMAP;
448 Dimension iwidth, iheight;
450 Pixel foreground, background;
452 char *ptr, *path, *name;
460 PixmapData *pixmapData;
461 char msg_buf[21+MAX_PATH];
463 /* macro that updates the change count */
464 # define INC_N_CHANGES() \
465 if (n_changes++ == 0) \
466 { /* first change: unmanage all children and clear the window */ \
467 XtUnmanageChildren(ip->composite.children, ip->composite.num_children); \
468 if (XtIsRealized((Widget)ip)) \
469 XClearWindow(XtDisplay(ip), XtWindow(ip)); \
472 /* macro that moves a child and updates the change count */
473 # define MOVE_OBJECT(w,_x,_y) \
474 if ((w)->core.x != (_x) || (w)->core.y != (_y)) \
477 XmeConfigureObject(w, _x, _y, (w)->core.width, (w)->core.height, (w)->core.border_width); \
482 "IconicPath.Update: cur_dir '%s', dir_shown '%s', icons_changed %d\n",
483 ip->iconic_path.current_directory,
484 ip->iconic_path.directory_shown? ip->iconic_path.directory_shown: "(nil)",
485 ip->iconic_path.icons_changed));
487 /* enforce the forceSmallIconsor forceLargeIcons resources */
488 if (ip->iconic_path.force_small_icons)
489 ip->iconic_path.large_icons = False;
490 else if (ip->iconic_path.force_large_icons)
491 ip->iconic_path.large_icons = True;
493 /* create "..." button, if necessary */
494 if (ip->iconic_path.dotdot_button == NULL)
496 xm_string = XmStringCreateLocalized("...");
498 XtSetArg (args[n], XmNlabelString, xm_string); n++;
499 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
500 XtSetArg (args[n], XmNmarginHeight, 0); n++;
501 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
502 if (ip->iconic_path.buttons)
504 XtSetArg (args[n], XmNshadowThickness, 1); n++;
505 XtSetArg (args[n], XmNtraversalOn, False); n++;
506 ip->iconic_path.dotdot_button =
507 XmCreatePushButtonGadget((Widget)ip, "iconic_path_button", args, n);
508 XtAddCallback(ip->iconic_path.dotdot_button,
509 XmNactivateCallback, ButtonCallback, ip);
513 ip->iconic_path.dotdot_button =
514 XmCreateLabelGadget((Widget)ip, "iconic_path_label", args, n);
516 XmStringFree(xm_string);
517 if (ip->iconic_path.dotdot_button->core.width < (Dimension)((Dimension)MIN_WD(ip)/(Dimension)2))
519 XmeConfigureObject(ip->iconic_path.dotdot_button,
520 ip->iconic_path.dotdot_button->core.x,
521 ip->iconic_path.dotdot_button->core.y,
522 (Dimension)MIN_WD(ip)/(Dimension)2,
523 ip->iconic_path.dotdot_button->core.height, 0);
526 else if (ip->iconic_path.large_shown != ip->iconic_path.large_icons)
528 xm_string = XmStringCreateLocalized("...");
529 XtSetArg (args[0], XmNlabelString, xm_string);
530 XtSetValues(ip->iconic_path.dotdot_button, args, 1);
531 XmStringFree(xm_string);
532 if (ip->iconic_path.dotdot_button->core.width < (Dimension)((Dimension)MIN_WD(ip)/(Dimension)2))
534 XmeConfigureObject(ip->iconic_path.dotdot_button,
535 ip->iconic_path.dotdot_button->core.x,
536 ip->iconic_path.dotdot_button->core.y,
537 (Dimension)MIN_WD(ip)/(Dimension)2,
538 ip->iconic_path.dotdot_button->core.height, 0);
542 /* create StatuMsg, if necessary */
543 if (ip->iconic_path.status_msg && ip->iconic_path.status_label == NULL)
545 /* create StatuMsg */
547 XtSetArg (args[n], XmNmarginHeight, 0); n++;
548 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
549 ip->iconic_path.status_label =
550 XmCreateLabelGadget((Widget)ip, "status_label", args, n);
553 foreground = ip->manager.foreground;
554 background = ip->core.background_pixel;
556 /* create DropZone, if necessary */
557 if (ip->iconic_path.dropzone && ip->iconic_path.dropzone_icon == NULL)
559 /* create DropZone */
560 if (change_view_pixmap == XmUNSPECIFIED_PIXMAP)
562 foreground = ip->manager.foreground;
563 background = ip->core.background_pixel;
564 change_view_pixmap = _DtGetPixmap(XtScreen(ip), CHANGE_VIEW_ICON_M,
565 foreground, background);
568 XtSetArg (args[n], XmNstring, NULL); n++;
569 XtSetArg (args[n], XmNshadowThickness, 2); n++;
570 XtSetArg (args[n], XmNfillOnArm, False); n++;
571 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
572 XtSetArg (args[n], XmNpixmap, change_view_pixmap); n++;
573 XtSetArg (args[n], XmNtraversalOn, False); n++;
574 XtSetArg (args[n], XmNdropSiteOperations,
575 XmDROP_MOVE | XmDROP_COPY | XmDROP_LINK); n++;
576 ip->iconic_path.dropzone_icon =
577 _DtCreateIcon ((Widget)ip, "change_view", args, n);
579 XtAddCallback (ip->iconic_path.dropzone_icon, XmNdropCallback,
580 DropOnChangeView, (XtPointer) file_mgr_rec);
581 XtAddCallback (ip->iconic_path.dropzone_icon, XmNcallback,
582 CurrentDirDropCallback, file_mgr_rec);
585 /* if the current directory changed, update component list */
586 if (file_mgr_data != NULL && ip->iconic_path.current_directory != NULL &&
587 ip->iconic_path.current_directory[0] == '/' &&
588 (ip->iconic_path.directory_shown == NULL ||
589 strcmp(ip->iconic_path.directory_shown,
590 ip->iconic_path.current_directory) != 0 ||
591 ip->iconic_path.large_shown != ip->iconic_path.large_icons ||
592 ip->iconic_path.icons_changed))
594 /* store the new directory */
595 XtFree(ip->iconic_path.directory_shown);
596 ip->iconic_path.directory_shown =
597 XtNewString(ip->iconic_path.current_directory);
599 /* for restricted directory: compute length of unshown path */
600 if (file_mgr_data->restricted_directory)
602 ptr = strrchr(file_mgr_data->restricted_directory, '/');
603 if( ptr == file_mgr_data->restricted_directory )
606 restricted_len = ptr? ptr - file_mgr_data->restricted_directory: 0;
612 /* get all path components */
614 ptr = ip->iconic_path.directory_shown;
617 /* extract the next path component */
620 if (ip->iconic_path.directory_shown[0] == '\0')
624 path = ip->iconic_path.directory_shown;
625 name = strrchr(path, '/') + 1;
628 /* don't show path components above a restricted directory */
629 path_len = strlen(path);
630 if (restricted_len && path_len <= restricted_len)
633 /* in restricted mode: check if this component is above $HOME */
634 forbidden = restrictMode
635 && strncmp(path, users_home_dir, path_len) == 0
637 users_home_dir[path_len] == '/' &&
638 users_home_dir[path_len + 1] != '\0');
640 /* check if we need to add or update the path component */
641 if (i >= ip->iconic_path.num_components)
643 /* create new component */
646 ip->iconic_path.components = (struct _IconicPathComponent *)
647 XtRealloc((char *)ip->iconic_path.components,
648 (i + 1)*sizeof(struct _IconicPathComponent));
650 ip->iconic_path.components[i].path = XtNewString(path);
651 pixmapData = GetPixmapData(file_mgr_rec,
654 ip->iconic_path.large_icons);
657 XtSetArg (args[n], XmNstring, NULL); n++;
660 XtSetArg (args[n], XmNimageName, pixmapData->iconFileName);
661 ip->iconic_path.components[i].icon_name =
662 XtNewString(pixmapData->iconFileName);
666 XtSetArg (args[n], XmNimageName, NULL);
667 ip->iconic_path.components[i].icon_name = NULL;
672 if ( background == white_pixel )
674 XtSetArg (args[n], XmNbackground, white_pixel); n++;
675 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
676 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
678 else if ( background == black_pixel )
680 XtSetArg (args[n], XmNbackground, black_pixel); n++;
681 XtSetArg (args[n], XmNpixmapBackground, white_pixel); n++;
682 XtSetArg (args[n], XmNpixmapForeground, black_pixel); n++;
686 XtSetArg (args[n], XmNbackground, background); n++;
690 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
691 XtSetArg (args[n], XmNmarginHeight, 0); n++;
692 XtSetArg (args[n], XmNmarginWidth, 0); n++;
693 XtSetArg (args[n], XmNtraversalOn, False); n++;
694 ip->iconic_path.components[i].icon =
695 _DtCreateIcon ((Widget)ip, "iconic_path_icon", args, n);
697 _DtCheckAndFreePixmapData(
698 GetDirectoryLogicalType(file_mgr_data, path),
700 (DtIconGadget) ip->iconic_path.components[i].icon,
703 XtAddCallback (ip->iconic_path.components[i].icon, XmNcallback,
706 if (fileLabel = DtDtsDataTypeToAttributeValue(
707 GetDirectoryLogicalType(file_mgr_data, path),
711 xm_string = XmStringCreateLocalized(fileLabel);
712 DtDtsFreeAttributeValue(fileLabel);
716 xm_string = XmStringCreateLocalized(name);
720 XtSetArg (args[n], XmNlabelString, xm_string); n++;
721 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
722 XtSetArg (args[n], XmNmarginHeight, 0); n++;
723 XtSetArg (args[n], XmNhighlightThickness, 0); n++;
724 if (ip->iconic_path.buttons)
726 XtSetArg (args[n], XmNshadowThickness, 1); n++;
727 XtSetArg (args[n], XmNtraversalOn, False); n++;
728 XtSetArg (args[n], XmNsensitive, !forbidden); n++;
729 ip->iconic_path.components[i].button =
730 XmCreatePushButtonGadget ((Widget)ip, "iconic_path_button",
732 XtAddCallback(ip->iconic_path.components[i].button,
733 XmNactivateCallback, ButtonCallback, ip);
737 ip->iconic_path.components[i].button =
738 XmCreateLabelGadget((Widget)ip, "iconic_path_label", args, n);
740 XmStringFree(xm_string);
745 /* check if the existing component needs to be updated */
747 /* check if the path has changed */
748 if (strcmp(ip->iconic_path.components[i].path, path) != 0 ||
749 ip->iconic_path.large_shown != ip->iconic_path.large_icons)
753 XtFree(ip->iconic_path.components[i].path);
754 ip->iconic_path.components[i].path = XtNewString(path);
757 if (fileLabel = DtDtsDataTypeToAttributeValue(
758 GetDirectoryLogicalType(file_mgr_data, path),
762 xm_string = XmStringCreateLocalized(fileLabel);
763 DtDtsFreeAttributeValue(fileLabel);
767 xm_string = XmStringCreateLocalized(name);
769 XtSetArg (args[0], XmNlabelString, xm_string);
770 XtSetArg (args[1], XmNsensitive, !forbidden);
771 XtSetValues(ip->iconic_path.components[i].button, args, 2);
772 XmStringFree(xm_string);
774 /* check if the icon has changed */
775 pixmapData = GetPixmapData(file_mgr_rec,
778 ip->iconic_path.large_icons);
782 if ((pixmapData->iconFileName == NULL) !=
783 (ip->iconic_path.components[i].icon_name == NULL) ||
784 pixmapData->iconFileName != NULL &&
785 strcmp(pixmapData->iconFileName,
786 ip->iconic_path.components[i].icon_name) != 0)
790 XtFree(ip->iconic_path.components[i].icon_name);
791 ip->iconic_path.components[i].icon_name =
792 XtNewString(pixmapData->iconFileName);
794 XtSetArg (args[0], XmNimageName, pixmapData->iconFileName);
795 XtSetValues(ip->iconic_path.components[i].icon, args, 1);
797 _DtCheckAndFreePixmapData(
798 GetDirectoryLogicalType(file_mgr_data, path),
800 (DtIconGadget) ip->iconic_path.components[i].icon,
806 XtFree(ip->iconic_path.components[i].icon_name);
807 ip->iconic_path.components[i].icon_name = NULL;
808 XtSetArg (args[0], XmNimageName, NULL);
809 XtSetValues(ip->iconic_path.components[i].icon, args, 1);
813 /* update component count */
817 /* go to the next path component */
824 /* find next component */
825 if (strcmp(ptr, "/") == 0)
827 ptr = DtStrchr(ptr + 1, '/');
830 /* free any leftover components */
831 for (j = i; j < ip->iconic_path.num_components; j++)
835 XtFree(ip->iconic_path.components[j].path);
836 ip->iconic_path.components[j].path = NULL;
837 XtFree(ip->iconic_path.components[j].icon_name);
838 ip->iconic_path.components[j].icon_name = NULL;
839 XtDestroyWidget(ip->iconic_path.components[j].icon);
840 XtDestroyWidget(ip->iconic_path.components[j].button);
843 ip->iconic_path.num_components = i;
844 ip->iconic_path.large_shown = ip->iconic_path.large_icons;
847 /* update component widths */
848 for (i = 0; i < ip->iconic_path.num_components; i++)
850 /* determine width for this component */
852 if (ip->iconic_path.components[i].icon->core.width > (Dimension)twidth)
853 twidth = ip->iconic_path.components[i].icon->core.width;
854 if (ip->iconic_path.components[i].button->core.width > (Dimension)twidth)
855 twidth = ip->iconic_path.components[i].button->core.width;
857 if (ip->iconic_path.components[i].button->core.width < (Dimension)twidth)
859 /* increment the change count */
863 XmeConfigureObject(ip->iconic_path.components[i].button,
864 ip->iconic_path.components[i].button->core.x,
865 ip->iconic_path.components[i].button->core.y,
867 ip->iconic_path.components[i].button->core.height,
871 ip->iconic_path.components[i].width = twidth;
874 /* update the status message */
875 if (file_mgr_data && ip->iconic_path.status_msg)
876 GetStatusMsg(file_mgr_data, msg_buf);
880 if (ip->iconic_path.msg_text == NULL ||
881 strcmp(msg_buf, ip->iconic_path.msg_text) != 0)
883 /* remember the new status message text */
884 XtFree(ip->iconic_path.msg_text);
885 ip->iconic_path.msg_text = XtNewString(msg_buf);
887 if (ip->iconic_path.status_label)
889 /* clear the area under the old status message text */
890 if (XtIsRealized((Widget)ip) &&
891 ip->iconic_path.status_label->core.x > 0)
892 XClearArea(XtDisplay(ip), XtWindow(ip),
893 ip->iconic_path.status_label->core.x,
894 ip->iconic_path.status_label->core.y,
895 ip->iconic_path.status_label->core.width,
896 ip->iconic_path.status_label->core.height, False);
898 /* set a new status message text */
899 xm_string = XmStringCreateLocalized(msg_buf);
900 XtSetArg (args[0], XmNlabelString, xm_string);
901 XtSetValues(ip->iconic_path.status_label, args, 1);
902 XmStringFree(xm_string);
906 /* set widget size, if necessary */
907 if (ip->core.width == 0)
908 ip->core.width = DESIRED_WIDTH(ip);
909 if (ip->core.height == 0)
910 ip->core.height = DESIRED_HEIGHT(ip);
912 /* for the layout: check how much of the path will fit */
913 twidth = MWD(ip) + ip->iconic_path.dotdot_button->core.width + MWD(ip);
914 if (ip->iconic_path.status_msg && ip->iconic_path.dropzone)
916 if (ip->iconic_path.status_label->core.width
917 >= ip->iconic_path.dropzone_icon->core.width)
918 twidth += ip->iconic_path.status_label->core.width + MWD(ip);
920 twidth += ip->iconic_path.dropzone_icon->core.width + MWD(ip);
922 else if (ip->iconic_path.status_msg)
923 twidth += ip->iconic_path.status_label->core.width + MWD(ip);
924 else if (ip->iconic_path.dropzone)
925 twidth += ip->iconic_path.dropzone_icon->core.width + MWD(ip);
928 for (i = ip->iconic_path.num_components; i > 0; i--)
930 twidth += SPC(ip) + ip->iconic_path.components[i - 1].width;
931 if ((Dimension)twidth > ip->core.width)
935 if (i == 1 && (Dimension)(twidth - ip->iconic_path.dotdot_button->core.width - SPC(ip))
941 if (i != ip->iconic_path.left_component)
944 ip->iconic_path.left_component = i;
947 /* allocate list of to-be-managed children */
949 XtMalloc((2*(ip->iconic_path.num_components - i) + 2)*sizeof(Widget));
952 /* position & manage the path components */
954 y = ip->core.height - MHT(ip) - ip->iconic_path.dotdot_button->core.height
959 MOVE_OBJECT(ip->iconic_path.dotdot_button, x, y + SPC(ip));
960 manage[nmanage++] = ip->iconic_path.dotdot_button;
961 x += ip->iconic_path.dotdot_button->core.width + SPC(ip);
964 for (j = i; j < ip->iconic_path.num_components; j++)
966 MOVE_OBJECT(ip->iconic_path.components[j].icon,
968 y - ip->iconic_path.components[j].icon->core.height);
969 MOVE_OBJECT(ip->iconic_path.components[j].button, x, y + SPC(ip));
971 x += ip->iconic_path.components[j].width + SPC(ip);
973 manage[nmanage++] = ip->iconic_path.components[j].icon;
974 manage[nmanage++] = ip->iconic_path.components[j].button;
977 /* position & manage the status message label */
978 if (ip->iconic_path.status_msg)
980 x = ip->core.width - MWD(ip) -
981 (int)ip->iconic_path.status_label->core.width;
984 y = ip->core.height - MHT(ip) -
985 (int)ip->iconic_path.status_label->core.height;
989 if (ip->iconic_path.status_label->core.x != x ||
990 ip->iconic_path.status_label->core.y != y)
992 XmeConfigureObject(ip->iconic_path.status_label, x, y,
993 ip->iconic_path.status_label->core.width,
994 ip->iconic_path.status_label->core.height,
995 ip->iconic_path.status_label->core.border_width);
998 manage[nmanage++] = ip->iconic_path.status_label;
1003 y = ip->core.height;
1005 /* position & manage the drop zone icon */
1006 if (ip->iconic_path.dropzone)
1008 x = ip->core.width - MWD(ip) -
1009 (int)ip->iconic_path.dropzone_icon->core.width;
1012 y = (y - (int)ip->iconic_path.dropzone_icon->core.height + 1)/2;
1016 MOVE_OBJECT(ip->iconic_path.dropzone_icon, x, y);
1018 manage[nmanage++] = ip->iconic_path.dropzone_icon;
1022 /* if all icons are there, manage the children */
1023 for (i = 0; i < ip->iconic_path.num_components; i++)
1024 if (ip->iconic_path.components[i].icon_name == NULL)
1026 if (file_mgr_data != NULL && i == ip->iconic_path.num_components)
1028 DPRINTF2(("IconicPath.Update: manage %d children\n", nmanage));
1029 XtManageChildren(manage, nmanage);
1031 XtFree((char *)manage);
1033 /* reset icons_changed flag */
1034 ip->iconic_path.icons_changed = False;
1040 /*--------------------------------------------------------------------
1041 * Iconic path redraw function
1042 *------------------------------------------------------------------*/
1046 DtIconicPathWidget ip)
1048 FileMgrRec *file_mgr_rec = (FileMgrRec *)ip->iconic_path.file_mgr_rec;
1049 DialogData * dialog_data;
1050 FileMgrData *file_mgr_data;
1054 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1056 file_mgr_data = (FileMgrData *) dialog_data->data;
1058 if (ip->iconic_path.gc == None)
1060 XGCValues gc_values;
1062 gc_values.foreground = ip->manager.foreground;
1063 gc_values.line_width = 2;
1065 ip->iconic_path.gc = XCreateGC(XtDisplay(ip), XtWindow(ip),
1066 GCForeground | GCLineWidth, &gc_values);
1070 y = ip->core.height - MHT(ip) - ip->iconic_path.dotdot_button->core.height
1071 - SPC(ip) - ICON_HT(ip)/2;
1073 if (ip->iconic_path.left_component > 0)
1075 XSetLineAttributes(XtDisplay(ip), ip->iconic_path.gc,
1076 2, LineOnOffDash, CapNotLast, JoinMiter);
1077 XSetDashes(XtDisplay(ip), ip->iconic_path.gc, 0, "\04", 1);
1079 l = ip->iconic_path.dotdot_button->core.width + SPC(ip) - 3;
1081 XDrawLine(XtDisplay(ip), XtWindow(ip), ip->iconic_path.gc,
1082 x + 2 + l, y, x + 2, y);
1083 x += ip->iconic_path.dotdot_button->core.width + SPC(ip);
1084 XSetLineAttributes(XtDisplay(ip), ip->iconic_path.gc,
1085 2, LineSolid, CapNotLast, JoinMiter);
1088 for (i = ip->iconic_path.left_component;
1089 i < ip->iconic_path.num_components - 1;
1092 if (ip->iconic_path.components[i].icon_name != NULL &&
1093 ip->iconic_path.components[i+1].icon_name != NULL)
1095 XDrawLine(XtDisplay(ip), XtWindow(ip), ip->iconic_path.gc,
1097 ip->iconic_path.components[i].icon->core.width + 1,
1100 ip->iconic_path.components[i].width + SPC(ip) - 1,
1103 x += ip->iconic_path.components[i].width + SPC(ip);
1109 /*--------------------------------------------------------------------
1111 *------------------------------------------------------------------*/
1114 ClassInitialize( void )
1116 baseClassExtRec.record_type = XmQmotif ;
1121 ClassPartInitialize(
1122 WidgetClass w_class )
1124 _XmFastSubclassInit( w_class, XmDRAWING_AREA_BIT) ;
1129 /*--------------------------------------------------------------------
1130 * Instance initialize
1131 *------------------------------------------------------------------*/
1138 Cardinal *num_args )
1140 DtIconicPathWidget new_w = (DtIconicPathWidget) nw ;
1141 FileMgrRec *file_mgr_rec = (FileMgrRec *)new_w->iconic_path.file_mgr_rec;
1143 new_w->iconic_path.msg_text = NULL;
1144 new_w->iconic_path.current_directory = NULL;
1145 new_w->iconic_path.directory_shown = NULL;
1146 new_w->iconic_path.large_shown = False;
1147 new_w->iconic_path.status_label = NULL;
1148 new_w->iconic_path.dotdot_button = NULL;
1149 new_w->iconic_path.dropzone_icon = NULL;
1150 new_w->iconic_path.num_components = 0;
1151 new_w->iconic_path.components = NULL;
1152 new_w->iconic_path.left_component = 0;
1153 new_w->iconic_path.gc = None;
1155 Update(new_w, file_mgr_rec, NULL);
1161 /*--------------------------------------------------------------------
1163 *------------------------------------------------------------------*/
1169 DtIconicPathWidget ip = (DtIconicPathWidget) w;
1173 XtFree(ip->iconic_path.current_directory);
1175 ip->iconic_path.current_directory = NULL;
1176 XtFree(ip->iconic_path.msg_text);
1177 ip->iconic_path.msg_text = NULL;
1178 XtFree(ip->iconic_path.directory_shown);
1179 ip->iconic_path.directory_shown = NULL;
1181 for (i = 0; i < ip->iconic_path.num_components; i++)
1183 XtFree(ip->iconic_path.components[i].path);
1184 ip->iconic_path.components[i].path = NULL;
1187 XtFree((char *)ip->iconic_path.components);
1188 ip->iconic_path.components = NULL;
1194 /*--------------------------------------------------------------------
1195 * General redisplay function called on exposure events
1196 *------------------------------------------------------------------*/
1204 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1206 IconicPathRedraw (ip);
1208 XmeRedisplayGadgets( (Widget) ip, event, region);
1213 /*--------------------------------------------------------------------
1215 *------------------------------------------------------------------*/
1221 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1222 FileMgrRec *file_mgr_rec = (FileMgrRec *)ip->iconic_path.file_mgr_rec;
1223 DialogData *dialog_data;
1224 FileMgrData *file_mgr_data;
1226 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1228 file_mgr_data = (FileMgrData *) dialog_data->data;
1230 Update(ip, file_mgr_rec, file_mgr_data);
1236 /*--------------------------------------------------------------------
1238 *------------------------------------------------------------------*/
1240 static XtGeometryResult
1243 XtWidgetGeometry *request,
1244 XtWidgetGeometry *reply )
1246 DtIconicPathWidget ip;
1248 ip = (DtIconicPathWidget) w->core.parent;
1250 if (IsQueryOnly(request)) return XtGeometryYes;
1252 if (IsWidth(request)) w->core.width = request->width;
1253 if (IsHeight(request)) w->core.height = request->height;
1254 if (IsBorder(request)) w->core.border_width = request->border_width;
1256 /* @@@ adjust layout ? */
1258 return XtGeometryYes;
1262 /*--------------------------------------------------------------------
1263 * Re-layout children
1264 *------------------------------------------------------------------*/
1270 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1271 XtWidgetProc manager ;
1273 XmeNavigChangeManaged((Widget) ip) ;
1279 /*--------------------------------------------------------------------
1281 *------------------------------------------------------------------*/
1289 Cardinal *num_args )
1291 DtIconicPathWidget current = (DtIconicPathWidget) cw ;
1292 DtIconicPathWidget ip = (DtIconicPathWidget) nw ;
1293 FileMgrRec *file_mgr_rec = (FileMgrRec *)ip->iconic_path.file_mgr_rec;
1294 DialogData *dialog_data;
1295 FileMgrData *file_mgr_data;
1298 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1299 file_mgr_data = dialog_data? (FileMgrData *) dialog_data->data: NULL;
1301 redisplay = (Update(ip, file_mgr_rec, file_mgr_data) > 0);
1303 if (XtHeight(ip) != DESIRED_HEIGHT(ip)
1304 || (Dimension)XtWidth(ip) < (Dimension)DESIRED_WIDTH(ip))
1306 XtWidgetGeometry request;
1307 XtWidgetGeometry reply;
1309 request.request_mode = 0;
1310 if (XtHeight(ip) != DESIRED_HEIGHT(ip))
1312 request.request_mode |= CWHeight;
1313 request.height = DESIRED_HEIGHT(ip);
1315 if ((Dimension)XtWidth(ip) < (Dimension)DESIRED_WIDTH(ip))
1317 request.request_mode |= CWWidth;
1318 request.width = DESIRED_WIDTH(ip);
1321 if (XtMakeGeometryRequest(nw, &request, &reply) != XtGeometryNo)
1322 Update(ip, file_mgr_rec, file_mgr_data);
1331 /*--------------------------------------------------------------------
1333 *------------------------------------------------------------------*/
1335 static XtGeometryResult
1338 XtWidgetGeometry *intended,
1339 XtWidgetGeometry *desired )
1341 DtIconicPathWidget ip = (DtIconicPathWidget) wid ;
1343 desired->width = DESIRED_WIDTH(ip);
1344 desired->height = DESIRED_HEIGHT(ip);
1346 /* deal with user initial size setting */
1347 if (!XtIsRealized(wid))
1349 if (XtWidth(wid) != 0) desired->width = XtWidth(wid) ;
1350 if (XtHeight(wid) != 0) desired->height = XtHeight(wid) ;
1353 return XmeReplyToQueryGeometry(wid, intended, desired) ;
1356 static XmNavigability
1360 if( wid->core.sensitive
1361 && wid->core.ancestor_sensitive
1362 && ((XmManagerWidget) wid)->manager.traversal_on )
1364 XmNavigationType nav_type
1365 = ((XmManagerWidget) wid)->manager.navigation_type ;
1367 if( (nav_type == XmSTICKY_TAB_GROUP)
1368 || (nav_type == XmEXCLUSIVE_TAB_GROUP)
1369 || ( (nav_type == XmTAB_GROUP)
1370 && !_XmShellIsExclusive( wid)) )
1372 return XmDESCENDANTS_TAB_NAVIGABLE ;
1375 return XmNOT_NAVIGABLE ;
1379 /*--------------------------------------------------------------------
1380 * _DtCreateIconicPath: creates and returns a IconicPath widget.
1381 *------------------------------------------------------------------*/
1384 _DtCreateIconicPath(
1390 return( XtCreateWidget( name, dtIconicPathWidgetClass, p, args, n)) ;
1394 /*--------------------------------------------------------------------
1395 * UpdateIconicPath: update IconicPath widget.
1396 *------------------------------------------------------------------*/
1400 FileMgrRec *file_mgr_rec,
1401 FileMgrData *file_mgr_data,
1402 Boolean icons_changed)
1406 XtSetArg (args[0], DtNfileMgrRec, file_mgr_rec);
1407 XtSetArg (args[1], DtNcurrentDirectory, file_mgr_data->current_directory);
1408 XtSetArg (args[2], DtNlargeIcons, file_mgr_data->view == BY_NAME_AND_ICON);
1409 XtSetArg (args[3], DtNiconsChanged, icons_changed);
1410 XtSetArg (args[4], "statusMsg", !file_mgr_data->show_status_line);
1411 XtSetValues(file_mgr_rec->iconic_path_da, args, 5);