Files
cdesktop/cde/programs/dtfile/ChangeDirP.c
Lev Kujawski 356ac2f327 Purge unused Freetype dependency from CDE
config/cf/{DragonFly,OpenBSD,darwin}.cf: Remove Freetype imake settings
config/cf/darwinLib.tmpl: Do not link against Freetype
debian/control: Remove Freetype and Xft dependencies
*/Imakefile: Purge Freetype includes

lib/DtWidget/ComboBoxP.h
lib/DtWidget/SpinBoxP.h
programs/dtfile/ChangeDirP.c
programs/dtlogin/vgcallback.c
    Undefine USE_XFT so Motif 2.3 doesn't pull in Freetype

CDE included Freetype and Xft solely to satisfy builds of Motif with
Xft support enabled. However, as CDE only supports bitmap fonts, this
dependency was entirely superfluous and unnecessarily broke backwards
compatibility with older systems.
2021-06-02 19:56:26 -06:00

1393 lines
42 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: ChangeDirP.c /main/8 1998/04/01 15:05:07 rafi $ */
/************************************<+>*************************************
****************************************************************************
*
* FILE: ChangeDirP.c
*
* COMPONENT_NAME: Desktop File Manager (dtfile)
*
* Description: Processing functions for the change directory display
* line and the current directory dialog.
*
* FUNCTIONS: ABS
* CheckCurrentDirectorySelect
* CurrentDirChange
* CurrentDirClose
* CurrentDirDropCallback
* CurrentDirExposed
* CurrentDirIconCallback
* CurrentDirSelected
* CurrentDirectoryIconMotion
* DrawCurrentDirectory
* GetStatusMsg
* ResizeFastText
* ShowChangeDirDialog
* ShowFastChangeDir
* TimerEvent
* draw_imagestring
* get_text_pieces
* get_textwidth
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
*
****************************************************************************
************************************<+>*************************************/
#include <limits.h>
#include <Xm/Xm.h>
#include <Xm/XmP.h>
#include <Xm/DrawP.h>
#undef USE_XFT
#include <Xm/TextFP.h>
#include <Xm/PushBG.h>
#include <Xm/DragDrop.h>
#include <Xm/RowColumn.h>
#include <Dt/Icon.h>
#include <Dt/IconP.h>
#include <Dt/DtNlUtils.h>
#include <Dt/Connect.h>
#include <Dt/FileM.h>
#include "Encaps.h"
#include "SharedProcs.h"
#include "Desktop.h"
#include "FileMgr.h"
#include "Main.h"
#include "ChangeDir.h"
#include "Prefs.h"
/******** Static Function Declarations ********/
static void CurrentDirChange(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data,
XtPointer call_data) ;
static void CurrentDirClose(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data) ;
static void CheckCurrentDirectorySelect(
FileMgrData *file_mgr_data ) ;
static void TimerEvent(
XtPointer client_data,
XtIntervalId *id );
static void ResizeFastText(
FileMgrRec *file_mgr_rec,
FileMgrData *file_mgr_data,
short columns) ;
static int get_textwidth(
FileMgrData *fmd,
char *str,
int len);
static void draw_imagestring(
Display *display,
Drawable d,
FileMgrData *fmd,
GC gc,
int x, int y,
char *text,
int bytes);
/******** End Static Function Declarations ********/
/* absolute value macro */
#ifndef ABS
#define ABS(x) (((x) > 0) ? (x) : (-(x)))
#endif
/* layout constants */
#define CUR_DIR_SPACING 5
/* local global varible to determine whether the user has double clicked
or not */
static Boolean doubleClick = False;
/*--------------------------------------------------------------------
* get_text_pieces:
*
* Given a width available for the current directory text,
* determines the text to be drawn in one of three formats:
*
* /path (non-restricted directory)
* /.../path (restricted directory)
* .../subpath (if the full path wouldn't fit)
*
* Returns the length (in chars) and width (in pixels) of each of
* the two components of the text:
* (1) prefix "/..." or "...", and (2) path or subpath.
* Returns True if the path was chopped because it wouldn't fit.
*
*------------------------------------------------------------------*/
static Boolean
get_text_pieces(
FileMgrData *file_mgr_data,
int width,
char buf[],
int *host_len_p,
int *host_pixels_p,
int *prefix_len_p,
int *prefix_pixels_p,
int *path_len_p,
int *path_pixels_p)
{
Boolean chopped = False;
int prefix_len;
int prefix_pixels;
int path_len;
int path_pixels;
char *path_begin;
char *next_part = NULL;
*host_len_p = *host_pixels_p = 0;
/* if restricted directory, path prefix is "/..." */
if (file_mgr_data->restricted_directory)
{
strcpy(buf, "/...");
prefix_len = strlen("/...");
prefix_pixels = get_textwidth (file_mgr_data, "/...", prefix_len);
path_begin = file_mgr_data->current_directory +
strlen(file_mgr_data->restricted_directory);
if (*path_begin == '\0')
path_begin = "/";
else if (*path_begin != '/')
-- path_begin;
}
else
{
prefix_len = 0;
prefix_pixels = 0;
path_begin = file_mgr_data->current_directory;
}
/* calculate path length & width */
path_len = strlen(path_begin);
path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
/* if whole path doesn't fit, we need to chop off pieces until it does */
if (prefix_pixels + path_pixels > width)
{
chopped = True;
/* change the path prefix */
strcpy(buf, "...");
prefix_len = strlen("...");
prefix_pixels = get_textwidth (file_mgr_data, "...", prefix_len);
do
{
/* chop off the next piece (everything up to the next '/') */
next_part = NULL;
next_part = DtStrchr(path_begin + 1, '/');
if (next_part == NULL)
{
/* Got here only when the last directory is still too
long to display
*/
break;
}
/* calculate new path length */
path_begin = next_part;
path_len = strlen(path_begin);
path_pixels = get_textwidth (file_mgr_data, path_begin, path_len);
/* keep going until it fits */
} while (prefix_pixels + path_pixels > width);
}
/* add the path to the buffer */
if( NULL == next_part )
{
/* Got here only when the last directory is still too
long to display
*/
int len = path_len;
char saved_char;
while( 0 != len )
{
/* Going back one character at a time to see if it fit
*/
path_pixels = get_textwidth( file_mgr_data, path_begin, len );
if( prefix_pixels + path_pixels < width )
{
break;
}
--len;
}
if( 0 == len )
{
buf[prefix_len] = 0x0;
*path_len_p = 0;
*path_pixels_p = 0;
}
else
{
strncpy (buf + prefix_len, path_begin, len);
*path_len_p = len;
*path_pixels_p = path_pixels;
}
}
else
{
strcpy (buf + prefix_len, path_begin);
*path_len_p = path_len;
*path_pixels_p = path_pixels;
}
/* return values */
*prefix_len_p = prefix_len;
*prefix_pixels_p = prefix_pixels;
return chopped;
}
/************************************************************************
*
* ShowChangeDirDialog
* Callback functions invoked from the Change Directory... menu
* item. This function displays the change directory dialog.
*
************************************************************************/
/*ARGSUSED*/
void
ShowChangeDirDialog(
Widget w,
XtPointer client_data,
XtPointer callback )
{
FileMgrRec * file_mgr_rec;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
ChangeDirData * change_dir_data;
ChangeDirRec * change_dir_rec;
Arg args[1];
Widget mbar;
char *tempStr, *tmpStr;
/* Set the menu item to insensitive to prevent multiple */
/* dialogs from being posted and get the area under the */
/* menu pane redrawn. */
if (w)
{
if((XtArgVal)client_data == FM_POPUP)
mbar = XtParent(w);
else
mbar = (Widget) XmGetPostedFromWidget(XtParent(w));
XmUpdateDisplay (w);
XtSetArg(args[0], XmNuserData, &file_mgr_rec);
XtGetValues(mbar, args, 1);
/* Ignore accelerators when we're insensitive */
if ((file_mgr_rec->menuStates & CHANGEDIR) == 0)
{
XSetInputFocus(XtDisplay(w),
XtWindow(file_mgr_rec->change_directoryBtn_child),
RevertToParent, CurrentTime);
return;
}
}
else
{
/* Done only during a restore session */
file_mgr_rec = (FileMgrRec *)client_data;
}
/* Got an accelerator after we were unposted */
if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
return;
file_mgr_data = (FileMgrData *) dialog_data->data;
change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
change_dir_data->file_mgr_rec = (XtPointer) file_mgr_rec;
file_mgr_rec->menuStates &= ~CHANGEDIR;
_DtShowDialog (file_mgr_rec->shell, (Widget)NULL, (XtPointer)file_mgr_rec,
file_mgr_data->change_dir,
CurrentDirChange, (XtPointer)file_mgr_rec,
CurrentDirClose, (XtPointer)file_mgr_rec, (char *)NULL,
False, False, (char *)NULL, (XClassHint *)NULL);
/* Save a ptr to file_mgr_rec in the find dialogs structure */
change_dir_rec = (ChangeDirRec *)_DtGetDialogInstance(
file_mgr_data->change_dir);
if(file_mgr_data->title != NULL &&
strcmp(file_mgr_data->helpVol, DTFILE_HELP_NAME) != 0)
{
tmpStr = GETMESSAGE(2,15, "Go To");
tempStr = (char *)XtMalloc(strlen(tmpStr) +
strlen(file_mgr_data->title) + 5);
sprintf(tempStr, "%s - %s", file_mgr_data->title, tmpStr);
}
else
{
tmpStr = (GETMESSAGE(2,17, "File Manager - Go To"));
tempStr = XtNewString(tmpStr);
}
XtSetArg (args[0], XmNtitle, tempStr);
XtSetValues (XtParent (change_dir_rec->change_dir), args, 1);
XtFree(tempStr);
file_mgr_rec->change_directoryBtn_child=XtParent (change_dir_rec->change_dir);
}
/************************************************************************
*
* CurrentDirSelected
* When a Button1 selection occurs on the current directory line,
* see if it occurred within the directory path, highlight the
* selected sub-path, or if the sub-path was already highlighted,
* set the current directory to the path and dehighlight.
*
************************************************************************/
void
CurrentDirSelected(
Widget w,
XtPointer client_data,
XtPointer call_data )
{
FileMgrRec *file_mgr_rec = (FileMgrRec *) client_data;
DialogData *dialog_data;
FileMgrData *file_mgr_data;
char buf[2*MAX_PATH];
char host_name[MAX_PATH];
Boolean chopped;
int host_len;
int host_pixels;
int prefix_len;
int prefix_pixels;
int path_len;
int path_pixels;
XmDrawnButtonCallbackStruct *button_data;
XButtonEvent *event;
Dimension width, highlight, shadow, margin;
Arg args[4];
int left_margin;
int begin_x;
int end_x;
int len;
int i;
char *ptr;
char *new_select;
int swidth;
static XtIntervalId TimerId;
/* if doubleClick is true than we have a double click so we want
* to change to the new directory that the user double clicked on
*/
if (doubleClick)
XtRemoveTimeOut(TimerId);
button_data = (XmDrawnButtonCallbackStruct *) call_data;
event = (XButtonEvent *) button_data->event;
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
file_mgr_data = (FileMgrData *) dialog_data->data;
/* Get layout values */
XtSetArg (args[0], XmNwidth, &width);
XtSetArg (args[1], XmNhighlightThickness, &highlight);
XtGetValues (w, args, 2);
XtSetArg (args[0], XmNshadowThickness, &shadow);
XtSetArg (args[1], XmNmarginWidth, &margin);
XtGetValues (file_mgr_rec->current_directory_text, args, 2);
left_margin = highlight + shadow + margin;
/* Get the starting and ending locations of the current */
/* directory text. */
chopped = get_text_pieces(file_mgr_data, width - 2*left_margin,
buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
&path_len, &path_pixels);
begin_x = left_margin;
end_x = begin_x + host_pixels + prefix_pixels + path_pixels;
/* Get the selected path */
if (event->x < begin_x || event->x >= end_x)
{
/* click outside the directory text: nothing selected */
new_select = NULL;
}
else if (event->x < begin_x + host_pixels ||
event->x < begin_x + host_pixels + prefix_pixels && !chopped)
{
/* click on host name or "/..." prefix: root selected */
if (file_mgr_data->restricted_directory)
new_select = XtNewString(file_mgr_data->restricted_directory);
else
new_select = XtNewString("/");
}
else if (event->x < begin_x + host_pixels + prefix_pixels && chopped)
{
/* click on "..." prefix: directory above the visible piece selected */
len = strlen(file_mgr_data->current_directory) - path_len;
new_select = (char *) XtMalloc(len + 1);
memcpy(new_select, file_mgr_data->current_directory, len);
new_select[len] = 0;
}
else /* event->x >= begin_x + host_pixels + prefix_pixels */
{
/* click on the path: determine which subdirectory selected */
begin_x += host_pixels + prefix_pixels;
i = host_len + prefix_len;
swidth = get_textwidth(file_mgr_data, "/", strlen("/")) / 2;
while (begin_x - swidth < event->x)
{
/* find next '/' in path */
ptr = DtStrchr(buf + i, '/');
if (ptr == NULL)
{
i = host_len + prefix_len + path_len + 1;
break;
}
/* get x-position of next path component */
len = ((ptr + 1) - buf) - i;
begin_x += get_textwidth(file_mgr_data, buf + i, len);
i += len;
}
/* if we have a restricted diretory and i == 5 ("/.../") then we want
the len to be the restricted directory */
if (file_mgr_data->restricted_directory && i == 5)
len = strlen(file_mgr_data->restricted_directory);
else
len = strlen(file_mgr_data->current_directory)
- (host_len + prefix_len + path_len - i) - 1;
new_select = (char *) XtMalloc(len + 1);
if (len == 0)
strcpy(new_select, "/");
else
{
memcpy(new_select, file_mgr_data->current_directory, len);
new_select[len] = 0;
}
}
/* in restricted mode, don't allow going above the user's home dir */
if (new_select != NULL && restrictMode)
{
/* check if new_select is the same as or a subdirectory of $HOME */
len = strlen(users_home_dir);
if (strncmp(new_select, users_home_dir, len) != 0
|| new_select[len] != '\0' && new_select[len] != '/')
{
/* change new_select to $HOME */
XtFree(new_select);
new_select = XtNewString(users_home_dir);
}
}
/* If the path is the same as what is already selected, */
/* free cd_select, set the directory to the selected */
/* directory, redraw the directory display. */
/* If the path was different, set cd_select to the */
/* selected directory and redraw the directory. */
if (new_select != NULL && file_mgr_data->cd_select != NULL &&
strcmp(new_select, file_mgr_data->cd_select) == 0)
{
XtFree (file_mgr_data->cd_select);
file_mgr_data->cd_select = NULL;
strcpy(buf, new_select);
strcpy(host_name, file_mgr_data->host);
if (strcmp (buf, file_mgr_data->current_directory) == 0)
FileMgrReread (file_mgr_rec);
else
ShowNewDirectory (file_mgr_data, host_name, buf);
XtFree (new_select);
}
else
{
XtFree (file_mgr_data->cd_select);
file_mgr_data->cd_select = new_select;
}
if (doubleClick)
{
doubleClick = False;
DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
}
else
{
doubleClick = True;
TimerId = XtAppAddTimeOut (XtWidgetToApplicationContext (w),
XtGetMultiClickTime(XtDisplay(w)),
(XtTimerCallbackProc) TimerEvent,
(XtPointer) file_mgr_rec);
}
}
/************************************************************************
*
* CurrentDirDropCallback
* Callback function invoked upon an action on the change view drop.
*
************************************************************************/
void
CurrentDirDropCallback(
Widget w,
XtPointer client_data,
XtPointer call_data )
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
XmAnyCallbackStruct * callback;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
char host_name[MAX_PATH];
callback = (XmAnyCallbackStruct *) call_data;
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
file_mgr_data = (FileMgrData *) dialog_data->data;
if (callback->reason == XmCR_DEFAULT_ACTION)
{
strcpy(host_name, file_mgr_data->host);
ShowNewDirectory (file_mgr_data, host_name,
_DtPName (file_mgr_data->current_directory));
}
}
/************************************************************************
*
* CurrentDirIconCallback
* Callback function invoked upon an action occurring on an icon.
*
************************************************************************/
void
CurrentDirIconCallback(
Widget w,
XtPointer client_data,
XtPointer call_data )
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
XmAnyCallbackStruct * callback;
XButtonEvent * event;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
callback = (XmAnyCallbackStruct *) call_data;
event = (XButtonEvent *) callback->event;
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
file_mgr_data = (FileMgrData *) dialog_data->data;
if (callback->reason == XmCR_DRAG)
{
/* Do nothing if a Button 1 drag is already ramping up */
if (B1DragPossible)
return;
/* Save starting X and Y, for threshold detection */
initialDragX = event->x;
initialDragY = event->y;
/* Flag that a Button 2 drag is ramping up */
B2DragPossible = True;
UnpostTextField(file_mgr_data);
}
else if (callback->reason == XmCR_ARM)
{
/* Do nothing if a Button 2 drag is already ramping up */
if (B2DragPossible)
return;
/* Save starting X and Y, for threshold detection */
initialDragX = event->x;
initialDragY = event->y;
/* Flag that a Button 1 drag is ramping up */
B1DragPossible = True;
/* but since we're in the current directory icon we don't want to
process on the button up */
ProcessBtnUpCD = False;
UnpostTextField(file_mgr_data);
}
else if (callback->reason == XmCR_DEFAULT_ACTION)
{
/* We now know that a drag operation won't be starting up */
B1DragPossible = False;
B2DragPossible = False;
UnpostTextField(file_mgr_data);
/* Default action is to reread the directory */
FileMgrReread (file_mgr_rec);
}
else if ((callback->reason == XmCR_SELECT) ||
(callback->reason == XmCR_DISARM) ||
(callback->reason == XmCR_DROP))
{
/* We now know that a drag operation won't be starting up */
B1DragPossible = False;
B2DragPossible = False;
}
}
/*
* This function processes motion events anytime a B1 or B2 drag operation
* has the potential of starting. When the drag threshold is surpassed,
* a drag operation will be started.
*/
void
CurrentDirectoryIconMotion(
Widget w,
XtPointer client_data,
XEvent *event)
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
Pixmap drag_pixmap;
char * type_set;
char * file_set;
int diffX, diffY;
Widget dirIcon;
DtIconGadget iconG;
if ((B1DragPossible && (event->xmotion.state & Button1Mask)) ||
(B2DragPossible && (event->xmotion.state & Button2Mask)))
{
/* Have we passed the drag threshold? */
diffX = initialDragX - event->xmotion.x;
diffY = initialDragY - event->xmotion.y;
if ((ABS(diffX) >= dragThreshold) || (ABS(diffY) >= dragThreshold))
{
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
file_mgr_data = (FileMgrData *) dialog_data->data;
initiating_view = (XtPointer) file_mgr_data;
dirIcon = file_mgr_rec->current_directory_icon;
StartDrag(dirIcon, NULL, event);
}
}
}
/************************************************************************
*
* CurrentDirExposed
* Callback functions invoked from the current directory display
* drawn button. This function extracts some structures and calls
* the directory display function.
*
************************************************************************/
void
CurrentDirExposed(
Widget w,
XtPointer client_data,
XtPointer call_data )
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
/* Check to see if the view has been closed */
if (dialog_data == NULL) return;
file_mgr_data = (FileMgrData *) dialog_data->data;
if (file_mgr_data->cd_normal_gc != 0)
DrawCurrentDirectory (w, file_mgr_rec, file_mgr_data);
}
/************************************************************************
*
* GetStatusMsg
* Construct the status message (normally "x Items, y Hidden").
* Returns True if the message is deemed "important".
*
* @@@ Note 2/17/95: messages below containing "Item(s)" should really
* be just "Item", but the message catalog is frozen at this time, so
* we can't fix this now. (In practice, it doesn't matter, because
* the item count should always be > 1, since every directory shoule
* contain at least two files "." and "..")
*
************************************************************************/
Boolean
GetStatusMsg(
FileMgrData *file_mgr_data,
char *buf )
{
int n_files;
int n_hidden;
int i, j;
TreeShow ts;
FileViewData **file_view_data;
/*
* If we are currently busy reading a directory, display a progress
* message instead of the normal "x Items, y Hidden" message.
*/
if (file_mgr_data->busy_status == initiating_readdir ||
file_mgr_data->busy_status == busy_readdir)
{
if (file_mgr_data->busy_detail == 0)
sprintf (buf, "%s", (GETMESSAGE(3,5, "Reading ...")));
else if (file_mgr_data->busy_detail == 1)
sprintf (buf, (GETMESSAGE(3,11, "%d Item(s)...")),
file_mgr_data->busy_detail);
else
sprintf (buf, (GETMESSAGE(3,9, "%3d Items ...")),
file_mgr_data->busy_detail);
return True; /* this message deemed important! */
}
else if (file_mgr_data->show_type == MULTIPLE_DIRECTORY)
{
/*
* In tree mode, we only show a count of the hidden files
* in branches that are currently expanded.
* The idea is we want to show how many additional files would
* show up if the user turned on the "Show Hidden" option.
*/
n_hidden = 0;
for (i = 0; i < file_mgr_data->directory_count; i++)
{
file_view_data = file_mgr_data->directory_set[i]->file_view_data;
if (file_view_data == NULL)
continue;
ts = file_mgr_data->directory_set[i]->sub_root->ts;
if (ts < tsDirs)
continue; /* this branch is not expanded */
for (j = 0; j < file_mgr_data->directory_set[i]->file_count; j++)
{
if (file_view_data[j]->filtered &&
(ts == tsAll || file_view_data[j]->file_data->is_subdir))
{
n_hidden++;
}
}
}
sprintf (buf, (GETMESSAGE(3,6, "%d Hidden")), n_hidden);
return False;
}
else
{
/*
* In flat mode, we only show a total count of all files
* and a count of hidden files.
*/
n_files = file_mgr_data->directory_set[0]->file_count;
if( n_files == 0 )
sprintf( buf, (GETMESSAGE(11,31, "Error while reading %s")), file_mgr_data->current_directory );
else if( file_mgr_data == trashFileMgrData )
{
n_hidden = file_mgr_data->directory_set[0]->filtered_file_count;
sprintf (buf, (GETMESSAGE(3,10, "%d Item(s)")),
n_files - n_hidden);
}
else
{
n_files -= file_mgr_data->directory_set[0]->invisible_file_count;
n_hidden = file_mgr_data->directory_set[0]->filtered_file_count -
file_mgr_data->directory_set[0]->invisible_file_count;
if (n_files == 1)
sprintf (buf, (GETMESSAGE(3,12, "%d Item(s) %d Hidden")),
n_files, n_hidden);
else
sprintf (buf, (GETMESSAGE(3,7, "%d Items %d Hidden")),
n_files, n_hidden);
}
return False;
}
}
/************************************************************************
*
* DrawCurrentDirectory
* Draw the current directory display area, including the hostname,
* the current directory, any highlighted sub-path of the directory,
* the file count and the number of selected files.
*
************************************************************************/
void
DrawCurrentDirectory(
Widget w,
FileMgrRec *file_mgr_rec,
FileMgrData *file_mgr_data )
{
Arg args[8];
Dimension width, height, highlight, shadow, margin, twidth;
XFontSetExtents *extents;
int font_height;
int font_yoffset;
int top_margin;
int left_margin;
char buf[2*MAX_PATH];
char msg[21+MAX_PATH];
Boolean chopped;
int host_len;
int host_pixels;
int prefix_len;
int prefix_pixels;
int path_len;
int path_pixels;
int draw_x;
int draw_y;
int dir_width;
int msg_width;
short columns;
Boolean msg_drawn;
/* Get layout values */
XtSetArg (args[0], XmNwidth, &width);
XtSetArg (args[1], XmNheight, &height);
XtSetArg (args[2], XmNhighlightThickness, &highlight);
XtGetValues (w, args, 3);
XtSetArg (args[0], XmNshadowThickness, &shadow);
XtSetArg (args[1], XmNmarginWidth, &margin);
XtGetValues (file_mgr_rec->current_directory_text, args, 2);
if(file_mgr_data->cd_fonttype == XmFONT_IS_FONTSET) {
extents = XExtentsOfFontSet(file_mgr_data->cd_fontset);
font_yoffset = -(extents->max_logical_extent.y);
font_height = extents->max_logical_extent.height;
}
else
{
font_yoffset = file_mgr_data->cd_font->ascent;
font_height = file_mgr_data->cd_font->ascent +
file_mgr_data->cd_font->descent;
}
top_margin = (height > (Dimension)font_height)? (Dimension)(height - font_height + 1)/(Dimension)2: 0;
left_margin = highlight + shadow + margin;
/* Ensure the area is cleared out. */
XClearArea (XtDisplay (w), XtWindow (w),
highlight, highlight,
width - 2*highlight, height - 2*highlight,
False);
/*
* If there is no status line and no iconic path,
* we will want yo draw the "x Files y Hidden" message here.
*/
if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
{
/*
* GetStatusMsg() returns True if the status msg is "important".
* In this case, make sure we leave room for it
*/
msg_drawn = GetStatusMsg(file_mgr_data, msg);
msg_width = get_textwidth (file_mgr_data, msg, strlen(msg));
}
else
msg_drawn = False;
draw_x = left_margin;
if( draw_x < 0 || (Dimension) draw_x > width ) /* Make sure that it's in bound */
draw_x = 0;
draw_y = top_margin + font_yoffset;
if( draw_y < 0 || (Dimension) draw_y > height ) /* Make sure that it's in bound */
{
draw_y = height-5;
}
/* get the text pieces */
dir_width = width - 2*left_margin;
if (msg_drawn)
dir_width -= CUR_DIR_SPACING + msg_width;
chopped = get_text_pieces(file_mgr_data, dir_width,
buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
&path_len, &path_pixels);
/*
* go check and change the file_mgr_data->cd_select, make sure its not
* longer than the file_mgr_data->current_directory.
*/
CheckCurrentDirectorySelect(file_mgr_data);
/* draw the host and paths */
if (!file_mgr_data->fast_cd_enabled)
{
draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
file_mgr_data->cd_normal_gc, draw_x, draw_y,
buf, host_len + prefix_len + path_len);
}
else if (file_mgr_data->restricted_directory)
{
draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
file_mgr_data->cd_normal_gc, draw_x, draw_y,
buf, host_len + prefix_len);
}
/*
* If there is no status line and no iconic path, and we have
* room left, draw the "x Files y Hidden" message here.
*/
if (!file_mgr_data->show_iconic_path && !file_mgr_data->show_status_line)
{
/* determine where the message could begin */
if (!file_mgr_data->fast_cd_enabled)
draw_x += host_pixels + prefix_pixels + path_pixels;
else
{
XtSetArg(args[0], XmNwidth, &twidth);
XtGetValues(file_mgr_rec->current_directory_text, args, 1);
if (file_mgr_data->restricted_directory && !chopped)
draw_x += host_pixels + prefix_pixels + twidth;
else
draw_x += host_pixels + twidth;
}
/* if there is enough space left, draw the message */
if ((Dimension)(draw_x + CUR_DIR_SPACING + msg_width + left_margin) <= width)
{
draw_x = width - left_margin - msg_width;
draw_imagestring (XtDisplay (w), XtWindow (w), file_mgr_data,
file_mgr_data->cd_normal_gc, draw_x, draw_y,
msg, strlen(msg));
draw_x -= shadow + CUR_DIR_SPACING; /* right edge of shadow */
msg_drawn = True;
}
else
msg_drawn = False;
}
if (!msg_drawn)
draw_x = width - (highlight + shadow);
/* draw the shadow */
if (!file_mgr_data->fast_cd_enabled)
{
int shadow_width = draw_x - highlight;
int shadow_height = height - 2*highlight;
XmTextFieldWidget tf =
(XmTextFieldWidget)file_mgr_rec->current_directory_text;
XmeDrawShadows(XtDisplay(w), XtWindow(w),
tf->primitive.top_shadow_GC,
tf->primitive.bottom_shadow_GC,
highlight, highlight, shadow_width, shadow_height,
shadow, XmSHADOW_IN);
}
}
/************************************************************************
*
* CurrentDirChange
* Callback functions invoked from the current directory dialog's
* apply button being pressed. This function updates and redisplays
* the current directory information.
*
************************************************************************/
static void
CurrentDirChange(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data,
XtPointer call_data )
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
DialogData * dialog_data;
FileMgrData * file_mgr_data;
ChangeDirData * new_change_dir_data;
ChangeDirData * old_change_dir_data;
char path[MAX_PATH];
char host_name[MAX_PATH];
char * ptr;
/* Get a pointer file manager's data structure, free up the */
/* old current directory and copy in a new one. Free up the */
/* old selected sub-path, update the file manager's internal */
/* data, and redraw the directory. */
dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
file_mgr_data = (FileMgrData *) dialog_data->data;
if (file_mgr_data->cd_select != NULL)
{
XtFree (file_mgr_data->cd_select);
file_mgr_data->cd_select = NULL;
}
old_change_dir_data = (ChangeDirData *) file_mgr_data->change_dir->data;
new_change_dir_data = (ChangeDirData *) new_dialog_data->data;
new_change_dir_data->host_name = XtNewString(old_change_dir_data->host_name);
new_change_dir_data->file_mgr_rec = old_change_dir_data->file_mgr_rec;
_DtHideDialog(old_dialog_data, False);
new_change_dir_data->displayed = False;
file_mgr_data->change_dir->data = (XtPointer) new_change_dir_data;
new_dialog_data->data = (XtPointer) old_change_dir_data;
_DtFreeDialogData (new_dialog_data);
file_mgr_rec->menuStates |= CHANGEDIR;
/* Process call_data into a hostname and directory name. */
ShowNewDirectory (file_mgr_data,
((ChangeDirData *)file_mgr_data->change_dir->data)->host_name,
call_data);
}
/************************************************************************
*
* CurrentDirClose
* Callback functions invoked from the current directory dialog's
* close button being pressed. This function resensitizes the
* Change Directory... menu item.
*
************************************************************************/
/*ARGSUSED*/
static void
CurrentDirClose(
XtPointer client_data,
DialogData *old_dialog_data,
DialogData *new_dialog_data )
{
FileMgrRec * file_mgr_rec = (FileMgrRec *) client_data;
_DtFreeDialogData (new_dialog_data);
file_mgr_rec->menuStates |= CHANGEDIR;
}
/************************************************************************
*
* CheckCurrentDirectorySelect
* Before calling DrawCurrentDirectorySelect() this function
* makes sure that the fm->cd_select isn't longer than the
* fm->current_directory. If it is it reconfigures fm->cd_select
* to hold no more than what fm->current_directory is.
*
************************************************************************/
static void
CheckCurrentDirectorySelect(
FileMgrData *file_mgr_data )
{
int length_cd, length_cd_s;
char *str, *ptr;
if (file_mgr_data == NULL ||
file_mgr_data->cd_select == NULL ||
file_mgr_data->current_directory == NULL)
return;
/* get the true lengths of current_directory and current_directory_select */
length_cd = strlen(file_mgr_data->current_directory);
length_cd_s = strlen(file_mgr_data->cd_select);
/* if cd is larger than cd_select than we have now problem */
if(length_cd >= length_cd_s)
return;
/* we need to recalculate the cd_select */
str = XtNewString(file_mgr_data->cd_select);
while(1)
{
ptr = strrchr(str, '/');
*ptr = '\0';
length_cd_s = strlen(str);
if(length_cd > length_cd_s)
{
XtFree(file_mgr_data->cd_select);
file_mgr_data->cd_select = (char *)XtMalloc(strlen(str) + 1);
strcpy(file_mgr_data->cd_select, str);
XtFree(str);
return;
}
}
}
/************************************************************************
*
* ShowFastChangeDir
* Post the fast change to text widget.
*
***************************************************************************/
void
ShowFastChangeDir(
FileMgrRec *file_mgr_rec,
FileMgrData *file_mgr_data )
{
char *textString;
Arg args[16];
Dimension width, height;
Dimension shadow, highlight, margin;
char buf[2*MAX_PATH];
Boolean chopped;
int host_len;
int host_pixels;
int prefix_len;
int prefix_pixels;
int path_len;
int path_pixels;
int begin_x;
int left_margin;
doubleClick = False;
XtRemoveAllCallbacks (file_mgr_rec->current_directory, XmNexposeCallback);
XtFree (file_mgr_data->cd_select);
file_mgr_data->cd_select = NULL;
file_mgr_data->fast_cd_enabled = True;
/* if not a toolbox, just put the current directory in text widget */
if (file_mgr_data->restricted_directory == NULL)
{
if (strcmp(file_mgr_data->host, home_host_name) == 0)
textString = XtNewString(file_mgr_data->current_directory);
else
textString = DtCreateContextString(file_mgr_data->host,
file_mgr_data->current_directory,
NULL);
}
else /* is a toolbox, so put the subset of what the toolbox is in the text*/
{
char *ptr;
ptr = file_mgr_data->current_directory +
strlen(file_mgr_data->restricted_directory);
if (strcmp(ptr, "") == 0)
textString = XtNewString("/");
else
textString = XtNewString(ptr);
}
begin_x = get_textwidth (file_mgr_data, textString, strlen (textString));
/* Get layout values */
XtSetArg (args[0], XmNwidth, &width);
XtSetArg (args[1], XmNhighlightThickness, &highlight);
XtGetValues (file_mgr_rec->current_directory, args, 2);
XtSetArg (args[0], XmNshadowThickness, &shadow);
XtSetArg (args[1], XmNmarginWidth, &margin);
XtGetValues (file_mgr_rec->current_directory_text, args, 2);
left_margin = highlight + shadow + margin;
if(file_mgr_data->restricted_directory == NULL)
XtSetArg (args[0], XmNleftOffset, 0);
else
{
XtSetArg (args[0], XmNshadowThickness, &shadow);
XtSetArg (args[1], XmNhighlightThickness, &highlight);
XtGetValues(file_mgr_rec->current_directory_text, args, 2);
chopped =
get_text_pieces(file_mgr_data, width - 2*left_margin,
buf, &host_len, &host_pixels, &prefix_len, &prefix_pixels,
&path_len, &path_pixels);
begin_x = left_margin + host_pixels - shadow - highlight;
if (!chopped)
begin_x += prefix_pixels;
XtSetArg (args[0], XmNleftOffset, begin_x);
}
XtSetArg (args[1], XmNvalue, textString);
XtSetValues(file_mgr_rec->current_directory_text, args, 2);
XtSetArg (args[0], XmNcursorPosition, strlen(textString));
XtSetValues(file_mgr_rec->current_directory_text, args, 1);
XtSetArg (args[0], XmNallowShellResize, False);
XtSetValues(file_mgr_rec->shell, args, 1);
XtManageChild(file_mgr_rec->current_directory_text);
XtSetArg (args[0], XmNallowShellResize, True);
XtSetValues(file_mgr_rec->shell, args, 1);
XRaiseWindow(XtDisplay(file_mgr_rec->current_directory_text),
XtWindow(file_mgr_rec->current_directory_text));
XmUpdateDisplay(file_mgr_rec->current_directory_text);
XmProcessTraversal(file_mgr_rec->current_directory_text,
XmTRAVERSE_CURRENT);
XtFree(textString);
XtAddCallback (file_mgr_rec->current_directory, XmNexposeCallback,
CurrentDirExposed, file_mgr_rec);
}
/************************************************************************
*
* TimerEvent - timeout for double click on current Directory line. If
* we get here we know it was a single click so lets post the
* fast change to text widget.
*
***************************************************************************/
static void
TimerEvent(
XtPointer client_data,
XtIntervalId *id )
{
FileMgrRec *file_mgr_rec = (FileMgrRec *)client_data;
DialogData * dialog_data;
FileMgrData *file_mgr_data;
doubleClick = False;
/* Got an accelerator after we were unposted */
if ((dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec)) == NULL)
return;
file_mgr_data = (FileMgrData *) dialog_data->data;
ShowFastChangeDir(file_mgr_rec, file_mgr_data);
}
/************************************************************************
*
* ResizeFastText - resizes the fast change text widget due to changes
* in the size of the FileManager window.
*
*************************************************************************/
static void
ResizeFastText(
FileMgrRec *file_mgr_rec,
FileMgrData *file_mgr_data,
short columns)
{
Arg args[2];
Dimension width;
int left_offset;
/* nothing to do if not managed */
if (!XtIsManaged(file_mgr_rec->current_directory_text))
return;
/* get width of current directory line */
XtSetArg (args[0], XmNwidth, &width);
XtGetValues (file_mgr_rec->current_directory, args, 1);
/* get offset of the text widget */
XtSetArg(args[0], XmNleftOffset, &left_offset);
XtGetValues(file_mgr_rec->current_directory_text, args, 1);
/* set text widget width = current_directory width minus left offset */
XtSetArg (args[0], XmNwidth, width - left_offset);
XtSetValues (file_mgr_rec->current_directory_text, args, 1);
}
/*--------------------------------------------------------------------
* get_textwidth
*------------------------------------------------------------------*/
/* use Xmb functions if XFontSet is used. */
static int
get_textwidth( FileMgrData *fmd,
char *str,
int len)
{
int w = 0;
switch(fmd->cd_fonttype)
{
case XmFONT_IS_FONTSET:
w = XmbTextEscapement(fmd->cd_fontset, str, len);
break;
case XmFONT_IS_FONT:
w = XTextWidth(fmd->cd_font, str, len);
default:
break;
}
return(w);
}
static void
draw_imagestring( Display *display,
Drawable d,
FileMgrData *fmd,
GC gc,
int x, int y,
char *text,
int bytes)
{
switch(fmd->cd_fonttype)
{
case XmFONT_IS_FONTSET:
XmbDrawImageString(display, d, fmd->cd_fontset, gc, x, y, text,
bytes);
break;
case XmFONT_IS_FONT:
XDrawImageString(display, d, gc, x, y, text, bytes);
default:
break;
}
}