summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/gui/xaw_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/xdvik/gui/xaw_menu.c')
-rw-r--r--Build/source/texk/xdvik/gui/xaw_menu.c1449
1 files changed, 1449 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/gui/xaw_menu.c b/Build/source/texk/xdvik/gui/xaw_menu.c
new file mode 100644
index 00000000000..ef9b387f8c1
--- /dev/null
+++ b/Build/source/texk/xdvik/gui/xaw_menu.c
@@ -0,0 +1,1449 @@
+/*
+ * Copyright (c) 2001-2004 the xdvik development team
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Menu bar implementation for the Athena widget set.
+ */
+#include "xdvi-config.h"
+#include "xdvi.h"
+
+#include "c-openmx.h"
+#include "events.h"
+#include "dvi-draw.h"
+#include "dvi-init.h"
+#include "statusline.h"
+#include "pagesel.h"
+#include "util.h"
+#include "x_util.h"
+#include "xaw_menu.h"
+#include "message-window.h"
+#include "my-snprintf.h"
+#include "filehist.h"
+#ifdef NEW_MENU_CREATION
+#include "menu.h"
+#endif /* NEW_MENU_CREATION */
+
+#ifndef MOTIF /* entire file */
+
+#include <ctype.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h> /* needed for def. of XtNiconX */
+
+#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/MenuButton.h>
+#include <X11/Xaw/Sme.h>
+#include <X11/Xaw/SmeBSB.h>
+#include <X11/Xaw/SmeLine.h>
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/Text.h>
+#include <X11/Xaw/Panner.h>
+#include <X11/Xaw/Porthole.h>
+#include <X11/Xaw/Command.h>
+
+#ifndef MAX
+# define MAX(i, j) ( (i) > (j) ? (i) : (j) )
+#endif
+
+
+#ifndef NEW_MENU_CREATION
+#define SEP_CHAR ':' /* character separating entries in translations lines */
+#endif
+
+/* needed to count the callbacks */
+static int destroy_count = 0;
+
+/* width of button panel */
+static int my_panel_width = 0;
+
+/* access method for panel width */
+int
+get_panel_width(void)
+{
+ int retval = 0;
+ if (resource.expert_mode & XPRT_SHOW_BUTTONS)
+ retval = my_panel_width;
+ TRACE_GUI((stderr, "get_panel_width: %d", retval));
+ return retval;
+}
+
+#ifndef NEW_MENU_CREATION
+typedef enum { INVALID, /* some error */
+ NONE, /* no new button created */
+ MENU_SEPARATOR, MENU_BUTTON, MENU_ENTRY, COMMAND_BUTTON } buttonTypeT;
+
+struct button_info {
+ struct button_info *next;
+ char *label;
+ struct xdvi_action *action;
+ Widget widget;
+ buttonTypeT type;
+};
+
+static Widget panner = 0;
+static struct button_info *b_head = NULL;
+
+#define MAX_MENU_NUM 128
+#define MAX_BUTTON_NUM 128
+
+static struct menu_list_ {
+ char *name;
+ Widget button_widget;
+ Widget popup_widget;
+} menu_list[MAX_MENU_NUM];
+
+#endif /* not NEW_MENU_CREATION */
+
+#ifdef NEW_MENU_CREATION
+/*
+ ================================================================================
+ Pixmaps indicating the state of menu buttons (radiobutton/checkbox
+ on/off, cascading menu). Inspired by menu.c, `check_bits' in the xterm source.
+ ================================================================================
+*/
+#include "xaw_bitmaps.h"
+static Pixmap menu_check_on_bitmap;
+static Pixmap menu_check_off_bitmap;
+static Pixmap menu_radio_on_bitmap;
+static Pixmap menu_radio_off_bitmap;
+static Pixmap menu_arrow_bitmap;
+#else
+#include "xaw_bitmaps.h"
+/* lifted from menu.c, check_bits in xterm */
+static Pixmap menu_check_bitmap;
+static Pixmap menu_arrow_bitmap;
+#endif /* NEW_MENU_CREATION */
+
+/*
+ ============================================================
+ Hack for pullright menus part I: data
+ ============================================================
+*/
+
+/* There are a few custom widgets for pullright menus out there, but
+ * these are old and potentially buggy, so just do it manually via an
+ * event handler, similar to Motif tooltips.
+ */
+static XtIntervalId m_timeout = 0;
+static Widget m_active_submenu = NULL; /* if not NULL, the currently active pullright */
+static Widget m_submenu = NULL; /* parent of the currently active pullright
+ (i.e. the menu label in the parent window) */
+
+static void ActPopdownSubmenus(Widget w, XEvent *event, String *params, Cardinal *num_params);
+
+/* to safely pop down the pullright, this callback is added to its parent menu */
+static XtActionsRec menu_actions[] = {
+ { "popdown-submenus", ActPopdownSubmenus }
+};
+
+static XtAccelerators menu_accels;
+
+struct pullright_position_info {
+ Position y;
+ Dimension w;
+ Dimension h;
+ Dimension border_width;
+ Widget menu;
+};
+
+
+#ifdef NEW_MENU_CREATION
+/*
+ * Set all pixmaps indicating the state of the wigdet pointed to by `elems'.
+ */
+void
+xaw_set_button_state(struct button_elems *elems, Boolean on)
+{
+ static Arg args[] = {
+ { XtNleftBitmap, (XtArgVal)0 },
+ { XtNrightBitmap, (XtArgVal)0 }
+ };
+
+ if (elems->type == BT_CHECK)
+ args[0].value = on ? menu_check_on_bitmap : menu_check_off_bitmap;
+ else if (elems->type == BT_RADIO)
+ args[0].value = on ? menu_radio_on_bitmap : menu_radio_off_bitmap;
+ if (elems->submenu != NULL)
+ args[1].value = menu_arrow_bitmap;
+
+ XtSetValues(elems->widget, args, XtNumber(args));
+}
+
+/*
+ * Initialize the bitmaps.
+ */
+void
+xaw_initialize_menu_bitmaps(void)
+{
+ static Boolean initialized = False;
+ if (!initialized) {
+ initialized = True;
+ menu_check_on_bitmap
+ = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)menu_check_on_bits, MENU_BITMAP_W, MENU_BITMAP_H);
+ menu_check_off_bitmap
+ = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)menu_check_off_bits, MENU_BITMAP_W, MENU_BITMAP_H);
+ menu_radio_on_bitmap
+ = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)menu_radio_on_bits, MENU_BITMAP_W, MENU_BITMAP_H);
+ menu_radio_off_bitmap
+ = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)menu_radio_off_bits, MENU_BITMAP_W, MENU_BITMAP_H);
+ menu_arrow_bitmap
+ = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)menu_arrow_bits, MENU_ARROW_W, MENU_ARROW_H);
+ }
+}
+
+#else
+
+/* toggle `checked' symbol on xaw menu w */
+void
+toggle_tick(Boolean val, Widget w)
+{
+ static Arg args = { XtNleftBitmap, (XtArgVal) 0 };
+ if (val)
+ args.value = (XtArgVal) menu_check_bitmap;
+ else
+ args.value = None;
+ XtSetValues(w, &args, 1);
+}
+
+void
+toggle_menu(int val, XtActionProc proc)
+{
+ struct button_info *bp;
+
+ for (bp = b_head; bp != NULL; bp = bp->next) {
+ if (bp->action != NULL && bp->action->proc == proc && bp->action->param != NULL) {
+ TRACE_GUI((stderr, "found proc; param: |%s|", bp->action->param));
+ if (strcmp(bp->action->param, "toggle") == 0) {
+ if (val != 0)
+ toggle_tick(True, bp->widget);
+ else
+ toggle_tick(False, bp->widget);
+ }
+ else if (strcmp(bp->action->param, "a") == 0) {
+ if (val == shrink_to_fit())
+ toggle_tick(True, bp->widget);
+ else
+ toggle_tick(False, bp->widget);
+ }
+ else {
+ int testval = strtoul(bp->action->param, (char **)NULL, 10);
+ if (testval == val) {
+ TRACE_GUI((stderr, "enabling param |%s|", bp->action->param));
+ toggle_tick(True, bp->widget);
+ }
+ else
+ toggle_tick(False, bp->widget);
+ }
+ }
+ }
+}
+
+/* initialize `checked' symbol on xaw menu w */
+static void
+initialize_tick_marks(void)
+{
+ int use_gs;
+ if (menu_check_bitmap == None) {
+ int check_width = 9;
+ int check_height = 8;
+ unsigned char check_bits[] = {
+ 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
+ 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00
+ };
+
+ menu_check_bitmap = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)check_bits, check_width, check_height);
+ }
+
+ /* initialize tickmarks for all possible actions */
+ use_gs = resource.postscript;
+#ifdef PS_GS
+ if (!resource.useGS)
+ use_gs = 0;
+#endif
+
+ toggle_menu(use_gs, Act_set_ps);
+ toggle_menu(resource.gs_alpha, Act_set_gs_alpha);
+ toggle_menu(resource.keep_flag, Act_set_keep_flag);
+ toggle_menu(resource.pixels_per_inch / mane.shrinkfactor, Act_shrink_to_dpi);
+ toggle_menu(mane.shrinkfactor, Act_set_shrink_factor);
+ toggle_menu(resource.use_tex_pages, Act_use_tex_pages);
+ toggle_menu(resource.mouse_mode, Act_switch_mode);
+}
+#endif /* NEW_MENU_CREATION */
+
+/* ================================================================================
+ ================================================================================
+*/
+
+static Widget line_widget, panel_widget;
+
+/* used for communication with the pagelist in xaw_create_pagelist */
+static int my_y_pos;
+
+/* access function: panel, height of buttons etc. */
+void
+xaw_create_pagelist(void)
+{
+ Dimension height, width;
+ int button_width = get_panel_width() - 2 * (resource.btn_side_spacing + resource.btn_border_width);
+
+ XtVaGetValues(globals.widgets.clip_widget, XtNheight, &height, NULL);
+ width = MAX(button_width, xaw_get_pagelist_size());
+ height -= resource.btn_top_spacing + resource.btn_border_width + my_y_pos;
+ xaw_create_pagelist_widgets(height, width, my_y_pos, panel_widget);
+}
+
+
+static XtCallbackRec command_call[] = {
+ {handle_command, NULL},
+ {NULL, NULL},
+};
+
+#ifdef NEW_MENU_CREATION
+void xaw_create_menu(struct button_info *items, Widget parent, int menu_depth, int *ret_width)
+{
+
+}
+
+Widget
+xaw_create_menu_widgets(Widget parent)
+{
+ /* hack to disable the magnifier in the panel: */
+ XtTranslations panel_translations = XtParseTranslationTable("#augment <ButtonPress>:");
+
+ line_widget = XtVaCreateWidget("line", widgetClass, parent,
+ XtNbackground, (XtArgVal)resource.fore_Pixel,
+ XtNwidth, (XtArgVal)1,
+ XtNfromHoriz, (XtArgVal)globals.widgets.vport_widget,
+ XtNborderWidth, (XtArgVal)0,
+ XtNtop, (XtArgVal)XtChainTop,
+ XtNbottom, (XtArgVal)XtChainBottom,
+ XtNleft, (XtArgVal)XtChainRight,
+ XtNright, (XtArgVal)XtChainRight,
+ NULL);
+ panel_widget = XtVaCreateWidget("panel", compositeWidgetClass, parent,
+ XtNborderWidth, (XtArgVal)0,
+ XtNfromHoriz, (XtArgVal)line_widget,
+ XtNtranslations, (XtArgVal)panel_translations,
+ XtNtop, (XtArgVal)XtChainTop,
+ XtNbottom, (XtArgVal)XtChainBottom,
+ XtNleft, (XtArgVal)XtChainRight,
+ XtNright, (XtArgVal)XtChainRight,
+ NULL);
+ return panel_widget;
+}
+
+#else /* NEW_MENU_CREATION */
+
+
+static void
+filehist_select_cb(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ char *label, *ptr;
+ int idx;
+
+ UNUSED(client_data);
+ UNUSED(call_data);
+
+ XtVaGetValues(w, XtNlabel, &label, NULL);
+
+ idx = strtol(label, &ptr, 10) - 1;
+ while (isspace(*ptr))
+ ptr++;
+ TRACE_GUI((stderr, "User selected: %d, `%s'", idx, ptr));
+ if (idx == 0) {
+ globals.ev.flags |= EV_RELOAD;
+ return;
+ }
+ file_history_open(ptr);
+}
+
+static void
+update_menu_labels(Widget menu)
+{
+ WidgetList children;
+ int num_children;
+ int i;
+
+ static char *buf = NULL;
+ static size_t buf_len = 0;
+ size_t new_len;
+
+ XtVaGetValues(menu,
+ XtNnumChildren, &num_children,
+ XtNchildren, &children,
+ NULL);
+ for (i = 0; i < (int)file_history_size(); i++) {
+ int dummy_page;
+ char *filename;
+
+ if ((filename = file_history_get_elem(i, &dummy_page)) == NULL) {
+ XDVI_ERROR((stderr, "Error accessing element %d of file history", i));
+ continue;
+ }
+
+ new_len = LENGTH_OF_INT + strlen(filename) + 1;
+ if (new_len > buf_len) {
+ buf = xrealloc(buf, new_len);
+ buf_len = new_len;
+ }
+
+ sprintf(buf, "%d %s", i + 1, filename);
+ XtVaSetValues(children[i], XtNlabel, buf, NULL);
+ TRACE_GUI((stderr, "child %d: `%s'", i, buf));
+ }
+
+ /* if history size < number of menu entries, destroy excess menu entries */
+ for (; i < num_children; i++) {
+ XtDestroyWidget(children[i]);
+ }
+}
+
+void
+filehist_menu_add_entry(const char *filename)
+{
+ static char *buf = NULL;
+ static size_t buf_len = 0;
+ size_t new_len = LENGTH_OF_INT + strlen(filename) + 1;
+
+ Widget menu;
+ /* Don't report an error here, since "filehist_pullright" is only created on-demand
+ when user clicks on menu, but this may be called before from the event loop.
+ (The menu will still contain this entry when it's created later.) */
+ if (get_widget_by_name(&menu, globals.widgets.top_level, "filehist_pullright", False)) {
+ int num_children;
+ Widget w;
+
+ if (new_len > buf_len) {
+ buf = xrealloc(buf, new_len);
+ buf_len = new_len;
+ }
+
+ XtVaGetValues(menu, XtNnumChildren, &num_children, NULL);
+ sprintf(buf, "%d %s", num_children + 1, filename);
+
+ w = XtVaCreateManagedWidget("_filehist", smeBSBObjectClass, menu,
+ XtNlabel, buf,
+ XtNleftMargin, 10,
+ NULL);
+ XtAddCallback(w, XtNcallback, filehist_select_cb, NULL);
+ update_menu_labels(menu);
+ }
+}
+
+void
+filehist_menu_refresh(void)
+{
+ Widget menu;
+
+ /* Don't report an error here, since "filehist_pullright" is only created on-demand
+ when user clicks on menu, but this may be called before from the event loop.
+ (The menu will still contain this entry when it's created later.) */
+ if (get_widget_by_name(&menu, globals.widgets.top_level, "filehist_pullright", False)) {
+ update_menu_labels(menu);
+ }
+}
+
+
+static void
+filehist_insert_submenu(int idx, const char *filename, int pageno, void *data)
+{
+ Widget menu = (Widget)data;
+ Widget w;
+ static char *buf = NULL;
+ static size_t buf_len = 0;
+ size_t new_len = LENGTH_OF_INT + strlen(filename) + 1;
+
+ UNUSED(pageno);
+
+ if (new_len > buf_len) {
+ buf = xrealloc(buf, new_len);
+ buf_len = new_len;
+ }
+
+ sprintf(buf, "%d %s", idx + 1, filename);
+ TRACE_GUI((stderr, "Creating menu `%s'", buf));
+ w = XtVaCreateManagedWidget("_filehist", smeBSBObjectClass, menu,
+ XtNlabel, buf,
+ XtNleftMargin, 10,
+ NULL);
+ XtAddCallback(w, XtNcallback, filehist_select_cb, NULL);
+}
+
+
+/*
+ ============================================================
+ Hack for pullright menus part II: callbacks and functions
+ ============================================================
+*/
+
+/* callback to pop down the currently active pullright */
+static void
+ActPopdownSubmenus(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ UNUSED(w);
+ UNUSED(event);
+ UNUSED(params);
+ UNUSED(num_params);
+
+ if (m_timeout != 0)
+ XtRemoveTimeOut(m_timeout);
+ m_timeout = 0;
+ if (m_active_submenu != NULL)
+ XtPopdown(m_active_submenu);
+}
+/* create a parent shell for the pullright menu entries */
+static Widget
+create_files_submenu(void)
+{
+ Widget popup = XtCreatePopupShell("filehist_pullright", simpleMenuWidgetClass, globals.widgets.top_level,
+ NULL, 0);
+ file_history_enumerate(filehist_insert_submenu, popup);
+ return popup;
+}
+
+/* Acutally pop up the pullright menu */
+static void
+popup_pullright(XtPointer client_data, XtIntervalId *id)
+{
+ int pos_x, pos_y;
+ Dimension w1;
+ Window dummy;
+ static Widget files_submenu = NULL;
+ struct pullright_position_info *info = (struct pullright_position_info *)client_data;
+
+ UNUSED(id);
+
+ if (files_submenu == NULL)
+ files_submenu = create_files_submenu();
+ /* XtManageChild(files_submenu); */
+ XTranslateCoordinates(DISP, XtWindow(XtParent(m_submenu)), RootWindowOfScreen(SCRN),
+ info->w, info->y, &pos_x, &pos_y, &dummy);
+ XtRealizeWidget(files_submenu);
+ XtVaGetValues(files_submenu, XtNwidth, &w1, NULL);
+ TRACE_GUI((stderr, "Popping up at %d, %d, %d, %d", pos_x, pos_y, w1, WidthOfScreen(SCRN)));
+
+ /* if not sufficient place on the right, pop it up on the left */
+ /* fprintf(stderr, "border_width: %d\n", info->border_width); */
+ if (pos_x + w1 > WidthOfScreen(SCRN)) {
+ /* fprintf(stderr, "%d > %d!\n", pos_x + w1, WidthOfScreen(SCRN)); */
+ pos_x -= (w1 + info->w + 3 * info->border_width);
+ /* fprintf(stderr, "new x: %d\n", pos_x); */
+ }
+ else {
+ pos_x += info->border_width;
+ }
+ XtVaSetValues(files_submenu,
+ XtNx, pos_x,
+ XtNy, pos_y,
+ NULL);
+ /* use XtPopupSpringLoaded() instead of XtPopup() since it does a few things
+ that make the pullright behave like a proper menu, like highlighting the
+ current selection, setting the cursor shape etc. */
+ XtPopupSpringLoaded(files_submenu);
+ m_active_submenu = files_submenu;
+}
+
+/*
+ * This event handler (to be called by read_events(), the main event handling loop)
+ * creates a timeout for the pullright to pop up.
+*/
+void
+SubMenuHandleEvent(XtAppContext app, XEvent *event)
+{
+ static int flag = 0;
+ static struct pullright_position_info info = { -1, 0, 0, 0, NULL };
+
+ UNUSED(app);
+
+ if (m_submenu == NULL)
+ return;
+
+ if (event->type == EnterNotify
+ || event->type == MotionNotify
+ || event->type == LeaveNotify
+ || event->type == ButtonPress) {
+
+/* fprintf(stderr, "SubMenuHandleEvent: 0x%lx, 0x%lx\n", event->xany.window, XtWindow(m_submenu)); */
+
+ /* Could also loop through a list of windows here ...
+ We need to check for the parent of the menu item, since smeBSBObject is not
+ a real window, and then manually check whether the pointer is inside the menu
+ item.
+ */
+ if (XtParent(m_submenu) != NULL &&
+ event->xany.window == XtWindow(XtParent(m_submenu))) {
+ /* don't need to check for x coordinates since we already
+ know that pointer is inside the parent */
+ if (info.y == -1) { /* initialize info */
+ XtVaGetValues(m_submenu,
+ XtNy, &(info.y),
+ XtNwidth, &(info.w),
+ XtNheight, &(info.h),
+ NULL);
+ XtVaGetValues(XtParent(m_submenu),
+ XtNborderWidth, &(info.border_width),
+ NULL);
+
+ info.menu = m_submenu;
+ }
+ if (info.y < event->xbutton.y && info.y + info.h > event->xbutton.y) {
+ if (flag == 0) {
+ /* Create a timeout of 200ms to pop up the menu, so that it doesn't
+ pop up always when the cursor is only moved over the pulldown menu.
+ I think this is about the same delay as the one used by Motif.
+ */
+ flag = 1;
+ TRACE_GUI((stderr, "ENTER: %d, %d, %d; %d, %d",
+ info.y, info.w, info.h, event->xbutton.x, event->xbutton.y));
+ m_timeout = XtAppAddTimeOut(app, 200, popup_pullright, &info);
+ return;
+ }
+ }
+ else if (flag == 1) {
+ flag = 0;
+ TRACE_GUI((stderr, "LEAVE!"));
+ if (m_timeout != 0)
+ XtRemoveTimeOut(m_timeout);
+ m_timeout = 0;
+ if (m_active_submenu != NULL)
+ XtPopdown(m_active_submenu);
+ m_active_submenu = NULL;
+ }
+ }
+ }
+}
+
+static Widget
+create_pulldown_entry(const char *menu_name,
+ Widget parent,
+ const char *item_name,
+ const char *accelerator, /* accelerator, or NULL */
+ struct xdvi_action *action,
+ buttonTypeT *type)
+{
+ Widget w;
+ char buf[1024];
+ char *m_name = xstrdup(menu_name);
+ m_name = xstrcat(m_name, item_name);
+
+#ifdef SHOW_ACCELERATORS
+ if (accelerator != NULL && *accelerator != '\0')
+ SNPRINTF(buf, 1024, "%s [%s]", item_name, accelerator);
+ else
+ strncpy(buf, item_name, 1024);
+#else
+ UNUSED(accelerator);
+ strncpy(buf, item_name, 1024);
+#endif
+
+/* fprintf(stderr, "creating pulldown for parent %p: `%s', `%s'\n", */
+/* (void *)parent, menu_name, item_name); */
+
+ if (strcmp(item_name, "SEP") == 0) { /* it's a separator */
+ *type = MENU_SEPARATOR;
+ w = XtCreateManagedWidget(m_name, smeLineObjectClass, parent, NULL, 0);
+ }
+ else if (action->proc != NULL && action->proc == Act_recent_files) { /* special case: submenu with recent files */
+/* w = recent_files_submenu(m_name, parent, buf); */
+/* *type = MENU_ENTRY; */
+ w = XtVaCreateManagedWidget(m_name, smeBSBObjectClass, parent,
+ XtNlabel, buf,
+ XtNleftMargin, 20,
+ XtNrightMargin, 16,
+ XtNrightBitmap, menu_arrow_bitmap,
+ NULL);
+ m_submenu = w;
+ /* fprintf(stderr, "setting translations for %p\n", (void *)XtParent(parent)); */
+ XtOverrideTranslations(parent, menu_accels);
+ /* XtOverrideTranslations(XtParent(parent), menu_accels); */
+
+ *type = MENU_ENTRY;
+ }
+ else { /* normal menu item */
+ w = XtVaCreateManagedWidget(m_name, smeBSBObjectClass, parent,
+ XtNlabel, buf,
+ XtNleftMargin, 20,
+ NULL);
+ *type = MENU_ENTRY;
+ XtAddCallback(w, XtNcallback, handle_command, action);
+ }
+ free(m_name);
+ return w;
+}
+
+static Widget
+create_pulldown_menu(const char *menu_name,
+ Dimension *width,
+ int *index,
+ Dimension *y_pos,
+ buttonTypeT *type,
+ int *menu_number)
+{
+ int i;
+
+ /* check whether a pulldown menu with this name already exists,
+ and if yes, return its position in index: */
+ for (i = 0; i < *menu_number; i++) {
+ if (menu_list[i].name != NULL && (strcmp(menu_list[i].name, menu_name)) == 0) {
+ *index = i;
+ break;
+ }
+ }
+ if (i == *menu_number) { /* doesn't exist, create one */
+ Dimension w, h;
+ Widget n_button_widget, n_popup_widget;
+ char *button_widget_name = NULL;
+
+ (*menu_number)++;
+ if (*menu_number > MAX_MENU_NUM) {
+ XDVI_WARNING((stderr, "Too many menus (max=%d), skipping all from \"%s\"",
+ MAX_MENU_NUM, menu_name));
+ *type = INVALID;
+ return 0;
+ }
+
+ /* save menu_name to list for later comparison */
+ menu_list[i].name = xrealloc(menu_list[i].name, strlen(menu_name) + 1);
+ strcpy(menu_list[i].name, menu_name);
+
+ button_widget_name = xstrdup(menu_name);
+ button_widget_name = xstrcat(button_widget_name, "B"); /* make it unique */
+
+ if (globals.debug & DBG_ALL) {
+ fprintf(stderr, "ypos: %d; h: %d; between: %d; border: %d\n",
+ *y_pos,
+ h,
+ resource.btn_between_spacing,
+ resource.btn_border_width);
+ }
+
+ n_button_widget = XtVaCreateWidget(menu_list[i].name, menuButtonWidgetClass, panel_widget,
+ XtNmenuName, button_widget_name,
+ XtNx, resource.btn_side_spacing,
+ XtNy, *y_pos,
+ XtNborderWidth, resource.btn_border_width,
+ NULL);
+ n_popup_widget = XtVaCreatePopupShell(button_widget_name, simpleMenuWidgetClass, n_button_widget,
+ NULL);
+ /* Mustn't free this one?? */
+/* free(button_widget_name); */
+ menu_list[i].button_widget = n_button_widget;
+ menu_list[i].popup_widget = n_popup_widget;
+ XtVaGetValues(n_button_widget, XtNwidth, &w, XtNheight, &h, NULL);
+ *width = w;
+ *index = i;
+ *y_pos += h + resource.btn_between_spacing + 2 * resource.btn_border_width;
+ *type = MENU_BUTTON;
+ return n_button_widget;
+ }
+ *type = NONE;
+ return 0;
+}
+
+static struct button_info *
+create_button_info(const char *label, struct xdvi_action *action, Widget w, buttonTypeT type)
+{
+ struct button_info *info = xmalloc(sizeof *info);
+ info->label = xstrdup(label);
+ info->action = action;
+ info->widget = w;
+ info->type = type;
+ return info;
+}
+
+typedef enum shrinkArgT_ { NO_SHRINK_ARG, HASH, PERCENT, UNDERSCORE } shrinkArgT;
+
+static shrinkArgT
+test_for_shrink_arg(const char *item, int *idx)
+{
+ const char *ptr = item;
+ size_t i;
+ for (i = 0; ptr[i] != '\0'; i++) {
+ if (ptr[i] == '$') {
+ i++;
+ if (ptr[i] == '#') {
+ *idx = i;
+ return HASH;
+ }
+ else if (ptr[i] == '%') {
+ *idx = i;
+ return PERCENT;
+ }
+ else if (ptr[i] == '_') {
+ *idx = i;
+ return UNDERSCORE;
+ }
+ }
+ }
+ *idx = 0;
+ return NO_SHRINK_ARG;
+}
+
+static Boolean
+create_shrink_button(char **label, int offset, shrinkArgT type, struct xdvi_action *action)
+{
+ int shrink_arg = 0;
+#define TEMPSTR_LEN 128 /* enough for printing a number into */
+ char tempstr[TEMPSTR_LEN];
+ char *new_label = NULL;
+
+ for (;; action = action->next) {
+ if (action == NULL) {
+ return False;
+ }
+ if (action->proc == Act_set_shrink_factor || action->proc == Act_shrink_to_dpi) {
+ /* NOTE: the shrinkbutton[] resource isn't implemented. It probably makes
+ less sense with the pulldown menu resources??
+ */
+ if (action->num_params > 0) {
+ shrink_arg = atoi(action->param);
+ if (action->proc == Act_shrink_to_dpi)
+ shrink_arg = (double)resource.pixels_per_inch / shrink_arg + 0.5;
+ if (shrink_arg < 1)
+ shrink_arg = 1;
+ else if (shrink_arg > 99)
+ shrink_arg = 99;
+ }
+ break; /* found shrink action */
+ }
+ }
+
+ if (type == HASH)
+ SNPRINTF(tempstr, TEMPSTR_LEN, "%d", shrink_arg);
+ else if (type == PERCENT) {
+ if (shrink_arg <= 15)
+ SNPRINTF(tempstr, TEMPSTR_LEN, "%d", (int)(100.0 / shrink_arg + .5));
+ else
+ SNPRINTF(tempstr, TEMPSTR_LEN, "%.2f", 100.0 / shrink_arg);
+ }
+ /* NOTE: I think UNDERSCORE is related to the shrinkbutton[] resource,
+ which is not implemented */
+
+ /* return resized label */
+ new_label = xmalloc(offset - 1 + strlen(tempstr) + strlen(*label + offset + 1) + 1);
+ memcpy(new_label, *label, offset - 1);
+ strcpy(new_label + offset - 1, tempstr); /* now it's null-terminated */
+ strcat(new_label, *label + offset + 1);
+ free(*label);
+ *label = new_label;
+
+#undef TEMPSTR_LEN
+ return True;
+}
+
+static Dimension
+create_button(int button_number, /* number of this button */
+ int *menu_num, /* number of submenus in this button */
+ char **items, /* description of label and action strings */
+ size_t item_count, /* number of items in description */
+ Widget parent, /* parent of widget to create */
+ struct button_info ***bipp, /* button info to insert new button into */
+ Dimension *y_pos, /* vertical position after creating button */
+ const char *c_ptr, /* entire rest of resource string, for error messages */
+ size_t len) /* length of current line in resource string, for error messages*/
+{
+ int menu_idx = -1, label_idx = -1, accelerator_idx = -1, action_idx = -1;
+#define NAME_LEN 16
+ char name[NAME_LEN];
+ struct button_info *bp;
+ shrinkArgT shrink_arg_type;
+ struct xdvi_action *action;
+ Widget widget;
+ buttonTypeT b_type;
+/* static int menu_num = 0; /\* count number of created menus *\/ */
+ Dimension width = 0;
+
+ ASSERT(item_count >= 2, "Too few items");
+
+ if (item_count == 4) { /* submenu for a button */
+ menu_idx = 0;
+ label_idx = 1;
+ accelerator_idx = 2;
+ action_idx = 3;
+ }
+ else if (item_count == 3) { /* command button */
+ label_idx = 0;
+ accelerator_idx = 1;
+ action_idx = 2;
+ }
+ else { /* separator */
+ if (strcmp(items[1], "SEP") == 0) { /* separator */
+ menu_idx = 0;
+ label_idx = 1;
+ }
+ else {
+ XDVI_WARNING((stderr, "Wrong number of items (%d) in translations line:\n\"%.*s\" (skipping this line).",
+ item_count, (int)len, c_ptr));
+ return 0;
+ }
+ }
+
+ if (action_idx != -1) {
+ int offset;
+ shrink_arg_type = test_for_shrink_arg(items[label_idx], &offset);
+
+/* fprintf(stderr, "compiling action: |%s|\n", items[action_idx]); */
+ if ((action = compile_action(items[action_idx])) == NULL) {
+ XDVI_WARNING((stderr, "Invalid action \"%s\" in translations line:\n\"%.*s\" (skipping this line).",
+ items[action_idx], (int)len, c_ptr));
+ return 0;
+ }
+
+ if (shrink_arg_type != NO_SHRINK_ARG) { /* search for corresponding shrink action */
+ if (!create_shrink_button(&(items[label_idx]), offset, shrink_arg_type, action)) {
+ XDVI_WARNING((stderr, "Non-existent shrink action \"%s\" in translations line:\n\"%.*s\"",
+ items[action_idx], (int)len, c_ptr));
+ return 0;
+ }
+ }
+ }
+ else {
+ action = NULL;
+ }
+
+ command_call[0].closure = (XtPointer) action;
+ SNPRINTF(name, NAME_LEN, "button%d", button_number);
+
+ if (menu_idx != -1) { /* it's a pulldown menu */
+ int index;
+
+ /* create a new pulldown menu if it doesn't exist yet */
+ widget = create_pulldown_menu(items[menu_idx], &width, &index, y_pos, &b_type, menu_num);
+ if (b_type == INVALID)
+ return 0;
+ if (b_type != NONE) { /* it didn't exist yet */
+ bp = create_button_info(items[label_idx], NULL, widget, b_type);
+ **bipp = bp;
+ *bipp = &bp->next;
+ }
+
+ /* create an entry for this item */
+ widget = create_pulldown_entry(menu_list[index].name,
+ menu_list[index].popup_widget,
+ items[label_idx],
+ accelerator_idx > 0 ? items[accelerator_idx] : NULL,
+ action,
+ &b_type);
+ bp = create_button_info(items[label_idx], action, widget, b_type);
+ **bipp = bp;
+ *bipp = &bp->next;
+ }
+ else { /* not a pulldown menu, but a simple command button */
+ command_call[0].closure = (XtPointer) action;
+ widget = XtVaCreateWidget(name, commandWidgetClass, parent,
+ XtNlabel, (XtArgVal)items[label_idx],
+ XtNx, resource.btn_side_spacing,
+ XtNy, (XtArgVal)*y_pos,
+ XtNborderWidth, resource.btn_border_width,
+ XtNcallback, (XtArgVal)command_call,
+ NULL);
+ bp = create_button_info(items[label_idx], action, widget, COMMAND_BUTTON);
+ **bipp = bp;
+ *bipp = &bp->next;
+ }
+#undef NAME_LEN
+ return width;
+}
+
+void
+scroll_x_panner(int x)
+{
+ static int old_x = 0;
+ if (panner != 0 && ABS(x - old_x) > 8) {
+ XtVaSetValues(panner, XtNsliderX, x, NULL);
+ old_x = x;
+ }
+}
+
+void
+scroll_y_panner(int y)
+{
+ static int old_y = 0;
+ if (panner != 0 && ABS(y - old_y) > 8) {
+ XtVaSetValues(panner, XtNsliderY, y, NULL);
+ old_y = y;
+ }
+}
+
+#ifdef USE_PANNER
+static void
+panner_cb(Widget widget, XtPointer closure, XtPointer report_ptr)
+{
+ XawPannerReport *report = (XawPannerReport *)report_ptr;
+ static int orig_x = 0, orig_y = 0;
+ int x = report->slider_x;
+ int y = report->slider_y;
+ static Dimension w, h;
+ static Arg arg_wh_clip[] = {
+ {XtNwidth, (XtArgVal) &w},
+ {XtNheight, (XtArgVal) &h},
+ };
+
+ UNUSED(closure);
+
+ XtGetValues(globals.widgets.clip_widget, arg_wh_clip, XtNumber(arg_wh_clip));
+
+ fprintf(stderr, "w: %d, h: %d, globals.page.w: %d, globals.page.h: %d\n",
+ w, h, globals.page.w, globals.page.h);
+ XtVaSetValues(widget,
+ XtNsliderWidth, w, XtNsliderHeight, h,
+ XtNcanvasWidth, globals.page.w, XtNcanvasHeight, globals.page.h,
+ NULL);
+
+ fprintf(stderr, "panner moved: %d, %d\n", report->slider_x, report->slider_y);
+ if (globals.widgets.x_bar != NULL)
+ XtCallCallbacks(globals.widgets.x_bar, XtNscrollProc, (XtPointer)(x - orig_x));
+ if (globals.widgets.y_bar != NULL)
+ XtCallCallbacks(globals.widgets.y_bar, XtNscrollProc, (XtPointer)(y - orig_y));
+ orig_x = x;
+ orig_y = y;
+}
+#endif /* USE_PANNER */
+
+void
+create_menu_buttons(Widget form, int *ret_panel_width)
+{
+ Dimension max_button_width = 0, curr_width;
+ Dimension y_pos;
+ struct button_info **bipp;
+ struct button_info *bp;
+ const char *c_ptr, *e_ptr;
+ int max_size;
+ int button_number = 0;
+ int menu_number = 0; /* number of menus created; passed through to create_pulldown_menu */
+
+ /* disable the magnifier in the panel: */
+ XtTranslations panel_translations = XtParseTranslationTable("#augment <ButtonPress>:");
+
+ XtAppAddActions(XtWidgetToApplicationContext(form), menu_actions, XtNumber(menu_actions));
+ /* add our own popdown-submenus() action to the default translations of this menu */
+ menu_accels = XtParseAcceleratorTable("<BtnUp>:MenuPopdown()notify()unhighlight()popdown-submenus()");
+
+ line_widget = XtVaCreateWidget("line", widgetClass, form,
+ XtNbackground, (XtArgVal)resource.fore_Pixel,
+ XtNwidth, (XtArgVal) 1,
+ XtNfromHoriz, (XtArgVal)globals.widgets.vport_widget,
+ XtNborderWidth, (XtArgVal)0,
+ XtNtop, (XtArgVal)XtChainTop,
+ XtNbottom, (XtArgVal)XtChainBottom,
+ XtNleft, (XtArgVal)XtChainRight,
+ XtNright, (XtArgVal)XtChainRight,
+ NULL);
+ panel_widget = XtVaCreateWidget("panel", compositeWidgetClass, form,
+ XtNborderWidth, (XtArgVal)0,
+ XtNfromHoriz, (XtArgVal)line_widget,
+ XtNtranslations, (XtArgVal)panel_translations,
+ XtNtop, (XtArgVal)XtChainTop,
+ XtNbottom, (XtArgVal)XtChainBottom,
+ XtNleft, (XtArgVal)XtChainRight,
+ XtNright, (XtArgVal)XtChainRight,
+ NULL);
+ menu_arrow_bitmap
+ = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level),
+ RootWindowOfScreen(XtScreen(globals.widgets.top_level)),
+ (char *)menu_arrow_bits, MENU_ARROW_W, MENU_ARROW_H);
+
+ b_head = NULL;
+ bipp = &b_head;
+
+ *ret_panel_width = 0;
+ y_pos = resource.btn_top_spacing;
+
+#define FREE_LINE_ITEMS do { \
+ for (curr = 0; curr < item_count; curr++) { \
+ free(line_items[curr]); \
+ } \
+ free(line_items); \
+ } while (0)
+
+ for (c_ptr = resource.menu_translations;
+ c_ptr != NULL && *c_ptr != '\0';
+ c_ptr = e_ptr + 1) {
+ e_ptr = strchr(c_ptr, '\n');
+ if (e_ptr != NULL) {
+ char **line_items = NULL;
+ size_t len, curr, item_count = 0;
+
+ if (e_ptr == c_ptr) { /* single '\n' marks additional space between buttons */
+ y_pos += resource.btn_between_extra;
+ continue;
+ }
+ len = e_ptr - c_ptr;
+
+ if (++button_number > MAX_BUTTON_NUM) {
+ XDVI_WARNING((stderr, "Too many buttons (max=%d), skipping all from:\n\"%.*s\"",
+ MAX_BUTTON_NUM, (int)len, c_ptr));
+ break;
+ }
+
+ line_items = split_line(c_ptr, SEP_CHAR, 0, len, &item_count);
+ if (item_count < 3 && !(item_count > 1 && strcmp(line_items[1], "SEP") == 0)) {
+ XDVI_WARNING((stderr, "Too few separators \"%c\" in translations line:\n\"%.*s\" (skipping this line).\n",
+ SEP_CHAR, (int)len, c_ptr));
+ FREE_LINE_ITEMS;
+ continue;
+ }
+ curr_width = create_button(button_number,
+ &menu_number,
+ line_items,
+ item_count,
+ panel_widget,
+ &bipp,
+ &y_pos,
+ c_ptr, len);
+ if (curr_width == 0) { /* no button created */
+ FREE_LINE_ITEMS;
+ continue;
+ }
+ /* adjust max_button_width to this new entry */
+ if (curr_width > max_button_width)
+ max_button_width = curr_width;
+
+ FREE_LINE_ITEMS;
+ }
+ }
+
+#undef FREE_LINE_ITEMS
+
+ /* null-terminate button info */
+ *bipp = NULL;
+
+ max_size = xaw_get_pagelist_size();
+ if (max_size > max_button_width) {
+ max_button_width = max_size;
+ }
+
+ *ret_panel_width = max_button_width + 2 * (resource.btn_side_spacing + resource.btn_border_width);
+ TRACE_GUI((stderr, "panel_widget: w: %d", *ret_panel_width));
+ XtVaSetValues(panel_widget, XtNwidth, (XtArgVal)*ret_panel_width, NULL);
+ ++(*ret_panel_width);
+ my_panel_width = *ret_panel_width; /* make it available */
+
+ for (bp = b_head; bp != NULL; bp = bp->next) {
+ if (bp->type == MENU_BUTTON || bp->type == COMMAND_BUTTON) {
+ TRACE_GUI((stderr, "bp->widget: w: %d", max_button_width));
+ XtVaSetValues(bp->widget, XtNwidth, (XtArgVal)max_button_width, NULL);
+ XtManageChild(bp->widget);
+ }
+ }
+
+ my_y_pos = y_pos - resource.btn_between_spacing + resource.btn_top_spacing + 2 * resource.btn_border_width;
+ initialize_tick_marks();
+#ifdef USE_PANNER
+ {
+ static Dimension w, h;
+ static Arg arg_wh_clip[] = {
+ {XtNwidth, (XtArgVal) &w},
+ {XtNheight, (XtArgVal) &h},
+ };
+ XtGetValues(globals.widgets.clip_widget, arg_wh_clip, XtNumber(arg_wh_clip));
+
+ fprintf(stderr, "w: %d, h: %d, globals.page.w: %d, globals.page.h: %d\n",
+ w, h, globals.page.w, globals.page.h);
+ if (w == 0)
+ w = globals.page.w - 2;
+ if (h == 0)
+ h = globals.page.h - 2;
+ panner = XtVaCreateManagedWidget("panner", pannerWidgetClass, panel_widget,
+ XtNx, resource.btn_side_spacing,
+ XtNy, my_y_pos,
+ XtNheight, 60,
+ XtNwidth, max_button_width,
+ XtNshadowThickness, 0,
+ XtNsliderWidth, w,
+ XtNsliderHeight, h,
+ XtNcanvasWidth, globals.page.w,
+ XtNcanvasHeight, globals.page.h,
+ XtNsliderX, 5,
+ XtNsliderY, 7,
+ XtNinternalSpace, 0,
+ NULL);
+ }
+ my_y_pos += 60 + resource.btn_top_spacing + 2 * resource.btn_border_width;
+ XtAddCallback(panner, XtNreportCallback, panner_cb, (XtPointer)NULL);
+
+#endif /* USE_PANNER */
+
+}
+#endif /* NEW_MENU_CREATION */
+
+
+void
+set_button_panel_height(XtArgVal h)
+{
+ TRACE_GUI((stderr, "line_widget: h %d", (int)h));
+ XtVaSetValues(line_widget, XtNheight, h, NULL);
+ XtManageChild(line_widget);
+
+ XtVaSetValues(panel_widget, XtNheight, h, NULL);
+ XtManageChild(panel_widget);
+}
+
+/****************************************************************************
+ * Action handling code.
+ */
+
+
+static void
+handle_destroy_buttons(Widget widget, XtPointer client_data, XtPointer call_data)
+{
+ int panel_width;
+ Dimension window_w, window_h;
+
+ UNUSED(widget);
+ UNUSED(client_data);
+ UNUSED(call_data);
+
+ if (--destroy_count != 0) {
+ return;
+ }
+ XtVaSetValues(globals.widgets.vport_widget, XtNresizable, (XtArgVal)True, NULL);
+ XtVaGetValues(globals.widgets.form_widget,
+ XtNwidth, &window_w,
+ XtNheight, &window_h,
+ NULL);
+
+ if ((resource.expert_mode & XPRT_SHOW_BUTTONS) == 0) {
+ /* destroy buttons */
+ TRACE_GUI((stderr, "globals.widgets.vport_widget: h %d, w %d", window_w, window_h));
+ XtVaSetValues(globals.widgets.vport_widget, XtNwidth, window_w, XtNheight, window_h, NULL);
+ }
+ else {
+ create_menu_buttons(globals.widgets.form_widget, &panel_width);
+ window_w -= panel_width;
+ TRACE_GUI((stderr, "globals.widgets.vport_widget: h %d, w %d", window_h, window_w));
+ XtVaSetValues(globals.widgets.vport_widget, XtNwidth, window_w, XtNheight, window_h, NULL);
+ set_button_panel_height((XtArgVal) window_h);
+ }
+}
+
+
+static void
+reconfig_window(void) {
+ Dimension x_top, y_top, h_top, w_top;
+ XWindowChanges sizeconfigure;
+ int sizeconfiguremask;
+
+ /* brute-force method to bring the scrollbars back. Apparently a single XConfigureWindow()
+ isn't enough to get the scrollbars back, we actually need to move the window a bit,
+ and then move it back. */
+ sizeconfiguremask = CWWidth | CWHeight;
+ XtVaGetValues(globals.widgets.top_level, XtNx, &x_top, XtNy, &y_top, XtNheight, &h_top, XtNwidth, &w_top, NULL);
+ sizeconfigure.width = w_top + 1;
+ sizeconfigure.height = h_top + 1;
+ XConfigureWindow(DISP, XtWindow(globals.widgets.top_level), sizeconfiguremask, &sizeconfigure);
+ sizeconfigure.width = w_top;
+ sizeconfigure.height = h_top;
+ XConfigureWindow(DISP, XtWindow(globals.widgets.top_level), sizeconfiguremask, &sizeconfigure);
+}
+
+/* toggle scrollbars to state `visible' */
+void
+toggle_scrollbars(void)
+{
+ Widget v_bar = XtNameToWidget(globals.widgets.vport_widget, "vertical");
+ Widget h_bar = XtNameToWidget(globals.widgets.vport_widget, "horizontal");
+ static Dimension bar_thick;
+ static Boolean v_bar_mapped = False, h_bar_mapped = False;
+ static Boolean initialized = False;
+
+ Boolean make_v_bar_visible = False;
+ Boolean make_v_bar_invisible = False;
+
+ Boolean make_h_bar_visible = False;
+ Boolean make_h_bar_invisible = False;
+
+ if (v_bar != 0) {
+ int test_v = 0;
+ XtVaGetValues(v_bar, XtNwidth, &test_v, NULL);
+ if (test_v > 1)
+ v_bar_mapped = True;
+ }
+ if (h_bar != 0) {
+ int test_h = 0;
+ XtVaGetValues(h_bar, XtNheight, &test_h, NULL);
+ if (test_h > 1)
+ h_bar_mapped = True;
+ }
+
+ if (!initialized) {
+ v_bar_mapped = h_bar_mapped = (resource.expert_mode & XPRT_SHOW_SCROLLBARS) != 0;
+ initialized = True;
+ if (v_bar != 0)
+ XtVaGetValues(v_bar, XtNwidth, &bar_thick, NULL);
+ else if (h_bar != 0)
+ XtVaGetValues(h_bar, XtNheight, &bar_thick, NULL);
+ else
+ bar_thick = 15; /* FIXME */
+ }
+
+ if ((resource.expert_mode & XPRT_SHOW_SCROLLBARS) == 0) {
+ if (v_bar_mapped)
+ make_v_bar_invisible = True;
+ if (h_bar_mapped)
+ make_h_bar_invisible = True;
+ }
+ else {
+ if (!v_bar_mapped)
+ make_v_bar_visible = True;
+ if (!h_bar_mapped)
+ make_h_bar_visible = True;
+ }
+
+ if (make_h_bar_visible || make_v_bar_visible) {
+ if (make_h_bar_visible && h_bar != 0) {
+ TRACE_GUI((stderr, "h_bar: h %d", bar_thick));
+ XtVaSetValues(h_bar, XtNheight, bar_thick, XtNx, bar_thick, XtNy, 0, XtNborderWidth, 1, NULL);
+ XtManageChild(h_bar);
+ h_bar_mapped = True;
+ }
+ if (make_v_bar_visible && v_bar != 0) {
+ TRACE_GUI((stderr, "v_bar: w %d", bar_thick));
+ XtVaSetValues(v_bar, XtNwidth, bar_thick, XtNx, 0, XtNy, bar_thick, XtNborderWidth, 1, NULL);
+ XtManageChild(v_bar);
+ v_bar_mapped = True;
+ }
+ if (h_bar != 0 || v_bar != 0) { /* need to reconfigure screen */
+ reconfig_window();
+ }
+ }
+ else if (make_h_bar_invisible || make_v_bar_invisible) {
+ if (make_h_bar_invisible && h_bar != 0) {
+ XtUnmanageChild(h_bar);
+ XtVaSetValues(h_bar, XtNheight, 1, XtNx, 0, XtNy, 0, XtNborderWidth, 0, NULL);
+ h_bar_mapped = False;
+ }
+ if (make_v_bar_invisible && v_bar != 0) {
+ XtUnmanageChild(v_bar);
+ XtVaSetValues(v_bar, XtNwidth, 1, XtNy, 0, XtNy, 0, XtNborderWidth, 0, NULL);
+ v_bar_mapped = False;
+ }
+ if (h_bar != 0 || v_bar != 0) { /* need to reconfigure screen */
+ reconfig_window();
+ }
+ }
+
+}
+
+void
+toggle_buttons(void)
+{
+ static Boolean buttons_active = False;
+ static Boolean initialized = False;
+ Dimension window_w, window_h;
+
+
+ Boolean make_buttons_visible = False;
+ Boolean make_buttons_invisible = False;
+
+ int panel_width;
+
+ if (!initialized) {
+ buttons_active = (resource.expert_mode & XPRT_SHOW_BUTTONS) != 0;
+ initialized = True;
+ }
+
+ if ((resource.expert_mode & XPRT_SHOW_BUTTONS) == 0) {
+ if (buttons_active)
+ make_buttons_invisible = True;
+ }
+ else {
+ if (!buttons_active)
+ make_buttons_visible = True;
+ }
+
+ if (make_buttons_visible) {
+ if (destroy_count != 0) {
+ return;
+ }
+
+ create_menu_buttons(globals.widgets.form_widget, &panel_width);
+ XtVaGetValues(globals.widgets.form_widget,
+ XtNwidth, &window_w,
+ XtNheight, &window_h,
+ NULL);
+ XtVaSetValues(globals.widgets.vport_widget, XtNresizable, (XtArgVal)True, NULL);
+ window_w -= panel_width;
+ TRACE_GUI((stderr, "globals.widgets.vport_widget: w: %d, h: %d", window_w, window_h));
+ XtVaSetValues(globals.widgets.vport_widget, XtNwidth, window_w, XtNheight, window_h, NULL);
+ set_button_panel_height((XtArgVal) window_h);
+ buttons_active = True;
+ }
+ else if (make_buttons_invisible) {
+ if (destroy_count != 0) {
+ return;
+ }
+ /* this counts the callback calls; 1 for the panel, 1 for the line */
+ destroy_count = 2;
+
+ XtAddCallback(panel_widget, XtNdestroyCallback,
+ handle_destroy_buttons, (XtPointer)0);
+ XtAddCallback(panel_widget, XtNdestroyCallback,
+ handle_destroy_pagelist, (XtPointer)0);
+ XtAddCallback(line_widget, XtNdestroyCallback,
+ handle_destroy_buttons, (XtPointer)0);
+ XtDestroyWidget(panel_widget);
+ XtDestroyWidget(line_widget);
+ buttons_active = False;
+/* window_w += get_panel_width(); */
+
+ while (b_head != NULL) {
+ struct button_info *bp = b_head;
+ struct xdvi_action *action;
+
+ b_head = bp->next;
+ free(bp->label);
+ /* free bp->action */
+ for (action = bp->action; action != NULL;) {
+ struct xdvi_action *act2 = action;
+ action = act2->next;
+ if (act2->num_params > 0) {
+ free(act2->param);
+ }
+ free(act2);
+ }
+ free(bp);
+ }
+ }
+}
+
+#else
+/* silence `empty compilation unit' warnings */
+static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
+#endif /* ifndef MOTIF */