/***************************************************************************/
/***************************************************************************/
/* */
/* (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 <Xm/RowColumn.h>
#include "xdir.h"
#include "list.h"
#define CONTROL 0
#define ICON_NAME 1
#define MIN_MOTION 5
static struct dirwin_st *src_dirwin;
extern Display *display;
extern Window root_window;
extern int dir_area_enabled;
extern int multiclick_interval;
struct entry_info *xy_to_entry();
char *entry_to_full_path();
char *entry_to_rel_path();
struct sl_struct *create_null_array_list();
/*
* HandleMouseEvents - Handle mouse events in drawing area of directory
* window.
*/
void
HandleMouseEvents(widget, client_data, event, continue_to_dispatch_return)
Widget widget;
XtPointer client_data;
XEvent *event;
Boolean *continue_to_dispatch_return;
{
static struct entry_info *prev_einfo = NULL;
static struct entry_info *hilited_einfo;
static Time prev_time;
static int state = 0;
static int button_press_x;
static int button_press_y;
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
struct dirwin_st *temp_dirwin;
struct entry_info *temp_einfo;
char *path;
char *rel_path;
char *true_path;
struct entry_info *einfo;
int part;
int x;
int y;
int delta_x;
int delta_y;
struct sl_struct *list;
int retval;
/* Is some important operation in progress? */
if (op_in_progress())
return;
/* Process event */
switch (event->type) {
case ButtonPress:
if (event->xbutton.button == Button3) {
XmMenuPosition(dirwin->w_popupLaunchMenu,
(XButtonPressedEvent *)event);
XtManageChild(dirwin->w_popupLaunchMenu);
}
if (event->xbutton.button != Button1)
return;
src_dirwin = dirwin;
x = virtual_x(dirwin, event->xbutton.x);
y = virtual_y(dirwin, event->xbutton.y);
einfo = xy_to_entry(dirwin, x, y, &part);
if (einfo == NULL) {
init_toggle_rect(src_dirwin, x, y);
state = 1;
return;
}
if (part == CONTROL) {
raise_okflag();
if (einfo->expanded)
collapse_subtree(&einfo, True);
else {
if (!start_op(False))
return;
if (dirwin->host != LOCAL) {
show_stop_button(dirwin);
retval = check_connection(dirwin->host, dirwin);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Expand Directory");
break;
case -1:
record_and_alert("Unable to expand directory.",
dirwin->w_shell);
}
hide_stop_button();
end_op();
state = 0;
return;
}
}
path = entry_to_full_path(einfo);
retval = determine_true_path(dirwin->host, path, True,
dirwin->cache_mode, dirwin->cache_mode, &true_path);
XtFree(path);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Expand Directory");
break;
case -1:
record_and_alert("Unable to go expand directory.",
dirwin->w_shell);
break;
case -3:
restore_lost_connection(dirwin->host, dirwin);
}
if (dirwin->host != LOCAL)
hide_stop_button();
end_op();
state = 0;
return;
}
if (is_dir_displayed(dirwin->host, true_path, &temp_dirwin,
&temp_einfo)) {
if (dirwin == temp_dirwin) {
if (dirwin->host != LOCAL)
hide_stop_button();
XtFree(true_path);
end_op();
state = 0;
return;
} else {
if (temp_einfo) /* Sanity check */
fatal_error("Bug in HandleMouseEvents()");
close_directory_window(temp_dirwin);
}
}
XtFree(true_path);
switch (expand_subtree(&einfo, dirwin->cache_mode,
dirwin->cache_mode)) {
case -6:
record_abort("Expand Directory");
break;
case -1:
record_and_alert("Unable to go expand directory.",
dirwin->w_shell);
break;
case -3:
restore_lost_connection(dirwin->host, dirwin);
break;
case 1:
report_cache_use(dirwin, True);
}
if (dirwin->host != LOCAL)
hide_stop_button();
end_op();
}
state = 0;
return;
} else if (einfo == prev_einfo &&
event->xbutton.time-prev_time < multiclick_interval) {
clear_selected_entries();
update_dir_controls();
if ((einfo->type == FILE_TYPE)
|| (einfo->type == EXECUTABLE_TYPE)) {
list = create_null_array_list();
rel_path = entry_to_rel_path(einfo);
add_to_array_list(&list, rel_path);
XtFree(rel_path);
if (!start_op(True))
return;
retval = init_view(dirwin, list);
release_array_list(list);
} else {
if (!start_op(False))
return;
if (dirwin->host != LOCAL) {
show_stop_button(dirwin);
retval = check_connection(dirwin->host, dirwin);
if (retval < 0) {
switch (retval) {
case -6:
record_abort("Go to Directory");
break;
case -1:
record_and_alert("Unable to go to directory.",
dirwin->w_shell);
}
hide_stop_button();
end_op();
state = 0;
return;
}
}
path = entry_to_full_path(einfo);
retval = display_dir(dirwin->host, dirwin, path, False, True,
dirwin->cache_mode, dirwin->cache_mode);
XtFree(path);
switch (retval) {
case -6:
record_abort("Go to Directory");
break;
case -1:
record_and_alert("Unable to go to directory.",
dirwin->w_shell);
break;
case -3:
restore_lost_connection(dirwin->host, dirwin);
}
if (dirwin->host != LOCAL)
hide_stop_button();
end_op();
}
state = 0;
} else {
XtGrabPointer(dirwin->w_drawingArea, True,
ButtonReleaseMask|Button1MotionMask, GrabModeAsync,
GrabModeAsync, None, None, CurrentTime);
prev_einfo = einfo;
prev_time = event->xbutton.time;
button_press_x = x;
button_press_y = y;
if (einfo->state == UNSELECTED) {
toggle_entry(einfo);
state = 5;
hilited_einfo = NULL;
} else
state = 3;
}
break;
case ButtonRelease:
if (event->xbutton.button != Button1)
return;
if (state > 0)
XtUngrabPointer(src_dirwin->w_drawingArea, CurrentTime);
x = virtual_x(dirwin, event->xbutton.x);
y = virtual_y(dirwin, event->xbutton.y);
einfo = xy_to_entry(dirwin, x, y, &part);
switch (state) {
case 1:
move_toggle_rect(x, y);
remove_toggle_rect();
break;
case 2:
if (hilited_einfo) {
unhilite_entry(hilited_einfo);
hilited_einfo = NULL;
}
restore_prev_cursor();
remove_move_outlines();
if (einfo && (einfo->type == DIRECTORY_TYPE) &&
(einfo->state == UNSELECTED)) {
if (event->xbutton.state&ControlMask)
init_move(src_dirwin, dirwin, einfo);
else
init_copy(src_dirwin, dirwin, einfo);
} else if (dirwin != src_dirwin) {
if (event->xbutton.state&ControlMask)
init_move(src_dirwin, dirwin, NULL);
else
init_copy(src_dirwin, dirwin, NULL);
}
break;
case 3:
if ((einfo == prev_einfo) && (einfo->state == SELECTED))
toggle_entry(einfo);
break;
case 4:
unset_toggle_rect_timer();
move_toggle_rect(x, y);
remove_toggle_rect();
break;
case 5:
break;
}
state = 0;
break;
case MotionNotify:
if (event->xbutton.root != root_window)
break;
x = virtual_x(dirwin, event->xbutton.x);
y = virtual_y(dirwin, event->xbutton.y);
einfo = xy_to_entry(dirwin, x, y, &part);
switch (state) {
case 1:
case 4:
move_toggle_rect(x, y);
break;
case 3:
case 5:
delta_x = x-button_press_x;
delta_y = y-button_press_y;
if (delta_x*delta_x+delta_y*delta_y < MIN_MOTION*MIN_MOTION)
break;
state = 2;
init_outlines(src_dirwin, button_press_x, button_press_y);
use_outlines_cursor();
case 2:
move_outlines(dirwin->w_drawingArea, event->xbutton.x,
event->xbutton.y);
if (hilited_einfo && hilited_einfo != einfo) {
unhilite_entry(hilited_einfo);
hilited_einfo = NULL;
}
if (einfo && part == ICON_NAME && einfo->state == UNSELECTED
&& einfo->type == DIRECTORY_TYPE && einfo != hilited_einfo) {
hilite_entry(einfo);
hilited_einfo = einfo;
}
break;
}
break;
case EnterNotify:
if (state == 4) {
state = 1;
unset_toggle_rect_timer();
}
break;
case LeaveNotify:
if (state == 1) {
state = 4;
set_toggle_rect_timer();
}
}
}
/*
* xy_to_entry - Determine the entry at coordinates (x, y). Returns NULL
* if no entry at this position. If entry is found, part
* is set to "CONTROL" if (x, y) falls in a tree view
* control, or to "ICON_NAME" if (x, y) falls on the entry
* icon or name.
*/
struct entry_info *
xy_to_entry(dirwin, x, y, part)
struct dirwin_st *dirwin;
int x;
int y;
int *part;
{
int indx;
int row;
int col;
struct entry_info *einfo;
int x_offset;
int y_offset;
if (dirwin->nentries == 0)
return NULL;
if (x < HMARGIN || y < 0)
return NULL;
switch (dirwin->layout) {
case TABULAR:
case ICONIC:
col = (x-HMARGIN)/(dirwin->max_entry_width+HSPACING);
if (col >= dirwin->ncols)
return NULL;
row = y/(dirwin->entry_height+VSPACING);
if (row >= dirwin->nrows
|| row >= dirwin->first_visible_row+dirwin->nrows_visible)
return NULL;
indx = col*dirwin->nrows+row;
if (indx >= dirwin->nentries)
return NULL;
einfo = &dirwin->entries[indx];
x_offset = x-HMARGIN-col*(dirwin->max_entry_width+HSPACING);
if (x_offset >= einfo->width)
return NULL;
y_offset = y-row*(dirwin->entry_height+VSPACING);
if (y_offset >=dirwin->entry_height)
return NULL;
*part = ICON_NAME;
return einfo;
case TREE:
row = y/(dirwin->entry_height+VSPACING);
if (row >= dirwin->nentries
|| row >= dirwin->first_visible_row+dirwin->nrows_visible)
return NULL;
einfo = &dirwin->entries[row];
y_offset = y-row*(dirwin->entry_height+VSPACING);
if (y_offset >=dirwin->entry_height)
return NULL;
x_offset = x-HMARGIN-einfo->level*INDENT;
if (x_offset < 0 || x_offset >= CWIDTH+CMARGIN+einfo->width)
return NULL;
else if (x_offset >= CWIDTH+CMARGIN) {
*part = ICON_NAME;
return einfo;
} else if (einfo->type == DIRECTORY_TYPE) {
*part = CONTROL;
return einfo;
} else
return NULL;
case FULL_INFO:
row = y/(dirwin->entry_height+VSPACING);
if (row >= dirwin->nrows
|| row >= dirwin->first_visible_row+dirwin->nrows_visible)
return NULL;
einfo = &dirwin->entries[row];
if (x >= HMARGIN+einfo->width)
return NULL;
else {
*part = ICON_NAME;
return einfo;
}
}
return NULL; /* Necessary to keep gcc compiler happy */
}
syntax highlighted by Code2HTML, v. 0.9.1