/***************************************************************************/
/***************************************************************************/
/* */
/* (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/Xm.h>
#include <sys/time.h>
#include "xdir.h"
#include "urbutton.h"
#define NSTOP_FRAMES 2
#define SDELTA 500000 /* Must be less than 1000000 */
static Pixmap stop_pixmap[NSTOP_FRAMES];
static Pixmap armed_stop_pixmap[NSTOP_FRAMES];
static Pixmap llnlxdir_pixmap;
static Pixmap grey_llnlxdir_pixmap;
static Pixmap armed_llnlxdir_pixmap;
static int stop_state;
static int ur_button_sensitivity;
static struct timeval time_of_next_update;
static struct dirwin_st *stop_dirwin = NULL;
static Pixel ur_button_fg;
static Pixel ur_button_bg;
static Pixel ur_button_armed_color;
static Dimension ur_button_width;
static Dimension ur_button_height;
static Dimension ur_button_ht;
static Dimension ur_button_st;
static int nstop_frame;
static int nstop_frames;
static Widget w_abort_dialog;
extern Display *display;
extern XtAppContext app;
extern Window root_window;
extern int depth;
extern int stop_button_blinking;
void cb_about_xdir();
void cb_stop();
void cb_stop_arm();
void cb_stop_disarm();
void cb_stop_expose();
void cb_llnlxdir_arm();
void cb_llnlxdir_expose();
void create_ur_button_pixmaps();
void draw_ur_button();
Widget show_in_progress_dialog();
/****************************************************************************/
/* */
/* Values of stop_state: */
/* */
/* 0 - initial value when stop button enabled */
/* 1 - stop button armed */
/* 2 - stop button pushed but stop() has not returned True */
/* 3 - stop button pushed and stop() has returned True */
/* */
/****************************************************************************/
/*
* initialize_ur_button - Determine colors and geometry of upper-right
* button. Also, create pixmaps needed to display
* it. "dirwin" identifies the first directory
* window to be created.
*/
void
initialize_ur_button(dirwin)
struct dirwin_st *dirwin;
{
Pixmap stop0_pixmap;
Pixmap armed_stop0_pixmap;
Pixmap stop1_pixmap;
Colormap cmap;
Pixel foreground;
Pixel top_shadow;
Pixel bottom_shadow;
/* Get geometry and colors of upper-right button */
XtVaGetValues(dirwin->w_urButton,
XmNcolormap, &cmap,
XmNbackground, &ur_button_bg,
XmNforeground, &ur_button_fg,
XmNheight, &ur_button_height,
XmNwidth, &ur_button_width,
XmNhighlightThickness, &ur_button_ht,
XmNshadowThickness, &ur_button_st,
NULL
);
XmGetColors(XtScreen(dirwin->w_urButton), cmap, ur_button_bg, &foreground,
&top_shadow, &bottom_shadow, &ur_button_armed_color);
/* Create pixmap for LLNL XDIR button */
create_ur_button_pixmaps(llnlxdir_bits, llnlxdir_width, llnlxdir_height,
&llnlxdir_pixmap, &grey_llnlxdir_pixmap, &armed_llnlxdir_pixmap);
/* Create pixmap for first frame of stop button */
create_ur_button_pixmaps(stop0_bits, stop0_width, stop0_height,
&stop0_pixmap, NULL, &armed_stop0_pixmap);
stop_pixmap[0] = stop0_pixmap;
armed_stop_pixmap[0] = armed_stop0_pixmap;
/* Create pixmap for second frame of stop button */
create_ur_button_pixmaps(stop1_bits, stop1_width, stop1_height,
&stop1_pixmap, NULL, NULL);
stop_pixmap[1] = stop1_pixmap;
armed_stop_pixmap[1] = armed_stop0_pixmap;
}
/*
* add_llnlxdir_button_callbacks - Add LLNL XDIR button callbacks for
* directory window "dirwin".
*/
void
add_llnlxdir_button_callbacks(dirwin)
struct dirwin_st *dirwin;
{
XtAddCallback(dirwin->w_urButton, XmNactivateCallback, cb_about_xdir,
(XtPointer)dirwin);
XtAddCallback(dirwin->w_urButton, XmNarmCallback, cb_llnlxdir_arm,
(XtPointer)dirwin);
XtAddCallback(dirwin->w_urButton, XmNdisarmCallback, cb_llnlxdir_expose,
(XtPointer)dirwin);
XtAddCallback(dirwin->w_urButton, XmNexposeCallback, cb_llnlxdir_expose,
(XtPointer)dirwin);
}
/*
* remove_llnlxdir_button_callbacks - Remove LLNL XDIR button callbacks for
* directory window "dirwin".
*/
void
remove_llnlxdir_button_callbacks(dirwin)
struct dirwin_st *dirwin;
{
XtRemoveCallback(dirwin->w_urButton, XmNactivateCallback, cb_about_xdir,
(XtPointer)dirwin);
XtRemoveCallback(dirwin->w_urButton, XmNarmCallback, cb_llnlxdir_arm,
(XtPointer)dirwin);
XtRemoveCallback(dirwin->w_urButton, XmNdisarmCallback, cb_llnlxdir_expose,
(XtPointer)dirwin);
XtRemoveCallback(dirwin->w_urButton, XmNexposeCallback, cb_llnlxdir_expose,
(XtPointer)dirwin);
}
/*
* add_stop_button_callbacks - Add stop button callbacks for directory
* window "dirwin".
*/
void
add_stop_button_callbacks(dirwin)
struct dirwin_st *dirwin;
{
XtAddCallback(dirwin->w_urButton, XmNactivateCallback, cb_stop,
(XtPointer)dirwin);
XtAddCallback(dirwin->w_urButton, XmNarmCallback, cb_stop_arm,
(XtPointer)dirwin);
XtAddCallback(dirwin->w_urButton, XmNdisarmCallback, cb_stop_disarm,
(XtPointer)dirwin);
XtAddCallback(dirwin->w_urButton, XmNexposeCallback, cb_stop_expose,
(XtPointer)dirwin);
}
/*
* remove_stop_button_callbacks - Remove stop button callbacks for directory
* window "dirwin".
*/
void
remove_stop_button_callbacks(dirwin)
struct dirwin_st *dirwin;
{
XtRemoveCallback(dirwin->w_urButton, XmNactivateCallback, cb_stop,
(XtPointer)dirwin);
XtRemoveCallback(dirwin->w_urButton, XmNarmCallback, cb_stop_arm,
(XtPointer)dirwin);
XtRemoveCallback(dirwin->w_urButton, XmNdisarmCallback, cb_stop_disarm,
(XtPointer)dirwin);
XtRemoveCallback(dirwin->w_urButton, XmNexposeCallback, cb_stop_expose,
(XtPointer)dirwin);
}
/*
* show_stop_button - Replace the "LLNL XDIR" button with the stop button.
* Call hide_stop_button() to restore the "LLNL XDIR"
* button. stop() must be frequently called to animate
* the stop button. It is a fatal error not to call
* hide_stop_button() between calls to this function.
*/
void
show_stop_button(dirwin)
struct dirwin_st *dirwin;
{
struct timeval current_time;
struct timeval delta;
/* Sanity check */
if (stop_dirwin)
fatal_error(
"Trouble in show_stop_button() - Operation already in progress.");
/* Remember which directory window has the stop button */
stop_dirwin = dirwin;
/* Remember sensitivity of LLNL XDIR button */
ur_button_sensitivity = XtIsSensitive(stop_dirwin->w_urButton);
XtSetSensitive(stop_dirwin->w_urButton, True);
/* Replace the LLNL XDIR button's callbacks with the stop button's */
remove_llnlxdir_button_callbacks(stop_dirwin);
add_stop_button_callbacks(stop_dirwin);
/* Control blinking */
if (stop_button_blinking)
nstop_frames = NSTOP_FRAMES;
else
nstop_frames = 1;
/* Draw first frame of animated stop button */
draw_ur_button(stop_dirwin, stop_pixmap[0]);
nstop_frame = 0;
/* Initialize stop button's state variables */
stop_state = 0;
/* Calculate time to update animated stop button with next frame */
gettimeofday(¤t_time, NULL);
delta.tv_sec = 0;
delta.tv_usec = SDELTA;
add_timevals(¤t_time, &delta, &time_of_next_update);
}
/*
* cb_stop - Callback to process stop button.
*/
void
cb_stop(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
/* Sanity check */
if (stop_state > 1)
fatal_error("Bug in cb_stop()");
/* Remember that stop button was pushed */
stop_state = 2;
/* Restore the LLNL XDIR button after clearing pending X events */
remove_stop_button_callbacks(stop_dirwin);
while (XPending(display))
XtAppProcessEvent(app, (XtInputMask)XtIMAll);
add_llnlxdir_button_callbacks(stop_dirwin);
draw_ur_button(stop_dirwin, llnlxdir_pixmap);
XtSetSensitive(stop_dirwin->w_urButton, ur_button_sensitivity);
}
/*
* stop - Returns True if the stop button has been pushed pushed, else
* False. Also, this function takes care of updating the animated
* stop button; hence this function should be called frequently
* (i.e., about every one-tenth second) when the stop button is
* being displayed so that the animation will be smooth.
*/
stop()
{
struct timeval current_time;
struct timeval delta;
/* Sanity check */
if (!stop_dirwin)
fatal_error("Bug in stop()");
switch (stop_state) {
case 0: /* Should stop button should be updated */
gettimeofday(¤t_time, NULL);
if (cmp_timevals(¤t_time, &time_of_next_update) > 0) {
nstop_frame = (nstop_frame+1)%nstop_frames;
draw_ur_button(stop_dirwin, stop_pixmap[nstop_frame]);
gettimeofday(¤t_time, NULL);
delta.tv_sec = 0;
delta.tv_usec = SDELTA;
add_timevals(¤t_time, &delta, &time_of_next_update);
}
case 1: /* Process X events in case stop button has been pushed */
while (XEventsQueued(display, QueuedAfterReading)) {
XtAppProcessEvent(app, (XtInputMask)XtIMAll);
if (stop_state == 2) {
stop_state = 3; /* Remember that True was returned */
return True;
}
}
return False;
case 2: /* Stop button has been pushed */
stop_state = 3; /* Remember that True was returned */
return True;
case 3: /* Can return True only once after stop button pressed */
return False;
}
/* Should not get here, but make compiler happy */
return False;
}
/*
* stop_button_is_showing - Returns True is stop button is showing on
* specified directory window, else False;
*/
stop_button_is_showing(dirwin)
struct dirwin_st *dirwin;
{
return (dirwin == stop_dirwin);
}
/*
* hide_stop_button - Replace the stop button with the "LLNL XDIR" button.
* Call show_stop_button() to restore the "LLNL XDIR"
* button.
*/
void
hide_stop_button()
{
/* Is the stop button showing? */
if (!stop_dirwin)
return;
/* Restore the LLNL XDIR button after clearing pending X events */
if (stop_state < 2) {
remove_stop_button_callbacks(stop_dirwin);
while (XPending(display))
XtAppProcessEvent(app, (XtInputMask)XtIMAll);
add_llnlxdir_button_callbacks(stop_dirwin);
draw_ur_button(stop_dirwin, llnlxdir_pixmap);
XtSetSensitive(stop_dirwin->w_urButton, ur_button_sensitivity);
}
/* Done with stop button */
stop_dirwin = NULL;
}
/*
* cb_llnlxdir_expose - Callback to handle LLNL XDIR button expose events.
*/
void
cb_llnlxdir_expose(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
/* Redraw the button */
if (XtIsSensitive(dirwin->w_urButton))
draw_ur_button(dirwin, llnlxdir_pixmap);
else
draw_ur_button(dirwin, grey_llnlxdir_pixmap);
}
/*
* cb_stop_expose - Callback to handle stop button expose events.
*/
void
cb_stop_expose(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
/* Sanity check */
if (dirwin != stop_dirwin)
fatal_error("Bug in cb_stop_expose()");
/* Redraw the button */
draw_ur_button(dirwin, stop_pixmap[nstop_frame]);
}
/*
* cb_llnlxdir_arm - Callback to handle LLNL XDIR button arm events.
*/
void
cb_llnlxdir_arm(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
draw_ur_button(dirwin, armed_llnlxdir_pixmap);
}
/*
* cb_stop_arm - Callback to handle stop button arm events.
*/
void
cb_stop_arm(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
draw_ur_button(dirwin, armed_stop_pixmap[nstop_frame]);
stop_state = 1; /* Stop button is armed */
}
/*
* cb_stop_disarm - Callback to handle stop button disarm events.
*/
void
cb_stop_disarm(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
stop_state = 0; /* Stop button no longer armed */
}
/*
* create_ur_button_pixmaps - Creates a normal, a greyed-out, and an armed
* pixmap from bitmap data for the "upper-right"
* drawn button and returns them. "bits", "width",
* and "height" describe the bitmap.
*/
void
create_ur_button_pixmaps(bits, width, height, normal_pixmap, normal_grey_pixmap,
armed_pixmap)
char *bits;
int width;
int height;
Pixmap *normal_pixmap;
Pixmap *normal_grey_pixmap;
Pixmap *armed_pixmap;
{
Pixmap temp_pixmap;
GC gc;
int bytes_in_row;
char *grey_bits;
unsigned char mask;
int i;
int j;
int indx;
int offset = ur_button_ht+ur_button_st;
unsigned int w = ur_button_width-2*offset;
unsigned int h = ur_button_height-2*offset;
/* Need a graphics context */
gc = XCreateGC(display, root_window, (unsigned long)0, NULL);
/* Create normal pixmap */
if (normal_pixmap) {
temp_pixmap = XCreatePixmapFromBitmapData(display, root_window, bits,
width, height, ur_button_fg, ur_button_bg, depth);
*normal_pixmap = XCreatePixmap(display, root_window, w, h, depth);
XSetForeground(display, gc, ur_button_bg);
XFillRectangle(display, *normal_pixmap, gc, 0, 0, w+1, h+1);
XCopyArea(display, temp_pixmap, *normal_pixmap, gc, 0, 0,
(unsigned int)width, (unsigned int)height,
(int)((w-width)/2), (int)((h-height)/2));
XFreePixmap(display, temp_pixmap);
}
/* Create an armed pixmap */
if (armed_pixmap) {
temp_pixmap = XCreatePixmapFromBitmapData(display, root_window, bits,
width, height, ur_button_fg, ur_button_armed_color, depth);
*armed_pixmap = XCreatePixmap(display, root_window, w, h, depth);
XSetForeground(display, gc, ur_button_armed_color);
XFillRectangle(display, *armed_pixmap, gc, 0, 0, w+1, h+1);
XCopyArea(display, temp_pixmap, *armed_pixmap, gc, 0, 0,
(unsigned int)width, (unsigned int)height,
(int)((w-width)/2), (int)((h-height)/2));
XFreePixmap(display, temp_pixmap);
}
/* Create greyed out pixmap */
if (normal_grey_pixmap) {
bytes_in_row = (width+7)/8;
grey_bits = XtMalloc(bytes_in_row*height);
indx = 0;
for (j=0; j<height; j++) {
mask = (j%2)?0xaa:0x55;
for (i=0; i<bytes_in_row; i++) {
grey_bits[indx] = bits[indx]&mask;
indx++;
}
}
temp_pixmap = XCreatePixmapFromBitmapData(display, root_window,
grey_bits, width, height, ur_button_fg, ur_button_bg, depth);
XtFree(grey_bits);
*normal_grey_pixmap = XCreatePixmap(display, root_window, w, h, depth);
XSetForeground(display, gc, ur_button_bg);
XFillRectangle(display, *normal_grey_pixmap, gc, 0, 0, w+1, h+1);
XCopyArea(display, temp_pixmap, *normal_grey_pixmap, gc, 0, 0,
(unsigned int)width, (unsigned int)height,
(int)((w-width)/2), (int)((h-height)/2));
XFreePixmap(display, temp_pixmap);
}
/* Free the graphics context */
XFreeGC(display, gc);
}
/*
* draw_ur_button - Copies "pixmap" onto the specified directory window's
* upper-right button. "pixmap" should have been created
* using create_ur_button_pixmaps().
*/
void
draw_ur_button(dirwin, pixmap)
struct dirwin_st *dirwin;
Pixmap pixmap;
{
int offset = ur_button_ht+ur_button_st;
unsigned int w = ur_button_width-2*offset;
unsigned int h = ur_button_height-2*offset;
XCopyArea(display, pixmap, XtWindow(dirwin->w_urButton),
XDefaultGCOfScreen(XtScreen(dirwin->w_urButton)), 0, 0, w, h,
offset, offset);
XSync(display, 0);
}
/*
* show_abort_dialog - Pop up a dialog that displays an abort-in-progress
* message over directory window that contains the
* stop button.
*/
void
show_abort_dialog()
{
/* Sanity check */
if (!stop_dirwin)
fatal_error("Bug in show_abort_dialog()");
w_abort_dialog = show_in_progress_dialog(stop_dirwin, "Abort in Progress",
"ABORT OPERATION IN PROGRESS\n\n------------\n\nPLEASE BE PATIENT");
}
/*
* hide_abort_dialog - Pop down dialog that displays an abort-in-progress
* message.
*/
void
hide_abort_dialog()
{
hide_in_progress_dialog(w_abort_dialog);
}
syntax highlighted by Code2HTML, v. 0.9.1