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 /* $TOG: ChangeDirP.c /main/8 1998/04/01 15:05:07 rafi $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 * COMPONENT_NAME: Desktop File Manager (dtfile)
31 * Description: Processing functions for the change directory display
32 * line and the current directory dialog.
35 * CheckCurrentDirectorySelect
38 * CurrentDirDropCallback
40 * CurrentDirIconCallback
42 * CurrentDirectoryIconMotion
43 * DrawCurrentDirectory
53 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
54 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
55 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
56 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
58 ****************************************************************************
59 ************************************<+>*************************************/
65 #include <Xm/TextFP.h>
66 #include <Xm/PushBG.h>
67 #include <Xm/DragDrop.h>
68 #include <Xm/RowColumn.h>
71 #include <Dt/DtNlUtils.h>
72 #include <Dt/Connect.h>
75 #include "SharedProcs.h"
80 #include "ChangeDir.h"
84 /******** Static Function Declarations ********/
86 static void CurrentDirChange(
87 XtPointer client_data,
88 DialogData *old_dialog_data,
89 DialogData *new_dialog_data,
90 XtPointer call_data) ;
91 static void CurrentDirClose(
92 XtPointer client_data,
93 DialogData *old_dialog_data,
94 DialogData *new_dialog_data) ;
95 static void CheckCurrentDirectorySelect(
96 FileMgrData *file_mgr_data ) ;
97 static void TimerEvent(
98 XtPointer client_data,
100 static void ResizeFastText(
101 FileMgrRec *file_mgr_rec,
102 FileMgrData *file_mgr_data,
104 static int get_textwidth(
108 static void draw_imagestring(
117 /******** End Static Function Declarations ********/
119 /* absolute value macro */
121 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
124 /* layout constants */
125 #define CUR_DIR_SPACING 5
128 /* local global varible to determine whether the user has double clicked
130 static Boolean doubleClick = False;
132 /*--------------------------------------------------------------------
135 * Given a width available for the current directory text,
136 * determines the text to be drawn in one of three formats:
138 * /path (non-restricted directory)
139 * /.../path (restricted directory)
140 * .../subpath (if the full path wouldn't fit)
142 * Returns the length (in chars) and width (in pixels) of each of
143 * the two components of the text:
144 * (1) prefix "/..." or "...", and (2) path or subpath.
145 * Returns True if the path was chopped because it wouldn't fit.
147 *------------------------------------------------------------------*/
151 FileMgrData *file_mgr_data,
157 int *prefix_pixels_p,
161 Boolean chopped = False;
167 char *next_part = NULL;
169 *host_len_p = *host_pixels_p = 0;
171 /* if restricted directory, path prefix is "/..." */
172 if (file_mgr_data->restricted_directory)
175 prefix_len = strlen("/...");
176 prefix_pixels = get_textwidth (file_mgr_data, "/...", prefix_len);
177 path_begin = file_mgr_data->current_directory +
178 strlen(file_mgr_data->restricted_directory);
179 if (*path_begin == '\0')
181 else if (*path_begin != '/')
189 path_begin = file_mgr_data->current_directory;
192 /* calculate path length & width */
193 path_len = strlen(path_begin);
194 path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
196 /* if whole path doesn't fit, we need to chop off pieces until it does */
197 if (prefix_pixels + path_pixels > width)
201 /* change the path prefix */
203 prefix_len = strlen("...");
204 prefix_pixels = get_textwidth (file_mgr_data, "...", prefix_len);
208 /* chop off the next piece (everything up to the next '/') */
210 next_part = DtStrchr(path_begin + 1, '/');
211 if (next_part == NULL)
213 /* Got here only when the last directory is still too
219 /* calculate new path length */
220 path_begin = next_part;
221 path_len = strlen(path_begin);
222 path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
224 /* keep going until it fits */
225 } while (prefix_pixels + path_pixels > width);
228 /* add the path to the buffer */
229 if( NULL == next_part )
231 /* Got here only when the last directory is still too
239 /* Going back one character at a time to see if it fit
241 path_pixels = get_textwidth( file_mgr_data, path_begin, len );
242 if( prefix_pixels + path_pixels < width )
251 buf[prefix_len] = 0x0;
257 strncpy (buf + prefix_len, path_begin, len);
259 *path_pixels_p = path_pixels;
264 strcpy (buf + prefix_len, path_begin);
265 *path_len_p = path_len;
266 *path_pixels_p = path_pixels;
270 *prefix_len_p = prefix_len;
271 *prefix_pixels_p = prefix_pixels;
276 /************************************************************************
278 * ShowChangeDirDialog
279 * Callback functions invoked from the Change Directory... menu
280 * item. This function displays the change directory dialog.
282 ************************************************************************/
288 XtPointer client_data,
291 FileMgrRec * file_mgr_rec;
292 DialogData * dialog_data;
293 FileMgrData * file_mgr_data;
294 ChangeDirData * change_dir_data;
295 ChangeDirRec * change_dir_rec;
298 char *tempStr, *tmpStr;
301 /* Set the menu item to insensitive to prevent multiple */
302 /* dialogs from being posted and get the area under the */
303 /* menu pane redrawn. */
307 if((XtArgVal)client_data == FM_POPUP)
310 mbar = (Widget) XmGetPostedFromWidget(XtParent(w));
313 XtSetArg(args[0], XmNuserData, &file_mgr_rec);
314 XtGetValues(mbar, args, 1);
316 /* Ignore accelerators when we're insensitive */
317 if ((file_mgr_rec->menuStates & CHANGEDIR) == 0)
319 XSetInputFocus(XtDisplay(w),
320 XtWindow(file_mgr_rec->change_directoryBtn_child),
321 RevertToParent, CurrentTime);
327 /* Done only during a restore session */
328 file_mgr_rec = (FileMgrRec *)client_data;
331 /* Got an accelerator after we were unposted */
332 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
335 file_mgr_data = (FileMgrData *) dialog_data->data;
336 change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
337 change_dir_data->file_mgr_rec = (XtPointer) file_mgr_rec;
339 file_mgr_rec->menuStates &= ~CHANGEDIR;
341 _DtShowDialog (file_mgr_rec->shell, (Widget)NULL, (XtPointer)file_mgr_rec,
342 file_mgr_data->change_dir,
343 CurrentDirChange, (XtPointer)file_mgr_rec,
344 CurrentDirClose, (XtPointer)file_mgr_rec, (char *)NULL,
345 False, False, (char *)NULL, (XClassHint *)NULL);
347 /* Save a ptr to file_mgr_rec in the find dialogs structure */
348 change_dir_rec = (ChangeDirRec *)_DtGetDialogInstance(
349 file_mgr_data->change_dir);
351 if(file_mgr_data->title != NULL &&
352 strcmp(file_mgr_data->helpVol, DTFILE_HELP_NAME) != 0)
354 tmpStr = GETMESSAGE(2,15, "Go To");
355 tempStr = (char *)XtMalloc(strlen(tmpStr) +
356 strlen(file_mgr_data->title) + 5);
357 sprintf(tempStr, "%s - %s", file_mgr_data->title, tmpStr);
361 tmpStr = (GETMESSAGE(2,17, "File Manager - Go To"));
362 tempStr = XtNewString(tmpStr);
364 XtSetArg (args[0], XmNtitle, tempStr);
365 XtSetValues (XtParent (change_dir_rec->change_dir), args, 1);
368 file_mgr_rec->change_directoryBtn_child=XtParent (change_dir_rec->change_dir);
374 /************************************************************************
377 * When a Button1 selection occurs on the current directory line,
378 * see if it occurred within the directory path, highlight the
379 * selected sub-path, or if the sub-path was already highlighted,
380 * set the current directory to the path and dehighlight.
382 ************************************************************************/
387 XtPointer client_data,
388 XtPointer call_data )
390 FileMgrRec *file_mgr_rec = (FileMgrRec *) client_data;
391 DialogData *dialog_data;
392 FileMgrData *file_mgr_data;
393 char buf[2*MAX_PATH];
394 char host_name[MAX_PATH];
403 XmDrawnButtonCallbackStruct *button_data;
405 Dimension width, highlight, shadow, margin;
416 static XtIntervalId TimerId;
418 /* if doubleClick is true than we have a double click so we want
419 * to change to the new directory that the user double clicked on
422 XtRemoveTimeOut(TimerId);
424 button_data = (XmDrawnButtonCallbackStruct *) call_data;
425 event = (XButtonEvent *) button_data->event;
427 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
428 file_mgr_data = (FileMgrData *) dialog_data->data;
430 /* Get layout values */
431 XtSetArg (args[0], XmNwidth, &width);
432 XtSetArg (args[1], XmNhighlightThickness, &highlight);
433 XtGetValues (w, args, 2);
434 XtSetArg (args[0], XmNshadowThickness, &shadow);
435 XtSetArg (args[1], XmNmarginWidth, &margin);
436 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
437 left_margin = highlight + shadow + margin;
439 /* Get the starting and ending locations of the current */
440 /* directory text. */
441 chopped = get_text_pieces(file_mgr_data, width - 2*left_margin,
442 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
443 &path_len, &path_pixels);
445 begin_x = left_margin;
446 end_x = begin_x + host_pixels + prefix_pixels + path_pixels;
448 /* Get the selected path */
449 if (event->x < begin_x || event->x >= end_x)
451 /* click outside the directory text: nothing selected */
454 else if (event->x < begin_x + host_pixels ||
455 event->x < begin_x + host_pixels + prefix_pixels && !chopped)
457 /* click on host name or "/..." prefix: root selected */
458 if (file_mgr_data->restricted_directory)
459 new_select = XtNewString(file_mgr_data->restricted_directory);
461 new_select = XtNewString("/");
463 else if (event->x < begin_x + host_pixels + prefix_pixels && chopped)
465 /* click on "..." prefix: directory above the visible piece selected */
466 len = strlen(file_mgr_data->current_directory) - path_len;
467 new_select = (char *) XtMalloc(len + 1);
468 memcpy(new_select, file_mgr_data->current_directory, len);
471 else /* event->x >= begin_x + host_pixels + prefix_pixels */
473 /* click on the path: determine which subdirectory selected */
474 begin_x += host_pixels + prefix_pixels;
475 i = host_len + prefix_len;
476 swidth = get_textwidth(file_mgr_data, "/", strlen("/")) / 2;
478 while (begin_x - swidth < event->x)
480 /* find next '/' in path */
481 ptr = DtStrchr(buf + i, '/');
484 i = host_len + prefix_len + path_len + 1;
488 /* get x-position of next path component */
489 len = ((ptr + 1) - buf) - i;
490 begin_x += get_textwidth(file_mgr_data, buf + i, len);
494 /* if we have a restricted diretory and i == 5 ("/.../") then we want
495 the len to be the restricted directory */
496 if (file_mgr_data->restricted_directory && i == 5)
497 len = strlen(file_mgr_data->restricted_directory);
499 len = strlen(file_mgr_data->current_directory)
500 - (host_len + prefix_len + path_len - i) - 1;
501 new_select = (char *) XtMalloc(len + 1);
503 strcpy(new_select, "/");
506 memcpy(new_select, file_mgr_data->current_directory, len);
511 /* in restricted mode, don't allow going above the user's home dir */
512 if (new_select != NULL && restrictMode)
514 /* check if new_select is the same as or a subdirectory of $HOME */
515 len = strlen(users_home_dir);
516 if (strncmp(new_select, users_home_dir, len) != 0
517 || new_select[len] != '\0' && new_select[len] != '/')
519 /* change new_select to $HOME */
521 new_select = XtNewString(users_home_dir);
526 /* If the path is the same as what is already selected, */
527 /* free cd_select, set the directory to the selected */
528 /* directory, redraw the directory display. */
530 /* If the path was different, set cd_select to the */
531 /* selected directory and redraw the directory. */
533 if (new_select != NULL && file_mgr_data->cd_select != NULL &&
534 strcmp(new_select, file_mgr_data->cd_select) == 0)
536 XtFree (file_mgr_data->cd_select);
537 file_mgr_data->cd_select = NULL;
539 strcpy(buf, new_select);
540 strcpy(host_name, file_mgr_data->host);
542 if (strcmp (buf, file_mgr_data->current_directory) == 0)
543 FileMgrReread (file_mgr_rec);
545 ShowNewDirectory (file_mgr_data, host_name, buf);
551 XtFree (file_mgr_data->cd_select);
552 file_mgr_data->cd_select = new_select;
558 DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
563 TimerId = XtAppAddTimeOut (XtWidgetToApplicationContext (w),
564 XtGetMultiClickTime(XtDisplay(w)),
565 (XtTimerCallbackProc) TimerEvent,
566 (XtPointer) file_mgr_rec);
572 /************************************************************************
574 * CurrentDirDropCallback
575 * Callback function invoked upon an action on the change view drop.
577 ************************************************************************/
580 CurrentDirDropCallback(
582 XtPointer client_data,
583 XtPointer call_data )
585 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
586 XmAnyCallbackStruct * callback;
587 DialogData * dialog_data;
588 FileMgrData * file_mgr_data;
589 char host_name[MAX_PATH];
591 callback = (XmAnyCallbackStruct *) call_data;
592 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
593 file_mgr_data = (FileMgrData *) dialog_data->data;
595 if (callback->reason == XmCR_DEFAULT_ACTION)
597 strcpy(host_name, file_mgr_data->host);
598 ShowNewDirectory (file_mgr_data, host_name,
599 _DtPName (file_mgr_data->current_directory));
604 /************************************************************************
606 * CurrentDirIconCallback
607 * Callback function invoked upon an action occurring on an icon.
609 ************************************************************************/
612 CurrentDirIconCallback(
614 XtPointer client_data,
615 XtPointer call_data )
617 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
618 XmAnyCallbackStruct * callback;
619 XButtonEvent * event;
620 DialogData * dialog_data;
621 FileMgrData * file_mgr_data;
623 callback = (XmAnyCallbackStruct *) call_data;
624 event = (XButtonEvent *) callback->event;
625 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
626 file_mgr_data = (FileMgrData *) dialog_data->data;
628 if (callback->reason == XmCR_DRAG)
630 /* Do nothing if a Button 1 drag is already ramping up */
634 /* Save starting X and Y, for threshold detection */
635 initialDragX = event->x;
636 initialDragY = event->y;
638 /* Flag that a Button 2 drag is ramping up */
639 B2DragPossible = True;
641 UnpostTextField(file_mgr_data);
643 else if (callback->reason == XmCR_ARM)
645 /* Do nothing if a Button 2 drag is already ramping up */
649 /* Save starting X and Y, for threshold detection */
650 initialDragX = event->x;
651 initialDragY = event->y;
653 /* Flag that a Button 1 drag is ramping up */
654 B1DragPossible = True;
656 /* but since we're in the current directory icon we don't want to
657 process on the button up */
658 ProcessBtnUpCD = False;
660 UnpostTextField(file_mgr_data);
662 else if (callback->reason == XmCR_DEFAULT_ACTION)
664 /* We now know that a drag operation won't be starting up */
665 B1DragPossible = False;
666 B2DragPossible = False;
668 UnpostTextField(file_mgr_data);
670 /* Default action is to reread the directory */
671 FileMgrReread (file_mgr_rec);
673 else if ((callback->reason == XmCR_SELECT) ||
674 (callback->reason == XmCR_DISARM) ||
675 (callback->reason == XmCR_DROP))
677 /* We now know that a drag operation won't be starting up */
678 B1DragPossible = False;
679 B2DragPossible = False;
685 * This function processes motion events anytime a B1 or B2 drag operation
686 * has the potential of starting. When the drag threshold is surpassed,
687 * a drag operation will be started.
691 CurrentDirectoryIconMotion(
693 XtPointer client_data,
697 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
698 DialogData * dialog_data;
699 FileMgrData * file_mgr_data;
708 if ((B1DragPossible && (event->xmotion.state & Button1Mask)) ||
709 (B2DragPossible && (event->xmotion.state & Button2Mask)))
711 /* Have we passed the drag threshold? */
712 diffX = initialDragX - event->xmotion.x;
713 diffY = initialDragY - event->xmotion.y;
715 if ((ABS(diffX) >= dragThreshold) || (ABS(diffY) >= dragThreshold))
717 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
718 file_mgr_data = (FileMgrData *) dialog_data->data;
720 initiating_view = (XtPointer) file_mgr_data;
721 dirIcon = file_mgr_rec->current_directory_icon;
722 StartDrag(dirIcon, NULL, event);
728 /************************************************************************
731 * Callback functions invoked from the current directory display
732 * drawn button. This function extracts some structures and calls
733 * the directory display function.
735 ************************************************************************/
740 XtPointer client_data,
741 XtPointer call_data )
743 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
744 DialogData * dialog_data;
745 FileMgrData * file_mgr_data;
747 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
749 /* Check to see if the view has been closed */
751 if (dialog_data == NULL) return;
753 file_mgr_data = (FileMgrData *) dialog_data->data;
755 if (file_mgr_data->cd_normal_gc != 0)
756 DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
762 /************************************************************************
765 * Construct the status message (normally "x Items, y Hidden").
766 * Returns True if the message is deemed "important".
768 * @@@ Note 2/17/95: messages below containing "Item(s)" should really
769 * be just "Item", but the message catalog is frozen at this time, so
770 * we can't fix this now. (In practice, it doesn't matter, because
771 * the item count should always be > 1, since every directory shoule
772 * contain at least two files "." and "..")
774 ************************************************************************/
778 FileMgrData *file_mgr_data,
785 FileViewData **file_view_data;
788 * If we are currently busy reading a directory, display a progress
789 * message instead of the normal "x Items, y Hidden" message.
791 if (file_mgr_data->busy_status == initiating_readdir ||
792 file_mgr_data->busy_status == busy_readdir)
794 if (file_mgr_data->busy_detail == 0)
795 sprintf (buf, "%s", (GETMESSAGE(3,5, "Reading ...")));
796 else if (file_mgr_data->busy_detail == 1)
797 sprintf (buf, (GETMESSAGE(3,11, "%d Item(s)...")),
798 file_mgr_data->busy_detail);
800 sprintf (buf, (GETMESSAGE(3,9, "%3d Items ...")),
801 file_mgr_data->busy_detail);
803 return True; /* this message deemed important! */
806 else if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
809 * In tree mode, we only show a count of the hidden files
810 * in branches that are currently expanded.
811 * The idea is we want to show how many additional files would
812 * show up if the user turned on the "Show Hidden" option.
815 for (i = 0; i < file_mgr_data->directory_count; i++)
817 file_view_data = file_mgr_data->directory_set[i]->file_view_data;
818 if (file_view_data == NULL)
821 ts = file_mgr_data->directory_set[i]->sub_root->ts;
823 continue; /* this branch is not expanded */
825 for (j = 0; j < file_mgr_data->directory_set[i]->file_count; j++)
827 if (file_view_data[j]->filtered &&
828 (ts == tsAll || file_view_data[j]->file_data->is_subdir))
834 sprintf (buf, (GETMESSAGE(3,6, "%d Hidden")), n_hidden);
842 * In flat mode, we only show a total count of all files
843 * and a count of hidden files.
845 n_files = file_mgr_data->directory_set[0]->file_count;
847 sprintf( buf, (GETMESSAGE(11,31, "Error while reading %s")), file_mgr_data->current_directory );
848 else if( file_mgr_data == trashFileMgrData )
850 n_hidden = file_mgr_data->directory_set[0]->filtered_file_count;
851 sprintf (buf, (GETMESSAGE(3,10, "%d Item(s)")),
856 n_files -= file_mgr_data->directory_set[0]->invisible_file_count;
857 n_hidden = file_mgr_data->directory_set[0]->filtered_file_count -
858 file_mgr_data->directory_set[0]->invisible_file_count;
860 sprintf (buf, (GETMESSAGE(3,12, "%d Item(s) %d Hidden")),
863 sprintf (buf, (GETMESSAGE(3,7, "%d Items %d Hidden")),
872 /************************************************************************
874 * DrawCurrentDirectory
875 * Draw the current directory display area, including the hostname,
876 * the current directory, any highlighted sub-path of the directory,
877 * the file count and the number of selected files.
879 ************************************************************************/
882 DrawCurrentDirectory(
884 FileMgrRec *file_mgr_rec,
885 FileMgrData *file_mgr_data )
888 Dimension width, height, highlight, shadow, margin, twidth;
889 XFontSetExtents *extents;
894 char buf[2*MAX_PATH];
895 char msg[21+MAX_PATH];
910 /* Get layout values */
911 XtSetArg (args[0], XmNwidth, &width);
912 XtSetArg (args[1], XmNheight, &height);
913 XtSetArg (args[2], XmNhighlightThickness, &highlight);
914 XtGetValues (w, args, 3);
915 XtSetArg (args[0], XmNshadowThickness, &shadow);
916 XtSetArg (args[1], XmNmarginWidth, &margin);
917 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
919 if(file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET) {
920 extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
921 font_yoffset = -(extents->max_logical_extent.y);
922 font_height = extents->max_logical_extent.height;
926 font_yoffset = file_mgr_data->cd_font->ascent;
927 font_height = file_mgr_data->cd_font->ascent +
928 file_mgr_data->cd_font->descent;
930 top_margin = (height > (Dimension)font_height)? (Dimension)(height - font_height + 1)/(Dimension)2: 0;
931 left_margin = highlight + shadow + margin;
933 /* Ensure the area is cleared out. */
934 XClearArea (XtDisplay (w), XtWindow (w),
935 highlight, highlight,
936 width - 2*highlight, height - 2*highlight,
940 * If there is no status line and no iconic path,
941 * we will want yo draw the "x Files y Hidden" message here.
943 if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
946 * GetStatusMsg() returns True if the status msg is "important".
947 * In this case, make sure we leave room for it
949 msg_drawn = GetStatusMsg(file_mgr_data, msg);
950 msg_width = get_textwidth (file_mgr_data, msg, strlen(msg));
955 draw_x = left_margin;
956 if( draw_x < 0 || (Dimension) draw_x > width ) /* Make sure that it's in bound */
959 draw_y = top_margin + font_yoffset;
960 if( draw_y < 0 || (Dimension) draw_y > height ) /* Make sure that it's in bound */
965 /* get the text pieces */
966 dir_width = width - 2*left_margin;
968 dir_width -= CUR_DIR_SPACING + msg_width;
969 chopped = get_text_pieces(file_mgr_data, dir_width,
970 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
971 &path_len, &path_pixels);
974 * go check and change the file_mgr_data->cd_select, make sure its not
975 * longer than the file_mgr_data->current_directory.
977 CheckCurrentDirectorySelect(file_mgr_data);
979 /* draw the host and paths */
980 if (!file_mgr_data->fast_cd_enabled)
982 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
983 file_mgr_data->cd_normal_gc, draw_x, draw_y,
984 buf, host_len + prefix_len + path_len);
986 else if (file_mgr_data->restricted_directory)
988 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
989 file_mgr_data->cd_normal_gc, draw_x, draw_y,
990 buf, host_len + prefix_len);
994 * If there is no status line and no iconic path, and we have
995 * room left, draw the "x Files y Hidden" message here.
997 if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
999 /* determine where the message could begin */
1000 if (!file_mgr_data->fast_cd_enabled)
1001 draw_x += host_pixels + prefix_pixels + path_pixels;
1004 XtSetArg(args[0], XmNwidth, &twidth);
1005 XtGetValues(file_mgr_rec->current_directory_text, args, 1);
1006 if (file_mgr_data->restricted_directory && !chopped)
1007 draw_x += host_pixels + prefix_pixels + twidth;
1009 draw_x += host_pixels + twidth;
1012 /* if there is enough space left, draw the message */
1013 if ((Dimension)(draw_x + CUR_DIR_SPACING + msg_width + left_margin) <= width)
1015 draw_x = width - left_margin - msg_width;
1016 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
1017 file_mgr_data->cd_normal_gc, draw_x, draw_y,
1019 draw_x -= shadow + CUR_DIR_SPACING; /* right edge of shadow */
1027 draw_x = width - (highlight + shadow);
1029 /* draw the shadow */
1030 if (!file_mgr_data->fast_cd_enabled)
1032 int shadow_width = draw_x - highlight;
1033 int shadow_height = height - 2*highlight;
1034 XmTextFieldWidget tf =
1035 (XmTextFieldWidget)file_mgr_rec->current_directory_text;
1037 XmeDrawShadows(XtDisplay(w), XtWindow(w),
1038 tf->primitive.top_shadow_GC,
1039 tf->primitive.bottom_shadow_GC,
1040 highlight, highlight, shadow_width, shadow_height,
1041 shadow, XmSHADOW_IN);
1047 /************************************************************************
1050 * Callback functions invoked from the current directory dialog's
1051 * apply button being pressed. This function updates and redisplays
1052 * the current directory information.
1054 ************************************************************************/
1058 XtPointer client_data,
1059 DialogData *old_dialog_data,
1060 DialogData *new_dialog_data,
1061 XtPointer call_data )
1063 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
1064 DialogData * dialog_data;
1065 FileMgrData * file_mgr_data;
1066 ChangeDirData * new_change_dir_data;
1067 ChangeDirData * old_change_dir_data;
1068 char path[MAX_PATH];
1069 char host_name[MAX_PATH];
1073 /* Get a pointer file manager's data structure, free up the */
1074 /* old current directory and copy in a new one. Free up the */
1075 /* old selected sub-path, update the file manager's internal */
1076 /* data, and redraw the directory. */
1078 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1079 file_mgr_data = (FileMgrData *) dialog_data->data;
1081 if (file_mgr_data->cd_select != NULL)
1083 XtFree (file_mgr_data->cd_select);
1084 file_mgr_data->cd_select = NULL;
1087 old_change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1088 new_change_dir_data = (ChangeDirData *) new_dialog_data->data;
1090 new_change_dir_data->host_name = XtNewString(old_change_dir_data->host_name);
1091 new_change_dir_data->file_mgr_rec = old_change_dir_data->file_mgr_rec;
1093 _DtHideDialog(old_dialog_data, False);
1095 new_change_dir_data->displayed = False;
1097 file_mgr_data->change_dir->data = (XtPointer) new_change_dir_data;
1098 new_dialog_data->data = (XtPointer) old_change_dir_data;
1099 _DtFreeDialogData (new_dialog_data);
1100 file_mgr_rec->menuStates |= CHANGEDIR;
1103 /* Process call_data into a hostname and directory name. */
1105 ShowNewDirectory (file_mgr_data,
1106 ((ChangeDirData *)file_mgr_data->change_dir->data)->host_name,
1113 /************************************************************************
1116 * Callback functions invoked from the current directory dialog's
1117 * close button being pressed. This function resensitizes the
1118 * Change Directory... menu item.
1120 ************************************************************************/
1125 XtPointer client_data,
1126 DialogData *old_dialog_data,
1127 DialogData *new_dialog_data )
1129 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
1131 _DtFreeDialogData (new_dialog_data);
1132 file_mgr_rec->menuStates |= CHANGEDIR;
1135 /************************************************************************
1137 * CheckCurrentDirectorySelect
1138 * Before calling DrawCurrentDirectorySelect() this function
1139 * makes sure that the fm->cd_select isn't longer than the
1140 * fm->current_directory. If it is it reconfigures fm->cd_select
1141 * to hold no more than what fm->current_directory is.
1143 ************************************************************************/
1145 CheckCurrentDirectorySelect(
1146 FileMgrData *file_mgr_data )
1148 int length_cd, length_cd_s;
1151 if (file_mgr_data == NULL ||
1152 file_mgr_data->cd_select == NULL ||
1153 file_mgr_data->current_directory == NULL)
1156 /* get the true lengths of current_directory and current_directory_select */
1157 length_cd = strlen(file_mgr_data->current_directory);
1158 length_cd_s = strlen(file_mgr_data->cd_select);
1160 /* if cd is larger than cd_select than we have now problem */
1161 if(length_cd >= length_cd_s)
1164 /* we need to recalculate the cd_select */
1165 str = XtNewString(file_mgr_data->cd_select);
1168 ptr = strrchr(str, '/');
1170 length_cd_s = strlen(str);
1171 if(length_cd > length_cd_s)
1173 XtFree(file_mgr_data->cd_select);
1174 file_mgr_data->cd_select = (char *)XtMalloc(strlen(str) + 1);
1175 strcpy(file_mgr_data->cd_select, str);
1182 /************************************************************************
1185 * Post the fast change to text widget.
1187 ***************************************************************************/
1190 FileMgrRec *file_mgr_rec,
1191 FileMgrData *file_mgr_data )
1195 Dimension width, height;
1196 Dimension shadow, highlight, margin;
1197 char buf[2*MAX_PATH];
1208 doubleClick = False;
1210 XtRemoveAllCallbacks (file_mgr_rec->current_directory, XmNexposeCallback);
1212 XtFree (file_mgr_data->cd_select);
1213 file_mgr_data->cd_select = NULL;
1215 file_mgr_data->fast_cd_enabled = True;
1217 /* if not a toolbox, just put the current directory in text widget */
1218 if (file_mgr_data->restricted_directory == NULL)
1220 if (strcmp(file_mgr_data->host, home_host_name) == 0)
1221 textString = XtNewString(file_mgr_data->current_directory);
1223 textString = DtCreateContextString(file_mgr_data->host,
1224 file_mgr_data->current_directory,
1227 else /* is a toolbox, so put the subset of what the toolbox is in the text*/
1231 ptr = file_mgr_data->current_directory +
1232 strlen(file_mgr_data->restricted_directory);
1233 if (strcmp(ptr, "") == 0)
1234 textString = XtNewString("/");
1236 textString = XtNewString(ptr);
1238 begin_x = get_textwidth (file_mgr_data, textString, strlen (textString));
1240 /* Get layout values */
1241 XtSetArg (args[0], XmNwidth, &width);
1242 XtSetArg (args[1], XmNhighlightThickness, &highlight);
1243 XtGetValues (file_mgr_rec->current_directory, args, 2);
1244 XtSetArg (args[0], XmNshadowThickness, &shadow);
1245 XtSetArg (args[1], XmNmarginWidth, &margin);
1246 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
1247 left_margin = highlight + shadow + margin;
1249 if(file_mgr_data->restricted_directory == NULL)
1250 XtSetArg (args[0], XmNleftOffset, 0);
1253 XtSetArg (args[0], XmNshadowThickness, &shadow);
1254 XtSetArg (args[1], XmNhighlightThickness, &highlight);
1255 XtGetValues(file_mgr_rec->current_directory_text, args, 2);
1257 get_text_pieces(file_mgr_data, width - 2*left_margin,
1258 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
1259 &path_len, &path_pixels);
1260 begin_x = left_margin + host_pixels - shadow - highlight;
1262 begin_x += prefix_pixels;
1263 XtSetArg (args[0], XmNleftOffset, begin_x);
1265 XtSetArg (args[1], XmNvalue, textString);
1266 XtSetValues(file_mgr_rec->current_directory_text, args, 2);
1267 XtSetArg (args[0], XmNcursorPosition, strlen(textString));
1268 XtSetValues(file_mgr_rec->current_directory_text, args, 1);
1270 XtSetArg (args[0], XmNallowShellResize, False);
1271 XtSetValues(file_mgr_rec->shell, args, 1);
1272 XtManageChild(file_mgr_rec->current_directory_text);
1273 XtSetArg (args[0], XmNallowShellResize, True);
1274 XtSetValues(file_mgr_rec->shell, args, 1);
1275 XRaiseWindow(XtDisplay(file_mgr_rec->current_directory_text),
1276 XtWindow(file_mgr_rec->current_directory_text));
1277 XmUpdateDisplay(file_mgr_rec->current_directory_text);
1278 XmProcessTraversal(file_mgr_rec->current_directory_text,
1279 XmTRAVERSE_CURRENT);
1281 XtAddCallback (file_mgr_rec->current_directory, XmNexposeCallback,
1282 CurrentDirExposed, file_mgr_rec);
1285 /************************************************************************
1287 * TimerEvent - timeout for double click on current Directory line. If
1288 * we get here we know it was a single click so lets post the
1289 * fast change to text widget.
1291 ***************************************************************************/
1294 XtPointer client_data,
1297 FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
1298 DialogData * dialog_data;
1299 FileMgrData *file_mgr_data;
1301 doubleClick = False;
1303 /* Got an accelerator after we were unposted */
1304 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1306 file_mgr_data = (FileMgrData *) dialog_data->data;
1308 ShowFastChangeDir(file_mgr_rec, file_mgr_data);
1311 /************************************************************************
1313 * ResizeFastText - resizes the fast change text widget due to changes
1314 * in the size of the FileManager window.
1316 *************************************************************************/
1319 FileMgrRec *file_mgr_rec,
1320 FileMgrData *file_mgr_data,
1327 /* nothing to do if not managed */
1328 if (!XtIsManaged(file_mgr_rec->current_directory_text))
1331 /* get width of current directory line */
1332 XtSetArg (args[0], XmNwidth, &width);
1333 XtGetValues (file_mgr_rec->current_directory, args, 1);
1335 /* get offset of the text widget */
1336 XtSetArg(args[0], XmNleftOffset, &left_offset);
1337 XtGetValues(file_mgr_rec->current_directory_text, args, 1);
1339 /* set text widget width = current_directory width minus left offset */
1340 XtSetArg (args[0], XmNwidth, width - left_offset);
1341 XtSetValues (file_mgr_rec->current_directory_text, args, 1);
1345 /*--------------------------------------------------------------------
1347 *------------------------------------------------------------------*/
1349 /* use Xmb functions if XFontSet is used. */
1351 get_textwidth( FileMgrData *fmd,
1357 switch(fmd->cd_fonttype)
1359 case XmFONT_IS_FONTSET:
1360 w = XmbTextEscapement(fmd->cd_fontset, str, len);
1362 case XmFONT_IS_FONT:
1363 w = XTextWidth(fmd->cd_font, str, len);
1371 draw_imagestring( Display *display,
1379 switch(fmd->cd_fonttype)
1381 case XmFONT_IS_FONTSET:
1382 XmbDrawImageString(display, d, fmd->cd_fontset, gc, x, y, text,
1385 case XmFONT_IS_FONT:
1386 XDrawImageString(display, d, gc, x, y, text, bytes);