/***************************************************************************/
/***************************************************************************/
/* */
/* (c) 1995-1999. The Regents of the University of California. All */
/* rights reserved. */
/* */
/* This work was produced at the University of California, Lawrence */
/* Livermore National Laboratory (UC LLNL) under contract no. */
/* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */
/* (DOE) and The Regents of the University of California (University) */
/* for the operation of UC LLNL. Copyright is reserved to the */
/* University for purposes of controlled dissemination, */
/* commercialization through formal licensing, or other disposition */
/* under terms of Contract 48; DOE policies, regulations and orders; */
/* and U.S. statutes. The rights of the Federal Government are */
/* reserved under Contract 48 subject to the restrictions agreed upon */
/* by the DOE and University. */
/* */
/* */
/* DISCLAIMER */
/* */
/* This software was prepared as an account of work sponsored by an */
/* agency of the United States Government. Neither the United States */
/* Government nor the University of California nor any of their */
/* employees, makes any warranty, express or implied, or assumes any */
/* liability or responsibility for the accuracy, completeness, or */
/* usefulness of any information, apparatus, product, or process */
/* disclosed, or represents that its specific commercial products, */
/* process, or service by trade name, trademark, manufacturer, or */
/* otherwise, does not necessarily constitute or imply its */
/* endorsement, recommendation, or favoring by the United States */
/* Government or the University of California. The views and opinions */
/* of the authors expressed herein do not necessarily state or reflect */
/* those of the United States Government or the University of */
/* California, and shall not be used for advertising or product */
/* endorsement purposes. */
/* */
/* Permission to use, copy, modify and distribute this software and its */
/* documentation for any non-commercial purpose, without fee, is */
/* hereby granted, provided that the above copyright notice and this */
/* permission notice appear in all copies of the software and */
/* supporting documentation, and that all UC LLNL identification in */
/* the user interface remain unchanged. The title to copyright LLNL */
/* XDIR shall at all times remain with The Regents of the University */
/* of California and users agree to preserve same. Users seeking the */
/* right to make derivative works with LLNL XDIR for commercial */
/* purposes may obtain a license from the Lawrence Livermore National */
/* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */
/* Livermore, CA 94550. */
/* */
/***************************************************************************/
/***************************************************************************/
#include <sys/param.h>
#include <ctype.h>
#include <Xm/Label.h>
#include "xdir.h"
#include "list.h"
static char *dirwin_help[] = {
"The \"tabular\" directory list allows you to view",
" the contents of the current",
"directory in tabular form. This list may be used to view",
"and modify the directory's selected entries. Entries may be",
"selected/deselected either by clicking or by moving the cursor",
"over the entries with the mouse button down. Moving the mouse",
"too quickly can cause some of the entries to be skipped. If an",
"entry is double-clicked, an attempt is made to change the",
"current directory to that entry. The tabular list is automatically",
"updated as the current directory changes.",
NULL
};
int safe_to_redraw = True;
extern struct dirwin_st *dirwin_head;
extern int xfer_mode;
extern struct sl_struct *launcher_mappings;
extern Display *display;
extern int screen;
extern struct st_host_info hinfo[];
char *links_to_path();
char *merge_paths();
void update_xfer_mode_menu();
void update_all_xfer_mode_menus();
/*
* cb_dirwin_close - Callback for closing directory table dialog.
*/
void
cb_dirwin_close(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
struct dirwin_st *dwin;
static char *msg1 = "Closing this window will terminate Xdir.\n\nContinue closing?";
static char *msg2 = "Closing this window will disconnect host.\n\nContinue closing?";
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
/* If this is the last dir window, does user really want to quit? */
if (dirwin_head->next == NULL) {
XMapRaised(display, XtWindow(dirwin->w_shell));
if (question_dialog(msg1, dirwin->w_shell))
quit(dirwin->w_shell);
else {
end_op();
return;
}
}
/* If this is the last window for remote host, does user want to quit? */
if (dirwin->host != LOCAL) {
dwin = dirwin_head;
while (dwin) {
if ((dwin != dirwin) && (dwin->host == dirwin->host))
break;
dwin = dwin->next;
}
if (!dwin) {
XMapRaised(display, XtWindow(dirwin->w_shell));
if (!question_dialog(msg2, dirwin->w_shell)) {
end_op();
return;
}
}
}
close_directory_window(dirwin);
/* End operation */
end_op();
}
/*
* cb_dirwin_help - Callback for invoking directory table dialog's
* help package.
*/
void
cb_dirwin_help(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
char *text;
XtVaGetValues(dirwin->w_shell, XmNtitle, &text, NULL);
help_dialog(widget, False, text, dirwin_help);
}
/*
* is_entry_visible - Returns true if specified entry is visible.
*/
is_entry_visible(einfo)
struct entry_info *einfo;
{
struct dirwin_st *dirwin = einfo->dirwin;
int col;
int row = einfo->indx%dirwin->nrows;
int x;
int left_da_x;
Dimension drawing_area_width;
/* Is entry vertically scrolled out of view? */
if (row < dirwin->first_visible_row ||
row >= dirwin->first_visible_row+dirwin->nrows_visible)
return False;
/* Is entry horizontally scrolled out of view? */
switch (dirwin->layout) {
case TABULAR:
case ICONIC:
col = einfo->indx/dirwin->nrows;
x = HMARGIN+col*(dirwin->max_entry_width+HSPACING);
break;
case TREE:
x = HMARGIN+einfo->level*INDENT+CWIDTH+CMARGIN;
break;
case FULL_INFO:
x = HMARGIN;
break;
}
left_da_x = virtual_x(dirwin, 0);
XtVaGetValues(dirwin->w_drawingArea, XmNwidth, &drawing_area_width, NULL);
if (x+einfo->width < left_da_x || x > left_da_x+(int)drawing_area_width)
return False;
else
return True;
}
/*
* select_entry - Select the entry specified by "einfo".
*/
void
select_entry(einfo)
struct entry_info *einfo;
{
einfo->state = SELECTED;
if (is_entry_visible(einfo))
draw_entry(einfo);
}
/*
* deselect_entry - Deselect the entry specified by "einfo".
*/
void
deselect_entry(einfo)
struct entry_info *einfo;
{
einfo->state = UNSELECTED;
if (is_entry_visible(einfo))
draw_entry(einfo);
}
/*
* toggle_entry - Toggle the selection of the entry specified by "einfo".
* Also update directory display in main window.
*/
void
toggle_entry(einfo)
struct entry_info *einfo;
{
struct dirwin_st *dirwin = einfo->dirwin;
/* Clear error flag */
raise_okflag();
/* First clear other hosts' selected directory entries */
if (!dirwin->has_selection)
clear_selected_entries();
/* Now toggle item */
dirwin->has_selection = True;
if (einfo->state == UNSELECTED)
select_entry(einfo);
else
deselect_entry(einfo);
update_dir_controls();
}
/*
* enable_dirwin - If "enable" is FALSE, the user is no longer able to
* change directories by double-clicking on a directory
* table entry. If "enable" is TRUE, this capability
* is turned back on.
*/
void
enable_dirwin(dirwin, enable)
struct dirwin_st *dirwin;
int enable;
{
XtSetSensitive(dirwin->w_drawingArea, enable);
}
void
cb_change_layout(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
struct entry_link *head = NULL;
struct entry_link *ptr;
int i;
int saved_layout = dirwin->layout;
int retval;
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
/* Don't redraw dir window while data structures are inconsistent */
safe_to_redraw = False;
/* All should be unset excepted selected item */
if (widget == dirwin->w_tabularButton)
dirwin->layout = TABULAR;
else if (widget == dirwin->w_iconicButton)
dirwin->layout = ICONIC;
else if (widget == dirwin->w_treeButton)
dirwin->layout = TREE;
else
dirwin->layout = FULL_INFO;
update_layout_mode_buttons(dirwin);
/* Save selection */
for (i=0; i<dirwin->nentries; i++)
if ((dirwin->entries[i].state == SELECTED)
&& (dirwin->entries[i].level == 0))
add_to_linked_list(&head, dirwin->entries[i].name);
/* Make operation interruptable */
if (dirwin->host != LOCAL)
show_stop_button(dirwin);
/* Make sure connection is still good */
if (dirwin->host != LOCAL) {
retval = check_connection(dirwin->host, dirwin);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Change Layout");
goto restore;
case -3:
goto fin;
case -1:
record_and_alert("Unable to change layout.", dirwin->w_shell);
goto restore;
}
}
}
/* Display in new layout */
retval = display_dir(dirwin->host, dirwin, dirwin->dirname, True, False,
dirwin->cache_mode, dirwin->cache_mode);
if (retval < 0) {
dirwin->layout = saved_layout;
update_layout_mode_buttons(dirwin);
switch (retval) {
case -6:
record_abort("Change Layout");
break;
case -3:
if (restore_lost_connection(dirwin->host, dirwin) < 0)
goto fin;
break;
case -1:
record_and_alert("Unable to change layout.", dirwin->w_shell);
}
}
restore:
/* Restore selection */
ptr = head;
while (ptr) {
for (i=0; i<dirwin->nentries; i++)
if (!strcmp(dirwin->entries[i].name, ptr->entry)) {
select_entry(&(dirwin->entries[i]));
dirwin->has_selection = True;
break;
}
ptr = ptr->next;
}
fin:
release_linked_list(&head);
update_dir_controls();
/* Get rid of stop button */
if (dirwin->host != LOCAL)
hide_stop_button();
/* Now it's safe to redraw directory windows */
safe_to_redraw = True;
/* End operation */
end_op();
}
/*
* cb_change_xfer_mode - Callback to process the ASCII and Binary menu
* toggles.
*/
void
cb_change_xfer_mode(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
/* Clear error flag */
raise_okflag();
/* Toggle the buttons */
if (widget == dirwin->w_asciiItem)
xfer_mode = ASCII;
else
xfer_mode = BINARY;
/* Update the other directory window */
update_all_xfer_mode_menus();
}
void
cb_select_all(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
int i;
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
clear_selected_entries();
for (i=0; i<dirwin->nentries; i++)
select_entry(&dirwin->entries[i]);
dirwin->has_selection = True;
update_dir_controls();
/* End operation */
end_op();
}
void
cb_deselect_all(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
int i;
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
for (i=0; i<dirwin->nentries; i++)
deselect_entry(&dirwin->entries[i]);
dirwin->has_selection = False;
update_dir_controls();
/* End operation */
end_op();
}
void
cb_options_menu(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
/* Clear error flag */
raise_okflag();
}
/*
* entry_to_rel_path - Returns pointer to relative path to entry
* represented by "einfo". Caller is responsible
* for freeing returned memory by calling XtFree().
*/
char *
entry_to_rel_path(einfo)
struct entry_info *einfo;
{
char *path;
int indx = einfo->indx;
int level = einfo->level;
char **links = (char **)XtMalloc(sizeof(char *)*(einfo->level+2));
/* Get entry name */
links[level] = XtNewString(einfo->name);
/* Get rest of relative path links */
level--;
while (level >= 0) {
if (--indx < 0)
fatal_error("Bug in entry_to_rel_path()");
if (einfo->dirwin->entries[indx].level == level) {
links[level] = XtNewString(einfo->dirwin->entries[indx].name);
level--;
}
}
path = links_to_path(hinfo[einfo->dirwin->host].system, links,
einfo->level+1);
links[einfo->level+1] = NULL;
release_path_links(links);
return path;
}
/*
* entry_to_full_path - Returns pointer to full path to entry represented
* by "einfo". Caller is responsible for freeing
* returned memory by calling XtFree().
*/
char *
entry_to_full_path(einfo)
struct entry_info *einfo;
{
char *rel_path;
char *full_path;
rel_path = entry_to_rel_path(einfo);
full_path = merge_paths(hinfo[einfo->dirwin->host].system,
einfo->dirwin->dirname, rel_path);
XtFree(rel_path);
return full_path;
}
actual_x(dirwin, x)
struct dirwin_st *dirwin;
int x;
{
Widget w_horizontal_sb;
int value;
XtVaGetValues(dirwin->w_scrolledWindow, XmNhorizontalScrollBar,
&w_horizontal_sb, NULL);
if (XtIsManaged(w_horizontal_sb)) {
XtVaGetValues(w_horizontal_sb, XmNvalue, &value, NULL);
return x-value*HINCREMENT;
} else
return x;
}
actual_y(dirwin, y)
struct dirwin_st *dirwin;
int y;
{
Widget w_vertical_sb;
int value;
XtVaGetValues(dirwin->w_scrolledWindow, XmNverticalScrollBar,
&w_vertical_sb, NULL);
if (XtIsManaged(w_vertical_sb)) {
XtVaGetValues(w_vertical_sb, XmNvalue, &value, NULL);
return y-value*(dirwin->entry_height+VSPACING)+VTMARGIN;
} else
return y+VTMARGIN;
}
virtual_x(dirwin, x)
struct dirwin_st *dirwin;
int x;
{
Widget w_horizontal_sb;
int value;
XtVaGetValues(dirwin->w_scrolledWindow, XmNhorizontalScrollBar,
&w_horizontal_sb, NULL);
if (XtIsManaged(w_horizontal_sb)) {
XtVaGetValues(w_horizontal_sb, XmNvalue, &value, NULL);
return x+value*HINCREMENT;
} else
return x;
}
virtual_y(dirwin, y)
struct dirwin_st *dirwin;
int y;
{
Widget w_vertical_sb;
int value;
XtVaGetValues(dirwin->w_scrolledWindow, XmNverticalScrollBar,
&w_vertical_sb, NULL);
if (XtIsManaged(w_vertical_sb)) {
XtVaGetValues(w_vertical_sb, XmNvalue, &value, NULL);
return y+value*(dirwin->entry_height+VSPACING)-VTMARGIN;
} else
return y-VTMARGIN;
}
/*
* update_all_xfer_mode_menus - Update the the file transfer option menu of
* each directory window.
*/
void
update_all_xfer_mode_menus()
{
struct dirwin_st *dirwin;
dirwin = dirwin_head;
while (dirwin) {
update_xfer_mode_menu(dirwin);
dirwin = dirwin->next;
}
}
/*
* update_xfer_mode_menu - Update the file transfer option menu of the
* specified directory window with its current
* value.
*/
void
update_xfer_mode_menu(dirwin)
struct dirwin_st *dirwin;
{
/* Set the transfer mode toggle buttons */
if (xfer_mode == ASCII)
XtVaSetValues(dirwin->w_xferModeMenu, XmNmenuHistory,
dirwin->w_asciiItem, NULL);
else
XtVaSetValues(dirwin->w_xferModeMenu, XmNmenuHistory,
dirwin->w_binaryItem, NULL);
}
/*
* iconify_directory_windows - Iconify all directory windows.
*/
void
iconify_directory_windows()
{
struct dirwin_st *dirwin;
dirwin = dirwin_head;
while (dirwin) {
XIconifyWindow(display, XtWindow(dirwin->w_shell), screen);
dirwin = dirwin->next;
}
}
/*
* deiconify_directory_windows - Deiconify all directory windows.
*/
void
deiconify_directory_windows()
{
struct dirwin_st *dirwin;
dirwin = dirwin_head;
while (dirwin) {
XMapWindow(display, XtWindow(dirwin->w_shell));
dirwin = dirwin->next;
}
}
/*
* cb_change_tunneling_mode - Callback for changing tunneling mode.
*/
void
cb_change_tunneling_mode(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
/* Toggle tunneling mode */
dirwin->tunneling_mode = !dirwin->tunneling_mode;
cb_tunneling_button_expose(widget, client_data, call_data);
/* End operation */
end_op();
}
/*
* cb_change_cache_mode - Callback for changing cache mode.
*/
void
cb_change_cache_mode(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
/* Toggle cache mode */
dirwin->cache_mode = !dirwin->cache_mode;
cb_cache_button_expose(widget, client_data, call_data);
/* End operation */
end_op();
}
/*
* cb_change_dotfiles_mode - Callback for changing dot files mode.
*/
void
cb_change_dotfiles_mode(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
struct entry_link *head = NULL;
struct entry_link *ptr;
int i;
int saved_dotfiles_mode = dirwin->dotfiles_mode;
int retval;
/* Start operation */
if (!start_op(False))
return;
/* Clear error flag */
raise_okflag();
/* Toggle dot files mode */
dirwin->dotfiles_mode = !dirwin->dotfiles_mode;
cb_dotfiles_button_expose(widget, client_data, call_data);
/* Save selection */
for (i=0; i<dirwin->nentries; i++)
if ((dirwin->entries[i].state == SELECTED)
&& (dirwin->entries[i].level == 0))
add_to_linked_list(&head, dirwin->entries[i].name);
/* Make operation interruptable */
if (dirwin->host != LOCAL)
show_stop_button(dirwin);
/* Make sure connection is still good */
if (dirwin->host != LOCAL) {
retval = check_connection(dirwin->host, dirwin);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Change Dot Files Mode");
goto restore;
case -3:
goto fin;
case -1:
record_and_alert("Unable to change dot files mode.",
dirwin->w_shell);
goto restore;
}
}
}
/* Redisplay directory */
retval = display_dir(dirwin->host, dirwin, dirwin->dirname, True, False,
dirwin->cache_mode, dirwin->cache_mode);
if (retval < 0) {
dirwin->dotfiles_mode = saved_dotfiles_mode;
cb_dotfiles_button_expose(widget, client_data, call_data);
switch (retval) {
case -6:
record_abort("Change Dot Files Mode");
break;
case -3:
if (restore_lost_connection(dirwin->host, dirwin) < 0)
goto fin;
break;
case -1:
record_and_alert("Unable to change dot files mode.",
dirwin->w_shell);
}
}
restore:
/* Restore selection */
ptr = head;
while (ptr) {
for (i=0; i<dirwin->nentries; i++)
if (!strcmp(dirwin->entries[i].name, ptr->entry)) {
select_entry(&(dirwin->entries[i]));
dirwin->has_selection = True;
break;
}
ptr = ptr->next;
}
fin:
release_linked_list(&head);
update_dir_controls();
/* Get rid of stop button */
if (dirwin->host != LOCAL)
hide_stop_button();
/* End operation */
end_op();
}
syntax highlighted by Code2HTML, v. 0.9.1