1 /* $TOG: ChangeDirP.c /main/8 1998/04/01 15:05:07 rafi $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 * COMPONENT_NAME: Desktop File Manager (dtfile)
9 * Description: Processing functions for the change directory display
10 * line and the current directory dialog.
13 * CheckCurrentDirectorySelect
16 * CurrentDirDropCallback
18 * CurrentDirIconCallback
20 * CurrentDirectoryIconMotion
21 * DrawCurrentDirectory
31 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
32 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
33 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
34 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
36 ****************************************************************************
37 ************************************<+>*************************************/
42 #include <Xm/TextFP.h>
43 #include <Xm/PushBG.h>
44 #include <Xm/DragDrop.h>
47 #include <Dt/DtNlUtils.h>
48 #include <Dt/Connect.h>
51 #include "SharedProcs.h"
56 #include "ChangeDir.h"
60 /******** Static Function Declarations ********/
62 static void CurrentDirChange(
63 XtPointer client_data,
64 DialogData *old_dialog_data,
65 DialogData *new_dialog_data,
66 XtPointer call_data) ;
67 static void CurrentDirClose(
68 XtPointer client_data,
69 DialogData *old_dialog_data,
70 DialogData *new_dialog_data) ;
71 static void CheckCurrentDirectorySelect(
72 FileMgrData *file_mgr_data ) ;
73 static void TimerEvent(
74 XtPointer client_data,
76 static void ResizeFastText(
77 FileMgrRec *file_mgr_rec,
78 FileMgrData *file_mgr_data,
80 static int get_textwidth(
84 static void draw_imagestring(
93 /******** End Static Function Declarations ********/
95 /* absolute value macro */
97 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
100 /* layout constants */
101 #define CUR_DIR_SPACING 5
104 /* local global varible to determine whether the user has double clicked
106 static Boolean doubleClick = False;
108 /*--------------------------------------------------------------------
111 * Given a width available for the current directory text,
112 * determines the text to be drawn in one of three formats:
114 * /path (non-restricted directory)
115 * /.../path (restricted directory)
116 * .../subpath (if the full path wouldn't fit)
118 * Returns the length (in chars) and width (in pixels) of each of
119 * the two components of the text:
120 * (1) prefix "/..." or "...", and (2) path or subpath.
121 * Returns True if the path was chopped because it wouldn't fit.
123 *------------------------------------------------------------------*/
127 FileMgrData *file_mgr_data,
133 int *prefix_pixels_p,
137 Boolean chopped = False;
143 char *next_part = NULL;
145 *host_len_p = *host_pixels_p = 0;
147 /* if restricted directory, path prefix is "/..." */
148 if (file_mgr_data->restricted_directory)
151 prefix_len = strlen("/...");
152 prefix_pixels = get_textwidth (file_mgr_data, "/...", prefix_len);
153 path_begin = file_mgr_data->current_directory +
154 strlen(file_mgr_data->restricted_directory);
155 if (*path_begin == '\0')
157 else if (*path_begin != '/')
165 path_begin = file_mgr_data->current_directory;
168 /* calculate path length & width */
169 path_len = strlen(path_begin);
170 path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
172 /* if whole path doesn't fit, we need to chop off pieces until it does */
173 if (prefix_pixels + path_pixels > width)
177 /* change the path prefix */
179 prefix_len = strlen("...");
180 prefix_pixels = get_textwidth (file_mgr_data, "...", prefix_len);
184 /* chop off the next piece (everything up to the next '/') */
186 next_part = DtStrchr(path_begin + 1, '/');
187 if (next_part == NULL)
189 /* Got here only when the last directory is still too
195 /* calculate new path length */
196 path_begin = next_part;
197 path_len = strlen(path_begin);
198 path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
200 /* keep going until it fits */
201 } while (prefix_pixels + path_pixels > width);
204 /* add the path to the buffer */
205 if( NULL == next_part )
207 /* Got here only when the last directory is still too
215 /* Going back one character at a time to see if it fit
217 path_pixels = get_textwidth( file_mgr_data, path_begin, len );
218 if( prefix_pixels + path_pixels < width )
227 buf[prefix_len] = 0x0;
233 strncpy (buf + prefix_len, path_begin, len);
235 *path_pixels_p = path_pixels;
240 strcpy (buf + prefix_len, path_begin);
241 *path_len_p = path_len;
242 *path_pixels_p = path_pixels;
246 *prefix_len_p = prefix_len;
247 *prefix_pixels_p = prefix_pixels;
252 /************************************************************************
254 * ShowChangeDirDialog
255 * Callback functions invoked from the Change Directory... menu
256 * item. This function displays the change directory dialog.
258 ************************************************************************/
264 XtPointer client_data,
267 FileMgrRec * file_mgr_rec;
268 DialogData * dialog_data;
269 FileMgrData * file_mgr_data;
270 ChangeDirData * change_dir_data;
271 ChangeDirRec * change_dir_rec;
274 char *tempStr, *tmpStr;
277 /* Set the menu item to insensitive to prevent multiple */
278 /* dialogs from being posted and get the area under the */
279 /* menu pane redrawn. */
283 if((int)client_data == FM_POPUP)
286 mbar = (Widget) XmGetPostedFromWidget(XtParent(w));
289 XtSetArg(args[0], XmNuserData, &file_mgr_rec);
290 XtGetValues(mbar, args, 1);
292 /* Ignore accelerators when we're insensitive */
293 if ((file_mgr_rec->menuStates & CHANGEDIR) == 0)
295 XSetInputFocus(XtDisplay(w),
296 XtWindow(file_mgr_rec->change_directoryBtn_child),
297 RevertToParent, CurrentTime);
303 /* Done only during a restore session */
304 file_mgr_rec = (FileMgrRec *)client_data;
307 /* Got an accelerator after we were unposted */
308 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
311 file_mgr_data = (FileMgrData *) dialog_data->data;
312 change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
313 change_dir_data->file_mgr_rec = (XtPointer) file_mgr_rec;
315 file_mgr_rec->menuStates &= ~CHANGEDIR;
317 _DtShowDialog (file_mgr_rec->shell, (Widget)NULL, (XtPointer)file_mgr_rec,
318 file_mgr_data->change_dir,
319 CurrentDirChange, (XtPointer)file_mgr_rec,
320 CurrentDirClose, (XtPointer)file_mgr_rec, (char *)NULL,
321 False, False, (char *)NULL, (XClassHint *)NULL);
323 /* Save a ptr to file_mgr_rec in the find dialogs structure */
324 change_dir_rec = (ChangeDirRec *)_DtGetDialogInstance(
325 file_mgr_data->change_dir);
327 if(file_mgr_data->title != NULL &&
328 strcmp(file_mgr_data->helpVol, DTFILE_HELP_NAME) != 0)
330 tmpStr = GETMESSAGE(2,15, "Go To");
331 tempStr = (char *)XtMalloc(strlen(tmpStr) +
332 strlen(file_mgr_data->title) + 5);
333 sprintf(tempStr, "%s - %s", file_mgr_data->title, tmpStr);
337 tmpStr = (GETMESSAGE(2,17, "File Manager - Go To"));
338 tempStr = XtNewString(tmpStr);
340 XtSetArg (args[0], XmNtitle, tempStr);
341 XtSetValues (XtParent (change_dir_rec->change_dir), args, 1);
344 file_mgr_rec->change_directoryBtn_child=XtParent (change_dir_rec->change_dir);
350 /************************************************************************
353 * When a Button1 selection occurs on the current directory line,
354 * see if it occurred within the directory path, highlight the
355 * selected sub-path, or if the sub-path was already highlighted,
356 * set the current directory to the path and dehighlight.
358 ************************************************************************/
363 XtPointer client_data,
364 XtPointer call_data )
366 FileMgrRec *file_mgr_rec = (FileMgrRec *) client_data;
367 DialogData *dialog_data;
368 FileMgrData *file_mgr_data;
369 char buf[2*MAX_PATH];
370 char host_name[MAX_PATH];
379 XmDrawnButtonCallbackStruct *button_data;
381 Dimension width, highlight, shadow, margin;
392 static XtIntervalId TimerId;
394 /* if doubleClick is true than we have a double click so we want
395 * to change to the new directory that the user double clicked on
398 XtRemoveTimeOut(TimerId);
400 button_data = (XmDrawnButtonCallbackStruct *) call_data;
401 event = (XButtonEvent *) button_data->event;
403 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
404 file_mgr_data = (FileMgrData *) dialog_data->data;
406 /* Get layout values */
407 XtSetArg (args[0], XmNwidth, &width);
408 XtSetArg (args[1], XmNhighlightThickness, &highlight);
409 XtGetValues (w, args, 2);
410 XtSetArg (args[0], XmNshadowThickness, &shadow);
411 XtSetArg (args[1], XmNmarginWidth, &margin);
412 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
413 left_margin = highlight + shadow + margin;
415 /* Get the starting and ending locations of the current */
416 /* directory text. */
417 chopped = get_text_pieces(file_mgr_data, width - 2*left_margin,
418 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
419 &path_len, &path_pixels);
421 begin_x = left_margin;
422 end_x = begin_x + host_pixels + prefix_pixels + path_pixels;
424 /* Get the selected path */
425 if (event->x < begin_x || event->x >= end_x)
427 /* click outside the directory text: nothing selected */
430 else if (event->x < begin_x + host_pixels ||
431 event->x < begin_x + host_pixels + prefix_pixels && !chopped)
433 /* click on host name or "/..." prefix: root selected */
434 if (file_mgr_data->restricted_directory)
435 new_select = XtNewString(file_mgr_data->restricted_directory);
437 new_select = XtNewString("/");
439 else if (event->x < begin_x + host_pixels + prefix_pixels && chopped)
441 /* click on "..." prefix: directory above the visible piece selected */
442 len = strlen(file_mgr_data->current_directory) - path_len;
443 new_select = (char *) XtMalloc(len + 1);
444 memcpy(new_select, file_mgr_data->current_directory, len);
447 else /* event->x >= begin_x + host_pixels + prefix_pixels */
449 /* click on the path: determine which subdirectory selected */
450 begin_x += host_pixels + prefix_pixels;
451 i = host_len + prefix_len;
452 swidth = get_textwidth(file_mgr_data, "/", strlen("/")) / 2;
454 while (begin_x - swidth < event->x)
456 /* find next '/' in path */
457 ptr = DtStrchr(buf + i, '/');
460 i = host_len + prefix_len + path_len + 1;
464 /* get x-position of next path component */
465 len = ((ptr + 1) - buf) - i;
466 begin_x += get_textwidth(file_mgr_data, buf + i, len);
470 /* if we have a restricted diretory and i == 5 ("/.../") then we want
471 the len to be the restricted directory */
472 if (file_mgr_data->restricted_directory && i == 5)
473 len = strlen(file_mgr_data->restricted_directory);
475 len = strlen(file_mgr_data->current_directory)
476 - (host_len + prefix_len + path_len - i) - 1;
477 new_select = (char *) XtMalloc(len + 1);
479 strcpy(new_select, "/");
482 memcpy(new_select, file_mgr_data->current_directory, len);
487 /* in restricted mode, don't allow going above the user's home dir */
488 if (new_select != NULL && restrictMode)
490 /* check if new_select is the same as or a subdirectory of $HOME */
491 len = strlen(users_home_dir);
492 if (strncmp(new_select, users_home_dir, len) != 0
493 || new_select[len] != '\0' && new_select[len] != '/')
495 /* change new_select to $HOME */
497 new_select = XtNewString(users_home_dir);
502 /* If the path is the same as what is already selected, */
503 /* free cd_select, set the directory to the selected */
504 /* directory, redraw the directory display. */
506 /* If the path was different, set cd_select to the */
507 /* selected directory and redraw the directory. */
509 if (new_select != NULL && file_mgr_data->cd_select != NULL &&
510 strcmp(new_select, file_mgr_data->cd_select) == 0)
512 XtFree (file_mgr_data->cd_select);
513 file_mgr_data->cd_select = NULL;
515 strcpy(buf, new_select);
516 strcpy(host_name, file_mgr_data->host);
518 if (strcmp (buf, file_mgr_data->current_directory) == 0)
519 FileMgrReread (file_mgr_rec);
521 ShowNewDirectory (file_mgr_data, host_name, buf);
527 XtFree (file_mgr_data->cd_select);
528 file_mgr_data->cd_select = new_select;
534 DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
539 TimerId = XtAppAddTimeOut (XtWidgetToApplicationContext (w),
540 XtGetMultiClickTime(XtDisplay(w)),
541 (XtTimerCallbackProc) TimerEvent,
542 (XtPointer) file_mgr_rec);
548 /************************************************************************
550 * CurrentDirDropCallback
551 * Callback function invoked upon an action on the change view drop.
553 ************************************************************************/
556 CurrentDirDropCallback(
558 XtPointer client_data,
559 XtPointer call_data )
561 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
562 XmAnyCallbackStruct * callback;
563 DialogData * dialog_data;
564 FileMgrData * file_mgr_data;
565 char host_name[MAX_PATH];
567 callback = (XmAnyCallbackStruct *) call_data;
568 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
569 file_mgr_data = (FileMgrData *) dialog_data->data;
571 if (callback->reason == XmCR_DEFAULT_ACTION)
573 strcpy(host_name, file_mgr_data->host);
574 ShowNewDirectory (file_mgr_data, host_name,
575 _DtPName (file_mgr_data->current_directory));
580 /************************************************************************
582 * CurrentDirIconCallback
583 * Callback function invoked upon an action occuring on an icon.
585 ************************************************************************/
588 CurrentDirIconCallback(
590 XtPointer client_data,
591 XtPointer call_data )
593 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
594 XmAnyCallbackStruct * callback;
595 XButtonEvent * event;
596 DialogData * dialog_data;
597 FileMgrData * file_mgr_data;
599 callback = (XmAnyCallbackStruct *) call_data;
600 event = (XButtonEvent *) callback->event;
601 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
602 file_mgr_data = (FileMgrData *) dialog_data->data;
604 if (callback->reason == XmCR_DRAG)
606 /* Do nothing if a Button 1 drag is already ramping up */
610 /* Save starting X and Y, for threshold detection */
611 initialDragX = event->x;
612 initialDragY = event->y;
614 /* Flag that a Button 2 drag is ramping up */
615 B2DragPossible = True;
617 UnpostTextField(file_mgr_data);
619 else if (callback->reason == XmCR_ARM)
621 /* Do nothing if a Button 2 drag is already ramping up */
625 /* Save starting X and Y, for threshold detection */
626 initialDragX = event->x;
627 initialDragY = event->y;
629 /* Flag that a Button 1 drag is ramping up */
630 B1DragPossible = True;
632 /* but since we're in the current directory icon we don't want to
633 process on the button up */
634 ProcessBtnUpCD = False;
636 UnpostTextField(file_mgr_data);
638 else if (callback->reason == XmCR_DEFAULT_ACTION)
640 /* We now know that a drag operation won't be starting up */
641 B1DragPossible = False;
642 B2DragPossible = False;
644 UnpostTextField(file_mgr_data);
646 /* Default action is to reread the directory */
647 FileMgrReread (file_mgr_rec);
649 else if ((callback->reason == XmCR_SELECT) ||
650 (callback->reason == XmCR_DISARM) ||
651 (callback->reason == XmCR_DROP))
653 /* We now know that a drag operation won't be starting up */
654 B1DragPossible = False;
655 B2DragPossible = False;
661 * This function processes motion events anytime a B1 or B2 drag operation
662 * has the potential of starting. When the drag threshold is surpassed,
663 * a drag operation will be started.
667 CurrentDirectoryIconMotion(
669 XtPointer client_data,
673 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
674 DialogData * dialog_data;
675 FileMgrData * file_mgr_data;
684 if ((B1DragPossible && (event->xmotion.state & Button1Mask)) ||
685 (B2DragPossible && (event->xmotion.state & Button2Mask)))
687 /* Have we passed the drag threshold? */
688 diffX = initialDragX - event->xmotion.x;
689 diffY = initialDragY - event->xmotion.y;
691 if ((ABS(diffX) >= dragThreshold) || (ABS(diffY) >= dragThreshold))
693 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
694 file_mgr_data = (FileMgrData *) dialog_data->data;
696 initiating_view = (XtPointer) file_mgr_data;
697 dirIcon = file_mgr_rec->current_directory_icon;
698 StartDrag(dirIcon, NULL, event);
704 /************************************************************************
707 * Callback functions invoked from the current directory display
708 * drawn button. This function extracts some structures and calls
709 * the directory display function.
711 ************************************************************************/
716 XtPointer client_data,
717 XtPointer call_data )
719 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
720 DialogData * dialog_data;
721 FileMgrData * file_mgr_data;
723 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
725 /* Check to see if the view has been closed */
727 if (dialog_data == NULL) return;
729 file_mgr_data = (FileMgrData *) dialog_data->data;
731 if (file_mgr_data->cd_normal_gc != 0)
732 DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
738 /************************************************************************
741 * Construct the status message (normally "x Items, y Hidden").
742 * Returns True if the message is deemed "important".
744 * @@@ Note 2/17/95: messages below containing "Item(s)" should really
745 * be just "Item", but the message catalog is frozen at this time, so
746 * we can't fix this now. (In practice, it doesn't matter, because
747 * the item count should always be > 1, since every directory shoule
748 * contain at least two files "." and "..")
750 ************************************************************************/
754 FileMgrData *file_mgr_data,
761 FileViewData **file_view_data;
764 * If we are currently busy reading a directory, display a progress
765 * message instead of the normal "x Items, y Hidden" message.
767 if (file_mgr_data->busy_status == initiating_readdir ||
768 file_mgr_data->busy_status == busy_readdir)
770 if (file_mgr_data->busy_detail == 0)
771 sprintf (buf, (GETMESSAGE(3,5, "Reading ...")));
772 else if (file_mgr_data->busy_detail == 1)
773 sprintf (buf, (GETMESSAGE(3,11, "%d Item(s)...")),
774 file_mgr_data->busy_detail);
776 sprintf (buf, (GETMESSAGE(3,9, "%3d Items ...")),
777 file_mgr_data->busy_detail);
779 return True; /* this message deemed important! */
782 else if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
785 * In tree mode, we only show a count of the hidden files
786 * in branches that are currently expanded.
787 * The idea is we want to show how many additional files would
788 * show up if the user turned on the "Show Hidden" option.
791 for (i = 0; i < file_mgr_data->directory_count; i++)
793 file_view_data = file_mgr_data->directory_set[i]->file_view_data;
794 if (file_view_data == NULL)
797 ts = file_mgr_data->directory_set[i]->sub_root->ts;
799 continue; /* this branch is not expanded */
801 for (j = 0; j < file_mgr_data->directory_set[i]->file_count; j++)
803 if (file_view_data[j]->filtered &&
804 (ts == tsAll || file_view_data[j]->file_data->is_subdir))
810 sprintf (buf, (GETMESSAGE(3,6, "%d Hidden")), n_hidden);
818 * In flat mode, we only show a total count of all files
819 * and a count of hidden files.
821 n_files = file_mgr_data->directory_set[0]->file_count;
823 sprintf( buf, (GETMESSAGE(11,31, "Error while reading %s")), file_mgr_data->current_directory );
824 else if( file_mgr_data == trashFileMgrData )
826 n_hidden = file_mgr_data->directory_set[0]->filtered_file_count;
827 sprintf (buf, (GETMESSAGE(3,10, "%d Item(s)")),
832 n_files -= file_mgr_data->directory_set[0]->invisible_file_count;
833 n_hidden = file_mgr_data->directory_set[0]->filtered_file_count -
834 file_mgr_data->directory_set[0]->invisible_file_count;
836 sprintf (buf, (GETMESSAGE(3,12, "%d Item(s) %d Hidden")),
839 sprintf (buf, (GETMESSAGE(3,7, "%d Items %d Hidden")),
848 /************************************************************************
850 * DrawCurrentDirectory
851 * Draw the current directory display area, including the hostname,
852 * the current directory, any highlighted sub-path of the directory,
853 * the file count and the number of selected files.
855 ************************************************************************/
858 DrawCurrentDirectory(
860 FileMgrRec *file_mgr_rec,
861 FileMgrData *file_mgr_data )
864 Dimension width, height, highlight, shadow, margin, twidth;
865 XFontSetExtents *extents;
870 char buf[2*MAX_PATH];
871 char msg[21+MAX_PATH];
886 /* Get layout values */
887 XtSetArg (args[0], XmNwidth, &width);
888 XtSetArg (args[1], XmNheight, &height);
889 XtSetArg (args[2], XmNhighlightThickness, &highlight);
890 XtGetValues (w, args, 3);
891 XtSetArg (args[0], XmNshadowThickness, &shadow);
892 XtSetArg (args[1], XmNmarginWidth, &margin);
893 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
895 if(file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET) {
896 extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
897 font_yoffset = -(extents->max_logical_extent.y);
898 font_height = extents->max_logical_extent.height;
902 font_yoffset = file_mgr_data->cd_font->ascent;
903 font_height = file_mgr_data->cd_font->ascent +
904 file_mgr_data->cd_font->descent;
906 top_margin = (height > (Dimension)font_height)? (Dimension)(height - font_height + 1)/(Dimension)2: 0;
907 left_margin = highlight + shadow + margin;
909 /* Ensure the area is cleared out. */
910 XClearArea (XtDisplay (w), XtWindow (w),
911 highlight, highlight,
912 width - 2*highlight, height - 2*highlight,
916 * If there is no status line and no iconic path,
917 * we will want yo draw the "x Files y Hidden" message here.
919 if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
922 * GetStatusMsg() returns True if the status msg is "important".
923 * In this case, make sure we leave room for it
925 msg_drawn = GetStatusMsg(file_mgr_data, msg);
926 msg_width = get_textwidth (file_mgr_data, msg, strlen(msg));
931 draw_x = left_margin;
932 if( draw_x < 0 || (Dimension) draw_x > width ) /* Make sure that it's in bound */
935 draw_y = top_margin + font_yoffset;
936 if( draw_y < 0 || (Dimension) draw_y > height ) /* Make sure that it's in bound */
941 /* get the text pieces */
942 dir_width = width - 2*left_margin;
944 dir_width -= CUR_DIR_SPACING + msg_width;
945 chopped = get_text_pieces(file_mgr_data, dir_width,
946 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
947 &path_len, &path_pixels);
950 * go check and change the file_mgr_data->cd_select, make sure its not
951 * longer than the file_mgr_data->current_directory.
953 CheckCurrentDirectorySelect(file_mgr_data);
955 /* draw the host and paths */
956 if (!file_mgr_data->fast_cd_enabled)
958 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
959 file_mgr_data->cd_normal_gc, draw_x, draw_y,
960 buf, host_len + prefix_len + path_len);
962 else if (file_mgr_data->restricted_directory)
964 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
965 file_mgr_data->cd_normal_gc, draw_x, draw_y,
966 buf, host_len + prefix_len);
970 * If there is no status line and no iconic path, and we have
971 * room left, draw the "x Files y Hidden" message here.
973 if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
975 /* determine where the message could begin */
976 if (!file_mgr_data->fast_cd_enabled)
977 draw_x += host_pixels + prefix_pixels + path_pixels;
980 XtSetArg(args[0], XmNwidth, &twidth);
981 XtGetValues(file_mgr_rec->current_directory_text, args, 1);
982 if (file_mgr_data->restricted_directory && !chopped)
983 draw_x += host_pixels + prefix_pixels + twidth;
985 draw_x += host_pixels + twidth;
988 /* if there is enough space left, draw the message */
989 if ((Dimension)(draw_x + CUR_DIR_SPACING + msg_width + left_margin) <= width)
991 draw_x = width - left_margin - msg_width;
992 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
993 file_mgr_data->cd_normal_gc, draw_x, draw_y,
995 draw_x -= shadow + CUR_DIR_SPACING; /* right edge of shadow */
1003 draw_x = width - (highlight + shadow);
1005 /* draw the shadow */
1006 if (!file_mgr_data->fast_cd_enabled)
1008 int shadow_width = draw_x - highlight;
1009 int shadow_height = height - 2*highlight;
1010 XmTextFieldWidget tf =
1011 (XmTextFieldWidget)file_mgr_rec->current_directory_text;
1013 XmeDrawShadows(XtDisplay(w), XtWindow(w),
1014 tf->primitive.top_shadow_GC,
1015 tf->primitive.bottom_shadow_GC,
1016 highlight, highlight, shadow_width, shadow_height,
1017 shadow, XmSHADOW_IN);
1023 /************************************************************************
1026 * Callback functions invoked from the current directory dialog's
1027 * apply button being pressed. This function updates and redisplays
1028 * the current directory information.
1030 ************************************************************************/
1034 XtPointer client_data,
1035 DialogData *old_dialog_data,
1036 DialogData *new_dialog_data,
1037 XtPointer call_data )
1039 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
1040 DialogData * dialog_data;
1041 FileMgrData * file_mgr_data;
1042 ChangeDirData * new_change_dir_data;
1043 ChangeDirData * old_change_dir_data;
1044 char path[MAX_PATH];
1045 char host_name[MAX_PATH];
1049 /* Get a pointer file manager's data structure, free up the */
1050 /* old current directory and copy in a new one. Free up the */
1051 /* old selected sub-path, update the file manager's internal */
1052 /* data, and redraw the directory. */
1054 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1055 file_mgr_data = (FileMgrData *) dialog_data->data;
1057 if (file_mgr_data->cd_select != NULL)
1059 XtFree (file_mgr_data->cd_select);
1060 file_mgr_data->cd_select = NULL;
1063 old_change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1064 new_change_dir_data = (ChangeDirData *) new_dialog_data->data;
1066 new_change_dir_data->host_name = XtNewString(old_change_dir_data->host_name);
1067 new_change_dir_data->file_mgr_rec = old_change_dir_data->file_mgr_rec;
1069 _DtHideDialog(old_dialog_data, False);
1071 new_change_dir_data->displayed = False;
1073 file_mgr_data->change_dir->data = (XtPointer) new_change_dir_data;
1074 new_dialog_data->data = (XtPointer) old_change_dir_data;
1075 _DtFreeDialogData (new_dialog_data);
1076 file_mgr_rec->menuStates |= CHANGEDIR;
1079 /* Process call_data into a hostname and directory name. */
1081 ShowNewDirectory (file_mgr_data,
1082 ((ChangeDirData *)file_mgr_data->change_dir->data)->host_name,
1089 /************************************************************************
1092 * Callback functions invoked from the current directory dialog's
1093 * close button being pressed. This function resensitizes the
1094 * Change Directory... menu item.
1096 ************************************************************************/
1101 XtPointer client_data,
1102 DialogData *old_dialog_data,
1103 DialogData *new_dialog_data )
1105 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
1107 _DtFreeDialogData (new_dialog_data);
1108 file_mgr_rec->menuStates |= CHANGEDIR;
1111 /************************************************************************
1113 * CheckCurrentDirectorySelect
1114 * Before calling DrawCurrentDirectorySelect() this function
1115 * makes sure that the fm->cd_select isn't longer than the
1116 * fm->current_directory. If it is it reconfigures fm->cd_select
1117 * to hold no more than what fm->current_directory is.
1119 ************************************************************************/
1121 CheckCurrentDirectorySelect(
1122 FileMgrData *file_mgr_data )
1124 int length_cd, length_cd_s;
1127 if (file_mgr_data == NULL ||
1128 file_mgr_data->cd_select == NULL ||
1129 file_mgr_data->current_directory == NULL)
1132 /* get the true lengths of current_directory and current_directory_select */
1133 length_cd = strlen(file_mgr_data->current_directory);
1134 length_cd_s = strlen(file_mgr_data->cd_select);
1136 /* if cd is larger than cd_select than we have now problem */
1137 if(length_cd >= length_cd_s)
1140 /* we need to recalculate the cd_select */
1141 str = XtNewString(file_mgr_data->cd_select);
1144 ptr = strrchr(str, '/');
1146 length_cd_s = strlen(str);
1147 if(length_cd > length_cd_s)
1149 XtFree(file_mgr_data->cd_select);
1150 file_mgr_data->cd_select = (char *)XtMalloc(strlen(str) + 1);
1151 strcpy(file_mgr_data->cd_select, str);
1158 /************************************************************************
1161 * Post the fast change to text widget.
1163 ***************************************************************************/
1166 FileMgrRec *file_mgr_rec,
1167 FileMgrData *file_mgr_data )
1171 Dimension width, height;
1172 Dimension shadow, highlight, margin;
1173 char buf[2*MAX_PATH];
1184 doubleClick = False;
1186 XtRemoveAllCallbacks (file_mgr_rec->current_directory, XmNexposeCallback);
1188 XtFree (file_mgr_data->cd_select);
1189 file_mgr_data->cd_select = NULL;
1191 file_mgr_data->fast_cd_enabled = True;
1193 /* if not a toolbox, just put the current directory in text widget */
1194 if (file_mgr_data->restricted_directory == NULL)
1196 if (strcmp(file_mgr_data->host, home_host_name) == 0)
1197 textString = XtNewString(file_mgr_data->current_directory);
1199 textString = DtCreateContextString(file_mgr_data->host,
1200 file_mgr_data->current_directory,
1203 else /* is a toolbox, so put the subset of what the toolbox is in the text*/
1207 ptr = file_mgr_data->current_directory +
1208 strlen(file_mgr_data->restricted_directory);
1209 if (strcmp(ptr, "") == 0)
1210 textString = XtNewString("/");
1212 textString = XtNewString(ptr);
1214 begin_x = get_textwidth (file_mgr_data, textString, strlen (textString));
1216 /* Get layout values */
1217 XtSetArg (args[0], XmNwidth, &width);
1218 XtSetArg (args[1], XmNhighlightThickness, &highlight);
1219 XtGetValues (file_mgr_rec->current_directory, args, 2);
1220 XtSetArg (args[0], XmNshadowThickness, &shadow);
1221 XtSetArg (args[1], XmNmarginWidth, &margin);
1222 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
1223 left_margin = highlight + shadow + margin;
1225 if(file_mgr_data->restricted_directory == NULL)
1226 XtSetArg (args[0], XmNleftOffset, 0);
1229 XtSetArg (args[0], XmNshadowThickness, &shadow);
1230 XtSetArg (args[1], XmNhighlightThickness, &highlight);
1231 XtGetValues(file_mgr_rec->current_directory_text, args, 2);
1233 get_text_pieces(file_mgr_data, width - 2*left_margin,
1234 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
1235 &path_len, &path_pixels);
1236 begin_x = left_margin + host_pixels - shadow - highlight;
1238 begin_x += prefix_pixels;
1239 XtSetArg (args[0], XmNleftOffset, begin_x);
1241 XtSetArg (args[1], XmNvalue, textString);
1242 XtSetValues(file_mgr_rec->current_directory_text, args, 2);
1243 XtSetArg (args[0], XmNcursorPosition, strlen(textString));
1244 XtSetValues(file_mgr_rec->current_directory_text, args, 1);
1246 XtSetArg (args[0], XmNallowShellResize, False);
1247 XtSetValues(file_mgr_rec->shell, args, 1);
1248 XtManageChild(file_mgr_rec->current_directory_text);
1249 XtSetArg (args[0], XmNallowShellResize, True);
1250 XtSetValues(file_mgr_rec->shell, args, 1);
1251 XRaiseWindow(XtDisplay(file_mgr_rec->current_directory_text),
1252 XtWindow(file_mgr_rec->current_directory_text));
1253 XmUpdateDisplay(file_mgr_rec->current_directory_text);
1254 XmProcessTraversal(file_mgr_rec->current_directory_text,
1255 XmTRAVERSE_CURRENT);
1257 XtAddCallback (file_mgr_rec->current_directory, XmNexposeCallback,
1258 CurrentDirExposed, file_mgr_rec);
1261 /************************************************************************
1263 * TimerEvent - timeout for double click on current Directory line. If
1264 * we get here we know it was a single click so lets post the
1265 * fast change to text widget.
1267 ***************************************************************************/
1270 XtPointer client_data,
1273 FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
1274 DialogData * dialog_data;
1275 FileMgrData *file_mgr_data;
1277 doubleClick = False;
1279 /* Got an accelerator after we were unposted */
1280 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1282 file_mgr_data = (FileMgrData *) dialog_data->data;
1284 ShowFastChangeDir(file_mgr_rec, file_mgr_data);
1287 /************************************************************************
1289 * ResizeFastText - resizes the fast change text widget due to changes
1290 * in the size of the FileManager window.
1292 *************************************************************************/
1295 FileMgrRec *file_mgr_rec,
1296 FileMgrData *file_mgr_data,
1303 /* nothing to do if not managed */
1304 if (!XtIsManaged(file_mgr_rec->current_directory_text))
1307 /* get width of current directory line */
1308 XtSetArg (args[0], XmNwidth, &width);
1309 XtGetValues (file_mgr_rec->current_directory, args, 1);
1311 /* get offset of the text widget */
1312 XtSetArg(args[0], XmNleftOffset, &left_offset);
1313 XtGetValues(file_mgr_rec->current_directory_text, args, 1);
1315 /* set text widget width = current_directory width minus left offset */
1316 XtSetArg (args[0], XmNwidth, width - left_offset);
1317 XtSetValues (file_mgr_rec->current_directory_text, args, 1);
1321 /*--------------------------------------------------------------------
1323 *------------------------------------------------------------------*/
1325 /* use Xmb functions if XFontSet is used. */
1327 get_textwidth( FileMgrData *fmd,
1333 switch(fmd->cd_fonttype)
1335 case XmFONT_IS_FONTSET:
1336 w = XmbTextEscapement(fmd->cd_fontset, str, len);
1338 case XmFONT_IS_FONT:
1339 w = XTextWidth(fmd->cd_font, str, len);
1347 draw_imagestring( Display *display,
1355 switch(fmd->cd_fonttype)
1357 case XmFONT_IS_FONTSET:
1358 XmbDrawImageString(display, d, fmd->cd_fontset, gc, x, y, text,
1361 case XmFONT_IS_FONT:
1362 XDrawImageString(display, d, gc, x, y, text, bytes);