2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: 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 ************************************<+>*************************************/
64 #include <Xm/TextFP.h>
65 #include <Xm/PushBG.h>
66 #include <Xm/DragDrop.h>
69 #include <Dt/DtNlUtils.h>
70 #include <Dt/Connect.h>
73 #include "SharedProcs.h"
78 #include "ChangeDir.h"
82 /******** Static Function Declarations ********/
84 static void CurrentDirChange(
85 XtPointer client_data,
86 DialogData *old_dialog_data,
87 DialogData *new_dialog_data,
88 XtPointer call_data) ;
89 static void CurrentDirClose(
90 XtPointer client_data,
91 DialogData *old_dialog_data,
92 DialogData *new_dialog_data) ;
93 static void CheckCurrentDirectorySelect(
94 FileMgrData *file_mgr_data ) ;
95 static void TimerEvent(
96 XtPointer client_data,
98 static void ResizeFastText(
99 FileMgrRec *file_mgr_rec,
100 FileMgrData *file_mgr_data,
102 static int get_textwidth(
106 static void draw_imagestring(
115 /******** End Static Function Declarations ********/
117 /* absolute value macro */
119 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
122 /* layout constants */
123 #define CUR_DIR_SPACING 5
126 /* local global varible to determine whether the user has double clicked
128 static Boolean doubleClick = False;
130 /*--------------------------------------------------------------------
133 * Given a width available for the current directory text,
134 * determines the text to be drawn in one of three formats:
136 * /path (non-restricted directory)
137 * /.../path (restricted directory)
138 * .../subpath (if the full path wouldn't fit)
140 * Returns the length (in chars) and width (in pixels) of each of
141 * the two components of the text:
142 * (1) prefix "/..." or "...", and (2) path or subpath.
143 * Returns True if the path was chopped because it wouldn't fit.
145 *------------------------------------------------------------------*/
149 FileMgrData *file_mgr_data,
155 int *prefix_pixels_p,
159 Boolean chopped = False;
165 char *next_part = NULL;
167 *host_len_p = *host_pixels_p = 0;
169 /* if restricted directory, path prefix is "/..." */
170 if (file_mgr_data->restricted_directory)
173 prefix_len = strlen("/...");
174 prefix_pixels = get_textwidth (file_mgr_data, "/...", prefix_len);
175 path_begin = file_mgr_data->current_directory +
176 strlen(file_mgr_data->restricted_directory);
177 if (*path_begin == '\0')
179 else if (*path_begin != '/')
187 path_begin = file_mgr_data->current_directory;
190 /* calculate path length & width */
191 path_len = strlen(path_begin);
192 path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
194 /* if whole path doesn't fit, we need to chop off pieces until it does */
195 if (prefix_pixels + path_pixels > width)
199 /* change the path prefix */
201 prefix_len = strlen("...");
202 prefix_pixels = get_textwidth (file_mgr_data, "...", prefix_len);
206 /* chop off the next piece (everything up to the next '/') */
208 next_part = DtStrchr(path_begin + 1, '/');
209 if (next_part == NULL)
211 /* Got here only when the last directory is still too
217 /* calculate new path length */
218 path_begin = next_part;
219 path_len = strlen(path_begin);
220 path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
222 /* keep going until it fits */
223 } while (prefix_pixels + path_pixels > width);
226 /* add the path to the buffer */
227 if( NULL == next_part )
229 /* Got here only when the last directory is still too
237 /* Going back one character at a time to see if it fit
239 path_pixels = get_textwidth( file_mgr_data, path_begin, len );
240 if( prefix_pixels + path_pixels < width )
249 buf[prefix_len] = 0x0;
255 strncpy (buf + prefix_len, path_begin, len);
257 *path_pixels_p = path_pixels;
262 strcpy (buf + prefix_len, path_begin);
263 *path_len_p = path_len;
264 *path_pixels_p = path_pixels;
268 *prefix_len_p = prefix_len;
269 *prefix_pixels_p = prefix_pixels;
274 /************************************************************************
276 * ShowChangeDirDialog
277 * Callback functions invoked from the Change Directory... menu
278 * item. This function displays the change directory dialog.
280 ************************************************************************/
286 XtPointer client_data,
289 FileMgrRec * file_mgr_rec;
290 DialogData * dialog_data;
291 FileMgrData * file_mgr_data;
292 ChangeDirData * change_dir_data;
293 ChangeDirRec * change_dir_rec;
296 char *tempStr, *tmpStr;
299 /* Set the menu item to insensitive to prevent multiple */
300 /* dialogs from being posted and get the area under the */
301 /* menu pane redrawn. */
305 if((int)client_data == FM_POPUP)
308 mbar = (Widget) XmGetPostedFromWidget(XtParent(w));
311 XtSetArg(args[0], XmNuserData, &file_mgr_rec);
312 XtGetValues(mbar, args, 1);
314 /* Ignore accelerators when we're insensitive */
315 if ((file_mgr_rec->menuStates & CHANGEDIR) == 0)
317 XSetInputFocus(XtDisplay(w),
318 XtWindow(file_mgr_rec->change_directoryBtn_child),
319 RevertToParent, CurrentTime);
325 /* Done only during a restore session */
326 file_mgr_rec = (FileMgrRec *)client_data;
329 /* Got an accelerator after we were unposted */
330 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
333 file_mgr_data = (FileMgrData *) dialog_data->data;
334 change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
335 change_dir_data->file_mgr_rec = (XtPointer) file_mgr_rec;
337 file_mgr_rec->menuStates &= ~CHANGEDIR;
339 _DtShowDialog (file_mgr_rec->shell, (Widget)NULL, (XtPointer)file_mgr_rec,
340 file_mgr_data->change_dir,
341 CurrentDirChange, (XtPointer)file_mgr_rec,
342 CurrentDirClose, (XtPointer)file_mgr_rec, (char *)NULL,
343 False, False, (char *)NULL, (XClassHint *)NULL);
345 /* Save a ptr to file_mgr_rec in the find dialogs structure */
346 change_dir_rec = (ChangeDirRec *)_DtGetDialogInstance(
347 file_mgr_data->change_dir);
349 if(file_mgr_data->title != NULL &&
350 strcmp(file_mgr_data->helpVol, DTFILE_HELP_NAME) != 0)
352 tmpStr = GETMESSAGE(2,15, "Go To");
353 tempStr = (char *)XtMalloc(strlen(tmpStr) +
354 strlen(file_mgr_data->title) + 5);
355 sprintf(tempStr, "%s - %s", file_mgr_data->title, tmpStr);
359 tmpStr = (GETMESSAGE(2,17, "File Manager - Go To"));
360 tempStr = XtNewString(tmpStr);
362 XtSetArg (args[0], XmNtitle, tempStr);
363 XtSetValues (XtParent (change_dir_rec->change_dir), args, 1);
366 file_mgr_rec->change_directoryBtn_child=XtParent (change_dir_rec->change_dir);
372 /************************************************************************
375 * When a Button1 selection occurs on the current directory line,
376 * see if it occurred within the directory path, highlight the
377 * selected sub-path, or if the sub-path was already highlighted,
378 * set the current directory to the path and dehighlight.
380 ************************************************************************/
385 XtPointer client_data,
386 XtPointer call_data )
388 FileMgrRec *file_mgr_rec = (FileMgrRec *) client_data;
389 DialogData *dialog_data;
390 FileMgrData *file_mgr_data;
391 char buf[2*MAX_PATH];
392 char host_name[MAX_PATH];
401 XmDrawnButtonCallbackStruct *button_data;
403 Dimension width, highlight, shadow, margin;
414 static XtIntervalId TimerId;
416 /* if doubleClick is true than we have a double click so we want
417 * to change to the new directory that the user double clicked on
420 XtRemoveTimeOut(TimerId);
422 button_data = (XmDrawnButtonCallbackStruct *) call_data;
423 event = (XButtonEvent *) button_data->event;
425 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
426 file_mgr_data = (FileMgrData *) dialog_data->data;
428 /* Get layout values */
429 XtSetArg (args[0], XmNwidth, &width);
430 XtSetArg (args[1], XmNhighlightThickness, &highlight);
431 XtGetValues (w, args, 2);
432 XtSetArg (args[0], XmNshadowThickness, &shadow);
433 XtSetArg (args[1], XmNmarginWidth, &margin);
434 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
435 left_margin = highlight + shadow + margin;
437 /* Get the starting and ending locations of the current */
438 /* directory text. */
439 chopped = get_text_pieces(file_mgr_data, width - 2*left_margin,
440 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
441 &path_len, &path_pixels);
443 begin_x = left_margin;
444 end_x = begin_x + host_pixels + prefix_pixels + path_pixels;
446 /* Get the selected path */
447 if (event->x < begin_x || event->x >= end_x)
449 /* click outside the directory text: nothing selected */
452 else if (event->x < begin_x + host_pixels ||
453 event->x < begin_x + host_pixels + prefix_pixels && !chopped)
455 /* click on host name or "/..." prefix: root selected */
456 if (file_mgr_data->restricted_directory)
457 new_select = XtNewString(file_mgr_data->restricted_directory);
459 new_select = XtNewString("/");
461 else if (event->x < begin_x + host_pixels + prefix_pixels && chopped)
463 /* click on "..." prefix: directory above the visible piece selected */
464 len = strlen(file_mgr_data->current_directory) - path_len;
465 new_select = (char *) XtMalloc(len + 1);
466 memcpy(new_select, file_mgr_data->current_directory, len);
469 else /* event->x >= begin_x + host_pixels + prefix_pixels */
471 /* click on the path: determine which subdirectory selected */
472 begin_x += host_pixels + prefix_pixels;
473 i = host_len + prefix_len;
474 swidth = get_textwidth(file_mgr_data, "/", strlen("/")) / 2;
476 while (begin_x - swidth < event->x)
478 /* find next '/' in path */
479 ptr = DtStrchr(buf + i, '/');
482 i = host_len + prefix_len + path_len + 1;
486 /* get x-position of next path component */
487 len = ((ptr + 1) - buf) - i;
488 begin_x += get_textwidth(file_mgr_data, buf + i, len);
492 /* if we have a restricted diretory and i == 5 ("/.../") then we want
493 the len to be the restricted directory */
494 if (file_mgr_data->restricted_directory && i == 5)
495 len = strlen(file_mgr_data->restricted_directory);
497 len = strlen(file_mgr_data->current_directory)
498 - (host_len + prefix_len + path_len - i) - 1;
499 new_select = (char *) XtMalloc(len + 1);
501 strcpy(new_select, "/");
504 memcpy(new_select, file_mgr_data->current_directory, len);
509 /* in restricted mode, don't allow going above the user's home dir */
510 if (new_select != NULL && restrictMode)
512 /* check if new_select is the same as or a subdirectory of $HOME */
513 len = strlen(users_home_dir);
514 if (strncmp(new_select, users_home_dir, len) != 0
515 || new_select[len] != '\0' && new_select[len] != '/')
517 /* change new_select to $HOME */
519 new_select = XtNewString(users_home_dir);
524 /* If the path is the same as what is already selected, */
525 /* free cd_select, set the directory to the selected */
526 /* directory, redraw the directory display. */
528 /* If the path was different, set cd_select to the */
529 /* selected directory and redraw the directory. */
531 if (new_select != NULL && file_mgr_data->cd_select != NULL &&
532 strcmp(new_select, file_mgr_data->cd_select) == 0)
534 XtFree (file_mgr_data->cd_select);
535 file_mgr_data->cd_select = NULL;
537 strcpy(buf, new_select);
538 strcpy(host_name, file_mgr_data->host);
540 if (strcmp (buf, file_mgr_data->current_directory) == 0)
541 FileMgrReread (file_mgr_rec);
543 ShowNewDirectory (file_mgr_data, host_name, buf);
549 XtFree (file_mgr_data->cd_select);
550 file_mgr_data->cd_select = new_select;
556 DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
561 TimerId = XtAppAddTimeOut (XtWidgetToApplicationContext (w),
562 XtGetMultiClickTime(XtDisplay(w)),
563 (XtTimerCallbackProc) TimerEvent,
564 (XtPointer) file_mgr_rec);
570 /************************************************************************
572 * CurrentDirDropCallback
573 * Callback function invoked upon an action on the change view drop.
575 ************************************************************************/
578 CurrentDirDropCallback(
580 XtPointer client_data,
581 XtPointer call_data )
583 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
584 XmAnyCallbackStruct * callback;
585 DialogData * dialog_data;
586 FileMgrData * file_mgr_data;
587 char host_name[MAX_PATH];
589 callback = (XmAnyCallbackStruct *) call_data;
590 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
591 file_mgr_data = (FileMgrData *) dialog_data->data;
593 if (callback->reason == XmCR_DEFAULT_ACTION)
595 strcpy(host_name, file_mgr_data->host);
596 ShowNewDirectory (file_mgr_data, host_name,
597 _DtPName (file_mgr_data->current_directory));
602 /************************************************************************
604 * CurrentDirIconCallback
605 * Callback function invoked upon an action occuring on an icon.
607 ************************************************************************/
610 CurrentDirIconCallback(
612 XtPointer client_data,
613 XtPointer call_data )
615 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
616 XmAnyCallbackStruct * callback;
617 XButtonEvent * event;
618 DialogData * dialog_data;
619 FileMgrData * file_mgr_data;
621 callback = (XmAnyCallbackStruct *) call_data;
622 event = (XButtonEvent *) callback->event;
623 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
624 file_mgr_data = (FileMgrData *) dialog_data->data;
626 if (callback->reason == XmCR_DRAG)
628 /* Do nothing if a Button 1 drag is already ramping up */
632 /* Save starting X and Y, for threshold detection */
633 initialDragX = event->x;
634 initialDragY = event->y;
636 /* Flag that a Button 2 drag is ramping up */
637 B2DragPossible = True;
639 UnpostTextField(file_mgr_data);
641 else if (callback->reason == XmCR_ARM)
643 /* Do nothing if a Button 2 drag is already ramping up */
647 /* Save starting X and Y, for threshold detection */
648 initialDragX = event->x;
649 initialDragY = event->y;
651 /* Flag that a Button 1 drag is ramping up */
652 B1DragPossible = True;
654 /* but since we're in the current directory icon we don't want to
655 process on the button up */
656 ProcessBtnUpCD = False;
658 UnpostTextField(file_mgr_data);
660 else if (callback->reason == XmCR_DEFAULT_ACTION)
662 /* We now know that a drag operation won't be starting up */
663 B1DragPossible = False;
664 B2DragPossible = False;
666 UnpostTextField(file_mgr_data);
668 /* Default action is to reread the directory */
669 FileMgrReread (file_mgr_rec);
671 else if ((callback->reason == XmCR_SELECT) ||
672 (callback->reason == XmCR_DISARM) ||
673 (callback->reason == XmCR_DROP))
675 /* We now know that a drag operation won't be starting up */
676 B1DragPossible = False;
677 B2DragPossible = False;
683 * This function processes motion events anytime a B1 or B2 drag operation
684 * has the potential of starting. When the drag threshold is surpassed,
685 * a drag operation will be started.
689 CurrentDirectoryIconMotion(
691 XtPointer client_data,
695 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
696 DialogData * dialog_data;
697 FileMgrData * file_mgr_data;
706 if ((B1DragPossible && (event->xmotion.state & Button1Mask)) ||
707 (B2DragPossible && (event->xmotion.state & Button2Mask)))
709 /* Have we passed the drag threshold? */
710 diffX = initialDragX - event->xmotion.x;
711 diffY = initialDragY - event->xmotion.y;
713 if ((ABS(diffX) >= dragThreshold) || (ABS(diffY) >= dragThreshold))
715 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
716 file_mgr_data = (FileMgrData *) dialog_data->data;
718 initiating_view = (XtPointer) file_mgr_data;
719 dirIcon = file_mgr_rec->current_directory_icon;
720 StartDrag(dirIcon, NULL, event);
726 /************************************************************************
729 * Callback functions invoked from the current directory display
730 * drawn button. This function extracts some structures and calls
731 * the directory display function.
733 ************************************************************************/
738 XtPointer client_data,
739 XtPointer call_data )
741 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
742 DialogData * dialog_data;
743 FileMgrData * file_mgr_data;
745 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
747 /* Check to see if the view has been closed */
749 if (dialog_data == NULL) return;
751 file_mgr_data = (FileMgrData *) dialog_data->data;
753 if (file_mgr_data->cd_normal_gc != 0)
754 DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
760 /************************************************************************
763 * Construct the status message (normally "x Items, y Hidden").
764 * Returns True if the message is deemed "important".
766 * @@@ Note 2/17/95: messages below containing "Item(s)" should really
767 * be just "Item", but the message catalog is frozen at this time, so
768 * we can't fix this now. (In practice, it doesn't matter, because
769 * the item count should always be > 1, since every directory shoule
770 * contain at least two files "." and "..")
772 ************************************************************************/
776 FileMgrData *file_mgr_data,
783 FileViewData **file_view_data;
786 * If we are currently busy reading a directory, display a progress
787 * message instead of the normal "x Items, y Hidden" message.
789 if (file_mgr_data->busy_status == initiating_readdir ||
790 file_mgr_data->busy_status == busy_readdir)
792 if (file_mgr_data->busy_detail == 0)
793 sprintf (buf, (GETMESSAGE(3,5, "Reading ...")));
794 else if (file_mgr_data->busy_detail == 1)
795 sprintf (buf, (GETMESSAGE(3,11, "%d Item(s)...")),
796 file_mgr_data->busy_detail);
798 sprintf (buf, (GETMESSAGE(3,9, "%3d Items ...")),
799 file_mgr_data->busy_detail);
801 return True; /* this message deemed important! */
804 else if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
807 * In tree mode, we only show a count of the hidden files
808 * in branches that are currently expanded.
809 * The idea is we want to show how many additional files would
810 * show up if the user turned on the "Show Hidden" option.
813 for (i = 0; i < file_mgr_data->directory_count; i++)
815 file_view_data = file_mgr_data->directory_set[i]->file_view_data;
816 if (file_view_data == NULL)
819 ts = file_mgr_data->directory_set[i]->sub_root->ts;
821 continue; /* this branch is not expanded */
823 for (j = 0; j < file_mgr_data->directory_set[i]->file_count; j++)
825 if (file_view_data[j]->filtered &&
826 (ts == tsAll || file_view_data[j]->file_data->is_subdir))
832 sprintf (buf, (GETMESSAGE(3,6, "%d Hidden")), n_hidden);
840 * In flat mode, we only show a total count of all files
841 * and a count of hidden files.
843 n_files = file_mgr_data->directory_set[0]->file_count;
845 sprintf( buf, (GETMESSAGE(11,31, "Error while reading %s")), file_mgr_data->current_directory );
846 else if( file_mgr_data == trashFileMgrData )
848 n_hidden = file_mgr_data->directory_set[0]->filtered_file_count;
849 sprintf (buf, (GETMESSAGE(3,10, "%d Item(s)")),
854 n_files -= file_mgr_data->directory_set[0]->invisible_file_count;
855 n_hidden = file_mgr_data->directory_set[0]->filtered_file_count -
856 file_mgr_data->directory_set[0]->invisible_file_count;
858 sprintf (buf, (GETMESSAGE(3,12, "%d Item(s) %d Hidden")),
861 sprintf (buf, (GETMESSAGE(3,7, "%d Items %d Hidden")),
870 /************************************************************************
872 * DrawCurrentDirectory
873 * Draw the current directory display area, including the hostname,
874 * the current directory, any highlighted sub-path of the directory,
875 * the file count and the number of selected files.
877 ************************************************************************/
880 DrawCurrentDirectory(
882 FileMgrRec *file_mgr_rec,
883 FileMgrData *file_mgr_data )
886 Dimension width, height, highlight, shadow, margin, twidth;
887 XFontSetExtents *extents;
892 char buf[2*MAX_PATH];
893 char msg[21+MAX_PATH];
908 /* Get layout values */
909 XtSetArg (args[0], XmNwidth, &width);
910 XtSetArg (args[1], XmNheight, &height);
911 XtSetArg (args[2], XmNhighlightThickness, &highlight);
912 XtGetValues (w, args, 3);
913 XtSetArg (args[0], XmNshadowThickness, &shadow);
914 XtSetArg (args[1], XmNmarginWidth, &margin);
915 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
917 if(file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET) {
918 extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
919 font_yoffset = -(extents->max_logical_extent.y);
920 font_height = extents->max_logical_extent.height;
924 font_yoffset = file_mgr_data->cd_font->ascent;
925 font_height = file_mgr_data->cd_font->ascent +
926 file_mgr_data->cd_font->descent;
928 top_margin = (height > (Dimension)font_height)? (Dimension)(height - font_height + 1)/(Dimension)2: 0;
929 left_margin = highlight + shadow + margin;
931 /* Ensure the area is cleared out. */
932 XClearArea (XtDisplay (w), XtWindow (w),
933 highlight, highlight,
934 width - 2*highlight, height - 2*highlight,
938 * If there is no status line and no iconic path,
939 * we will want yo draw the "x Files y Hidden" message here.
941 if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
944 * GetStatusMsg() returns True if the status msg is "important".
945 * In this case, make sure we leave room for it
947 msg_drawn = GetStatusMsg(file_mgr_data, msg);
948 msg_width = get_textwidth (file_mgr_data, msg, strlen(msg));
953 draw_x = left_margin;
954 if( draw_x < 0 || (Dimension) draw_x > width ) /* Make sure that it's in bound */
957 draw_y = top_margin + font_yoffset;
958 if( draw_y < 0 || (Dimension) draw_y > height ) /* Make sure that it's in bound */
963 /* get the text pieces */
964 dir_width = width - 2*left_margin;
966 dir_width -= CUR_DIR_SPACING + msg_width;
967 chopped = get_text_pieces(file_mgr_data, dir_width,
968 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
969 &path_len, &path_pixels);
972 * go check and change the file_mgr_data->cd_select, make sure its not
973 * longer than the file_mgr_data->current_directory.
975 CheckCurrentDirectorySelect(file_mgr_data);
977 /* draw the host and paths */
978 if (!file_mgr_data->fast_cd_enabled)
980 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
981 file_mgr_data->cd_normal_gc, draw_x, draw_y,
982 buf, host_len + prefix_len + path_len);
984 else if (file_mgr_data->restricted_directory)
986 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
987 file_mgr_data->cd_normal_gc, draw_x, draw_y,
988 buf, host_len + prefix_len);
992 * If there is no status line and no iconic path, and we have
993 * room left, draw the "x Files y Hidden" message here.
995 if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
997 /* determine where the message could begin */
998 if (!file_mgr_data->fast_cd_enabled)
999 draw_x += host_pixels + prefix_pixels + path_pixels;
1002 XtSetArg(args[0], XmNwidth, &twidth);
1003 XtGetValues(file_mgr_rec->current_directory_text, args, 1);
1004 if (file_mgr_data->restricted_directory && !chopped)
1005 draw_x += host_pixels + prefix_pixels + twidth;
1007 draw_x += host_pixels + twidth;
1010 /* if there is enough space left, draw the message */
1011 if ((Dimension)(draw_x + CUR_DIR_SPACING + msg_width + left_margin) <= width)
1013 draw_x = width - left_margin - msg_width;
1014 draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
1015 file_mgr_data->cd_normal_gc, draw_x, draw_y,
1017 draw_x -= shadow + CUR_DIR_SPACING; /* right edge of shadow */
1025 draw_x = width - (highlight + shadow);
1027 /* draw the shadow */
1028 if (!file_mgr_data->fast_cd_enabled)
1030 int shadow_width = draw_x - highlight;
1031 int shadow_height = height - 2*highlight;
1032 XmTextFieldWidget tf =
1033 (XmTextFieldWidget)file_mgr_rec->current_directory_text;
1035 XmeDrawShadows(XtDisplay(w), XtWindow(w),
1036 tf->primitive.top_shadow_GC,
1037 tf->primitive.bottom_shadow_GC,
1038 highlight, highlight, shadow_width, shadow_height,
1039 shadow, XmSHADOW_IN);
1045 /************************************************************************
1048 * Callback functions invoked from the current directory dialog's
1049 * apply button being pressed. This function updates and redisplays
1050 * the current directory information.
1052 ************************************************************************/
1056 XtPointer client_data,
1057 DialogData *old_dialog_data,
1058 DialogData *new_dialog_data,
1059 XtPointer call_data )
1061 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
1062 DialogData * dialog_data;
1063 FileMgrData * file_mgr_data;
1064 ChangeDirData * new_change_dir_data;
1065 ChangeDirData * old_change_dir_data;
1066 char path[MAX_PATH];
1067 char host_name[MAX_PATH];
1071 /* Get a pointer file manager's data structure, free up the */
1072 /* old current directory and copy in a new one. Free up the */
1073 /* old selected sub-path, update the file manager's internal */
1074 /* data, and redraw the directory. */
1076 dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
1077 file_mgr_data = (FileMgrData *) dialog_data->data;
1079 if (file_mgr_data->cd_select != NULL)
1081 XtFree (file_mgr_data->cd_select);
1082 file_mgr_data->cd_select = NULL;
1085 old_change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
1086 new_change_dir_data = (ChangeDirData *) new_dialog_data->data;
1088 new_change_dir_data->host_name = XtNewString(old_change_dir_data->host_name);
1089 new_change_dir_data->file_mgr_rec = old_change_dir_data->file_mgr_rec;
1091 _DtHideDialog(old_dialog_data, False);
1093 new_change_dir_data->displayed = False;
1095 file_mgr_data->change_dir->data = (XtPointer) new_change_dir_data;
1096 new_dialog_data->data = (XtPointer) old_change_dir_data;
1097 _DtFreeDialogData (new_dialog_data);
1098 file_mgr_rec->menuStates |= CHANGEDIR;
1101 /* Process call_data into a hostname and directory name. */
1103 ShowNewDirectory (file_mgr_data,
1104 ((ChangeDirData *)file_mgr_data->change_dir->data)->host_name,
1111 /************************************************************************
1114 * Callback functions invoked from the current directory dialog's
1115 * close button being pressed. This function resensitizes the
1116 * Change Directory... menu item.
1118 ************************************************************************/
1123 XtPointer client_data,
1124 DialogData *old_dialog_data,
1125 DialogData *new_dialog_data )
1127 FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
1129 _DtFreeDialogData (new_dialog_data);
1130 file_mgr_rec->menuStates |= CHANGEDIR;
1133 /************************************************************************
1135 * CheckCurrentDirectorySelect
1136 * Before calling DrawCurrentDirectorySelect() this function
1137 * makes sure that the fm->cd_select isn't longer than the
1138 * fm->current_directory. If it is it reconfigures fm->cd_select
1139 * to hold no more than what fm->current_directory is.
1141 ************************************************************************/
1143 CheckCurrentDirectorySelect(
1144 FileMgrData *file_mgr_data )
1146 int length_cd, length_cd_s;
1149 if (file_mgr_data == NULL ||
1150 file_mgr_data->cd_select == NULL ||
1151 file_mgr_data->current_directory == NULL)
1154 /* get the true lengths of current_directory and current_directory_select */
1155 length_cd = strlen(file_mgr_data->current_directory);
1156 length_cd_s = strlen(file_mgr_data->cd_select);
1158 /* if cd is larger than cd_select than we have now problem */
1159 if(length_cd >= length_cd_s)
1162 /* we need to recalculate the cd_select */
1163 str = XtNewString(file_mgr_data->cd_select);
1166 ptr = strrchr(str, '/');
1168 length_cd_s = strlen(str);
1169 if(length_cd > length_cd_s)
1171 XtFree(file_mgr_data->cd_select);
1172 file_mgr_data->cd_select = (char *)XtMalloc(strlen(str) + 1);
1173 strcpy(file_mgr_data->cd_select, str);
1180 /************************************************************************
1183 * Post the fast change to text widget.
1185 ***************************************************************************/
1188 FileMgrRec *file_mgr_rec,
1189 FileMgrData *file_mgr_data )
1193 Dimension width, height;
1194 Dimension shadow, highlight, margin;
1195 char buf[2*MAX_PATH];
1206 doubleClick = False;
1208 XtRemoveAllCallbacks (file_mgr_rec->current_directory, XmNexposeCallback);
1210 XtFree (file_mgr_data->cd_select);
1211 file_mgr_data->cd_select = NULL;
1213 file_mgr_data->fast_cd_enabled = True;
1215 /* if not a toolbox, just put the current directory in text widget */
1216 if (file_mgr_data->restricted_directory == NULL)
1218 if (strcmp(file_mgr_data->host, home_host_name) == 0)
1219 textString = XtNewString(file_mgr_data->current_directory);
1221 textString = DtCreateContextString(file_mgr_data->host,
1222 file_mgr_data->current_directory,
1225 else /* is a toolbox, so put the subset of what the toolbox is in the text*/
1229 ptr = file_mgr_data->current_directory +
1230 strlen(file_mgr_data->restricted_directory);
1231 if (strcmp(ptr, "") == 0)
1232 textString = XtNewString("/");
1234 textString = XtNewString(ptr);
1236 begin_x = get_textwidth (file_mgr_data, textString, strlen (textString));
1238 /* Get layout values */
1239 XtSetArg (args[0], XmNwidth, &width);
1240 XtSetArg (args[1], XmNhighlightThickness, &highlight);
1241 XtGetValues (file_mgr_rec->current_directory, args, 2);
1242 XtSetArg (args[0], XmNshadowThickness, &shadow);
1243 XtSetArg (args[1], XmNmarginWidth, &margin);
1244 XtGetValues (file_mgr_rec->current_directory_text, args, 2);
1245 left_margin = highlight + shadow + margin;
1247 if(file_mgr_data->restricted_directory == NULL)
1248 XtSetArg (args[0], XmNleftOffset, 0);
1251 XtSetArg (args[0], XmNshadowThickness, &shadow);
1252 XtSetArg (args[1], XmNhighlightThickness, &highlight);
1253 XtGetValues(file_mgr_rec->current_directory_text, args, 2);
1255 get_text_pieces(file_mgr_data, width - 2*left_margin,
1256 buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
1257 &path_len, &path_pixels);
1258 begin_x = left_margin + host_pixels - shadow - highlight;
1260 begin_x += prefix_pixels;
1261 XtSetArg (args[0], XmNleftOffset, begin_x);
1263 XtSetArg (args[1], XmNvalue, textString);
1264 XtSetValues(file_mgr_rec->current_directory_text, args, 2);
1265 XtSetArg (args[0], XmNcursorPosition, strlen(textString));
1266 XtSetValues(file_mgr_rec->current_directory_text, args, 1);
1268 XtSetArg (args[0], XmNallowShellResize, False);
1269 XtSetValues(file_mgr_rec->shell, args, 1);
1270 XtManageChild(file_mgr_rec->current_directory_text);
1271 XtSetArg (args[0], XmNallowShellResize, True);
1272 XtSetValues(file_mgr_rec->shell, args, 1);
1273 XRaiseWindow(XtDisplay(file_mgr_rec->current_directory_text),
1274 XtWindow(file_mgr_rec->current_directory_text));
1275 XmUpdateDisplay(file_mgr_rec->current_directory_text);
1276 XmProcessTraversal(file_mgr_rec->current_directory_text,
1277 XmTRAVERSE_CURRENT);
1279 XtAddCallback (file_mgr_rec->current_directory, XmNexposeCallback,
1280 CurrentDirExposed, file_mgr_rec);
1283 /************************************************************************
1285 * TimerEvent - timeout for double click on current Directory line. If
1286 * we get here we know it was a single click so lets post the
1287 * fast change to text widget.
1289 ***************************************************************************/
1292 XtPointer client_data,
1295 FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
1296 DialogData * dialog_data;
1297 FileMgrData *file_mgr_data;
1299 doubleClick = False;
1301 /* Got an accelerator after we were unposted */
1302 if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
1304 file_mgr_data = (FileMgrData *) dialog_data->data;
1306 ShowFastChangeDir(file_mgr_rec, file_mgr_data);
1309 /************************************************************************
1311 * ResizeFastText - resizes the fast change text widget due to changes
1312 * in the size of the FileManager window.
1314 *************************************************************************/
1317 FileMgrRec *file_mgr_rec,
1318 FileMgrData *file_mgr_data,
1325 /* nothing to do if not managed */
1326 if (!XtIsManaged(file_mgr_rec->current_directory_text))
1329 /* get width of current directory line */
1330 XtSetArg (args[0], XmNwidth, &width);
1331 XtGetValues (file_mgr_rec->current_directory, args, 1);
1333 /* get offset of the text widget */
1334 XtSetArg(args[0], XmNleftOffset, &left_offset);
1335 XtGetValues(file_mgr_rec->current_directory_text, args, 1);
1337 /* set text widget width = current_directory width minus left offset */
1338 XtSetArg (args[0], XmNwidth, width - left_offset);
1339 XtSetValues (file_mgr_rec->current_directory_text, args, 1);
1343 /*--------------------------------------------------------------------
1345 *------------------------------------------------------------------*/
1347 /* use Xmb functions if XFontSet is used. */
1349 get_textwidth( FileMgrData *fmd,
1355 switch(fmd->cd_fonttype)
1357 case XmFONT_IS_FONTSET:
1358 w = XmbTextEscapement(fmd->cd_fontset, str, len);
1360 case XmFONT_IS_FONT:
1361 w = XTextWidth(fmd->cd_font, str, len);
1369 draw_imagestring( Display *display,
1377 switch(fmd->cd_fonttype)
1379 case XmFONT_IS_FONTSET:
1380 XmbDrawImageString(display, d, fmd->cd_fontset, gc, x, y, text,
1383 case XmFONT_IS_FONT:
1384 XDrawImageString(display, d, gc, x, y, text, bytes);