/***************************************************************************/ /***************************************************************************/ /* */ /* (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" #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; jw_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); }