/***************************************************************************/ /***************************************************************************/ /* */ /* (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 #include #include "xdir.h" #define HPAGEINCREMENT 4 extern Display *display; extern GC gcv1; extern int safe_to_redraw; void scroll_vertical(); void scroll_horizontal(); void cb_scroll_vertical(widget, client_data, call_data) Widget widget; XtPointer client_data; XtPointer call_data; { struct dirwin_st *dirwin = (struct dirwin_st *)client_data; XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)call_data; /* Make sure that the data structures are consistent */ if (!safe_to_redraw) return; scroll_vertical(dirwin, cbs->value); } void scroll_down(dirwin) struct dirwin_st *dirwin; { Widget w_vertical_sb; int value; XtVaGetValues(dirwin->w_scrolledWindow, XmNverticalScrollBar, &w_vertical_sb, NULL); XtVaGetValues(w_vertical_sb, XmNvalue, &value, NULL); scroll_vertical(dirwin, value+1); } void scroll_up(dirwin) struct dirwin_st *dirwin; { Widget w_vertical_sb; int value; XtVaGetValues(dirwin->w_scrolledWindow, XmNverticalScrollBar, &w_vertical_sb, NULL); XtVaGetValues(w_vertical_sb, XmNvalue, &value, NULL); scroll_vertical(dirwin, value-1); } void scroll_vertical(dirwin, value) struct dirwin_st *dirwin; int value; { Dimension drawing_area_width; int width; int height; int x; int y; int offset; int src_x; int src_y; int dest_x; int dest_y; int minimum; int maximum; int slider_size; Widget w_vertical_sb; /* If no change, or value out of range, nothing to do */ XtVaGetValues(dirwin->w_scrolledWindow, XmNverticalScrollBar, &w_vertical_sb, NULL); XtVaGetValues(w_vertical_sb, XmNminimum, &minimum, XmNmaximum, &maximum, XmNsliderSize, &slider_size, NULL ); if (value == dirwin->first_visible_row || value < minimum || value > maximum-slider_size) return; XtVaSetValues(w_vertical_sb, XmNvalue, value, NULL); /* If no overlap, redraw entire window */ if (value >= dirwin->first_visible_row+dirwin->nrows_visible || value+dirwin->nrows_visible <= dirwin->first_visible_row) { dirwin->first_visible_row = value; redraw_entire_dir(dirwin); return; } /* There is overlap. Block copy overlap. Explicitly redraw rest */ XtVaGetValues(dirwin->w_drawingArea, XmNwidth, &drawing_area_width, NULL); if (value > dirwin->first_visible_row) { offset = value-dirwin->first_visible_row; src_x = 0; src_y = VTMARGIN+offset*(dirwin->entry_height+VSPACING); dest_x = 0; dest_y = VTMARGIN; width = drawing_area_width; height = (dirwin->nrows_visible-offset) *(dirwin->entry_height+VSPACING)-VSPACING; XSync(display, 0); XCopyArea(display, XtWindow(dirwin->w_drawingArea), XtWindow(dirwin->w_drawingArea), gcv1, src_x, src_y, width, height, dest_x, dest_y); dirwin->first_visible_row = value; x = virtual_x(dirwin, 0); y = virtual_y(dirwin, VTMARGIN+(dirwin->nrows_visible-offset) *(dirwin->entry_height+VSPACING)); width = drawing_area_width; height = offset*(dirwin->entry_height+VSPACING)-VSPACING; redraw_dir(dirwin, x, y, width, height, True, NULL, 0); } else { offset = dirwin->first_visible_row-value; src_x = 0; src_y = VTMARGIN; dest_x = 0; dest_y = VTMARGIN+offset*(dirwin->entry_height+VSPACING); width = drawing_area_width; height = (dirwin->nrows_visible-offset) *(dirwin->entry_height+VSPACING)-VSPACING; XSync(display, 0); XCopyArea(display, XtWindow(dirwin->w_drawingArea), XtWindow(dirwin->w_drawingArea), gcv1, src_x, src_y, width, height, dest_x, dest_y); dirwin->first_visible_row = value; x = virtual_x(dirwin, 0); y = virtual_y(dirwin, 0); width = drawing_area_width; height = VTMARGIN+offset*(dirwin->entry_height+VSPACING); redraw_dir(dirwin, x, y, width, height, True, NULL, 0); } } void cb_scroll_horizontal(widget, client_data, call_data) Widget widget; XtPointer client_data; XtPointer call_data; { struct dirwin_st *dirwin = (struct dirwin_st *)client_data; XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)call_data; /* Make sure that the data structures are consistent */ if (!safe_to_redraw) return; scroll_horizontal(dirwin, cbs->value); } void scroll_right(dirwin) struct dirwin_st *dirwin; { Widget w_horizontal_sb; int value; XtVaGetValues(dirwin->w_scrolledWindow, XmNhorizontalScrollBar, &w_horizontal_sb, NULL); XtVaGetValues(w_horizontal_sb, XmNvalue, &value, NULL); scroll_horizontal(dirwin, value+1); } void scroll_left(dirwin) struct dirwin_st *dirwin; { Widget w_horizontal_sb; int value; XtVaGetValues(dirwin->w_scrolledWindow, XmNhorizontalScrollBar, &w_horizontal_sb, NULL); XtVaGetValues(w_horizontal_sb, XmNvalue, &value, NULL); scroll_horizontal(dirwin, value-1); } void scroll_horizontal(dirwin, value) struct dirwin_st *dirwin; int value; { Dimension drawing_area_width; Dimension drawing_area_height; int width; int height; int x; int y; int offset; int src_x; int src_y; int dest_x; int dest_y; XRectangle rect; int minimum; int maximum; int slider_size; Widget w_horizontal_sb; /* If no change, or value out of range, nothing to do */ XtVaGetValues(dirwin->w_scrolledWindow, XmNhorizontalScrollBar, &w_horizontal_sb, NULL); XtVaGetValues(w_horizontal_sb, XmNminimum, &minimum, XmNmaximum, &maximum, XmNsliderSize, &slider_size, NULL ); if (value == dirwin->first_visible_hincrement || value < minimum || value > maximum-slider_size) return; XtVaSetValues(w_horizontal_sb, XmNvalue, value, NULL); /* Get drawing area dimensions */ XtVaGetValues(dirwin->w_drawingArea, XmNwidth, &drawing_area_width, XmNheight, &drawing_area_height, NULL ); /* If no overlap, redraw entire window */ if (value >= dirwin->first_visible_hincrement +dirwin->nhincrements_visible || dirwin->nhincrements_visible < dirwin->first_visible_hincrement) { redraw_entire_dir(dirwin); dirwin->first_visible_hincrement = value; goto clear_margins; } /* There is overlap. Block copy overlap. Explicitly redraw rest */ if (value > dirwin->first_visible_hincrement) { offset = value-dirwin->first_visible_hincrement; src_x = offset*HINCREMENT; src_y = 0; dest_x = 0; dest_y = 0; width = drawing_area_width-src_x; height = drawing_area_height; XSync(display, 0); XCopyArea(display, XtWindow(dirwin->w_drawingArea), XtWindow(dirwin->w_drawingArea), gcv1, src_x, src_y, width, height, dest_x, dest_y); rect.x = width; rect.y = 0; rect.width = src_x; rect.height = drawing_area_height; x = virtual_x(dirwin, width); y = virtual_y(dirwin, 0); width = src_x; height = drawing_area_height; redraw_dir(dirwin, x, y, width, height, True, &rect, 1); } else { offset = dirwin->first_visible_hincrement-value; src_x = 0; src_y = 0; dest_x = offset*HINCREMENT; dest_y = 0; width = drawing_area_width-dest_x; height = drawing_area_height; XSync(display, 0); XCopyArea(display, XtWindow(dirwin->w_drawingArea), XtWindow(dirwin->w_drawingArea), gcv1, src_x, src_y, width, height, dest_x, dest_y); rect.x = 0; rect.y = 0; rect.width = dest_x; rect.height = drawing_area_height; x = virtual_x(dirwin, 0); y = virtual_y(dirwin, 0); width = dest_x; height = drawing_area_height; redraw_dir(dirwin, x, y, width, height, True, &rect, 1); } dirwin->first_visible_hincrement = value; clear_margins: /* Clear left margin */ if (value*HINCREMENT < HMARGIN) { x = 0; y = 0; width = HMARGIN-value*HINCREMENT; height = drawing_area_height; XClearArea(display, XtWindow(dirwin->w_drawingArea), x, y, width, height, False); } /* Clear right margin */ if (dirwin->virtual_width-value*HINCREMENT-HMARGIN < (int)drawing_area_width) { x = dirwin->virtual_width-value*HINCREMENT-HMARGIN; y = 0; width = drawing_area_width-x; height = drawing_area_height; XClearArea(display, XtWindow(dirwin->w_drawingArea), x, y, width, height, False); } } /* * reset_scrollbars - Set the display's scrollbars to values appropriate * to its contents. Set vertical scrollbar value to * "vert_value". Set to -1 to retain current value. * Set horizontal scrollbar value to "horiz_value". * Set to -1 to retain current value. */ void reset_scrollbars(dirwin, horiz_value, vert_value) struct dirwin_st *dirwin; int horiz_value; int vert_value; { Widget w_vertical_sb; Widget w_horizontal_sb; int value; int slider_size; int nhincrements; int nhincrements_visible; Dimension drawing_area_width; XtVaGetValues(dirwin->w_scrolledWindow, XmNhorizontalScrollBar, &w_horizontal_sb, XmNverticalScrollBar, &w_vertical_sb, NULL ); /* Adjust vertical scrollbar parameters */ if (XtIsManaged(w_vertical_sb)) { if (vert_value == -1) XtVaGetValues(w_vertical_sb, XmNvalue, &value, NULL); else value = vert_value; if ((dirwin->nrows < value+dirwin->nrows_visible-1) && value) value = MAX(0, dirwin->nrows-dirwin->nrows_visible); slider_size = MIN(dirwin->nrows_visible, dirwin->nrows); XtVaSetValues(w_vertical_sb, XmNmaximum, MAX(dirwin->nrows, 1), XmNsliderSize, MAX(slider_size, 1), XmNpageIncrement, MAX(dirwin->nrows_visible-1, 1), XmNvalue, MIN(value, dirwin->nrows-slider_size), NULL ); XtVaGetValues(w_vertical_sb, XmNvalue, &dirwin->first_visible_row, NULL); } else dirwin->first_visible_row = 0; /* Adjust horizontal scrollbar parameters */ if (XtIsManaged(w_horizontal_sb)) { if (horiz_value == -1) XtVaGetValues(w_horizontal_sb, XmNvalue, &value, NULL); else value = horiz_value; nhincrements = (dirwin->virtual_width+HINCREMENT-1)/HINCREMENT; XtVaGetValues(dirwin->w_drawingArea, XmNwidth, &drawing_area_width, NULL); nhincrements_visible =(int)(drawing_area_width+HINCREMENT-1)/HINCREMENT; slider_size = MIN(nhincrements_visible, nhincrements); XtVaSetValues(w_horizontal_sb, XmNmaximum, MAX(nhincrements, 1), XmNsliderSize, MAX(slider_size, 1), XmNpageIncrement, MAX(HPAGEINCREMENT, 1), XmNvalue, MIN(value, nhincrements-slider_size), NULL ); XtVaGetValues(w_horizontal_sb, XmNvalue, &dirwin->first_visible_hincrement, NULL); dirwin->nhincrements = nhincrements; dirwin->nhincrements_visible = nhincrements_visible; } else dirwin->first_visible_hincrement = 0; } void scroll_entry_into_view(einfo) struct entry_info *einfo; { struct dirwin_st *dirwin = einfo->dirwin; int row = einfo->indx%dirwin->nrows; int value; int x; int col; int left_da_x; int right_da_x; Dimension drawing_area_width; int width; /* Scroll vertically, if necessary */ if (row < dirwin->first_visible_row) scroll_vertical(dirwin, row); else if (row >= dirwin->first_visible_row+dirwin->nrows_visible) scroll_vertical(dirwin, row-dirwin->nrows_visible+1); /* Scroll horizontally, if necessary */ switch (dirwin->layout) { case TABULAR: case ICONIC: col = einfo->indx/dirwin->nrows; x = HMARGIN+col*(dirwin->max_entry_width+HSPACING); width = einfo->width; break; case TREE: x = HMARGIN+einfo->level*INDENT; width = CWIDTH+CMARGIN+einfo->width; break; case FULL_INFO: x = HMARGIN; width = einfo->width; break; } XtVaGetValues(dirwin->w_drawingArea, XmNwidth, &drawing_area_width, NULL); left_da_x = virtual_x(dirwin, 0); right_da_x = left_da_x+drawing_area_width; if (x < left_da_x) { if (dirwin->layout == TREE && einfo->level != 0) value = (x-HMARGIN)/HINCREMENT; else value = 0; scroll_horizontal(dirwin, value); } else if (x+width > right_da_x) { if (dirwin->layout == TREE && einfo->level != 0) value = MAX(x, right_da_x-width-HMARGIN)/HINCREMENT; else value = 0; scroll_horizontal(dirwin, value); } }