diff options
Diffstat (limited to 'Build/source/texk/xdvik/gui/xm_prefs.c')
-rw-r--r-- | Build/source/texk/xdvik/gui/xm_prefs.c | 590 |
1 files changed, 590 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/gui/xm_prefs.c b/Build/source/texk/xdvik/gui/xm_prefs.c new file mode 100644 index 00000000000..388ef07ac12 --- /dev/null +++ b/Build/source/texk/xdvik/gui/xm_prefs.c @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2004 Stefan Ulrich + * + * 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. + * + */ + +/* + * Preferences dialog for xdvik. + */ + +#include "xdvi-config.h" +#include "xdvi.h" + +#include "x_util.h" +#include "xm_colorsel.h" +#include "topic-window.h" +#include "message-window.h" +#include "util.h" +#include "events.h" + +#include "xm_prefsP.h" +#include "xm_prefs.h" + +#include "xm_prefs_appearance.h" +#include "xm_prefs_fonts.h" +#include "xm_prefs_helpers.h" +#include "xm_prefs_page.h" +#include "xm_prefs_scroll.h" + +/* for reverting preferences, we need access to more prototypes ... */ +#include "dvi-draw.h" +#include "search-internal.h" +#include "statusline.h" +#include "xm_toolbar.h" +#include "xm_menu.h" +#include "pagesel.h" + +#ifdef MOTIF /* entire file */ + +#include <X11/Xatom.h> + +#include <Xm/Xm.h> +#include <Xm/Protocols.h> +#include <Xm/DialogS.h> +#include <Xm/Form.h> + +#define SCROLLING_DONE 0 + +#define NUM_PREFS_TOPICS 16 /* should be ample ... */ + +/* hmm, should maybe move these into xm_prefsP.c ... */ +void +h_attach_below(Widget x, Widget y) { + if (y == NULL) { + /* no top widget, attach to form - could just pass NULL as XmNtopWidget, but lesstif warns in that case ... */ + XtVaSetValues(x, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + } + else { + XtVaSetValues(x, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, y, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + } +} + + +static void +initialize_items(struct topic_info *info) +{ + int i = 0; + + info->items[i].widget = prefs_appearance(info); + info->items[i].topic = xstrdup("Appearance"); + info->items[i].title = xstrdup("Change the appearance of xdvi"); + + i++; + info->items[i].widget = prefs_fonts_and_colors(info); + info->items[i].topic = xstrdup("Fonts and Colors"); + info->items[i].title = xstrdup("Display of fonts and colors in DVI files"); + + i++; + info->items[i].widget = prefs_paper(info); + info->items[i].topic = xstrdup("Page Size"); + info->items[i].title = xstrdup("Customize the default window and page size"); + +#if SCROLLING_DONE /* not finished yet */ + i++; + info->items[i].widget = prefs_scrolling(info); + info->items[i].topic = xstrdup("Scrolling"); + info->items[i].title = xstrdup("Customize the scrolling behaviour when switching pages"); +#endif + + i++; + info->items[i].widget = prefs_helpers(info); +#ifdef LESSTIF_VERSION + /* compensate for width computation bug by adding extra whitespace at end */ + info->items[i].topic = xstrdup("Helper Applications "); +#else + info->items[i].topic = xstrdup("Helper Applications"); +#endif + info->items[i].title = xstrdup("External programs used by xdvi"); + + /* terminate */ + i++; + info->items[i].widget = 0; + info->items[i].topic = info->items[i].title = NULL; + + ASSERT(i < NUM_PREFS_TOPICS, "NUM_PREFS_TOPICS too small!"); +} + +void +remove_from_deplist(struct prefs_choice *prefs, Widget w) +{ + size_t i; + Boolean found = False; + + /* locate this widget */ + for (i = 0; i < prefs->depwin_cnt; i++) { + if (prefs->depwin[i] == w) { + found = True; + break; + } + } + + if (found) { + /* move later widgets down */ + for (; i < prefs->depwin_cnt - 1; i++) { + prefs->depwin[i] = prefs->depwin[i + 1]; + } + prefs->depwin_cnt--; + } + +#if 0 + fprintf(stderr, "deplist after removal:\n"); + for (i = 0; i < prefs->depwin_cnt; i++) { + fprintf(stderr, "%d: %p\n", i, prefs->depwin[i]); + } +#endif +} + +static void +update_button(Widget button, Pixel pix) +{ + struct color_button_info *cinfo; + static XmDrawnButtonCallbackStruct cbs; + + XtVaGetValues(button, XmNuserData, &cinfo, NULL); + cinfo->pixel = pix; + cbs.reason = XmCR_EXPOSE; + XtCallCallbacks(button, XmNexposeCallback, &cbs); +} + +static void +update_button_by_name(Pixel pix, const char *name) +{ + static Widget pref_shell = 0; + Widget button; + + if (pref_shell == 0 + && !get_widget_by_name(&pref_shell, globals.widgets.top_level, Xdvi_PREFS_DIALOG_NAME, True)) + return; + + if (get_widget_by_name(&button, pref_shell, name, True)) { + update_button(button, pix); + } +} + +static Boolean +revert_colors(Pixel fg, Pixel bg, Pixel hl) +{ + XColor color_data[2]; + Boolean need_redraw = False; + Widget button; + Pixel visited, unvisited; + + color_data[0].pixel = resource.fore_Pixel; + color_data[1].pixel = resource.back_Pixel; + + str_to_pixel(globals.widgets.top_level, resource.visited_link_color, &visited); + str_to_pixel(globals.widgets.top_level, resource.link_color, &unvisited); + + XQueryColors(DISP, G_colormap, color_data, 2); + + if (fg != resource.fore_Pixel) { + XGCValues values; + + fg_initial.r = color_data[0].red; + fg_initial.g = color_data[0].green; + fg_initial.b = color_data[0].blue; + + values.foreground = resource.rule_pixel = resource.fore_Pixel; + XChangeGC(DISP, globals.gc.ruler, GCForeground, &values); + + scanned_page = scanned_page_color = scanned_page_reset; + + update_button_by_name(resource.fore_Pixel, Xdvi_FG_COLOR_BTN); + + need_redraw = True; + } + if (bg != resource.back_Pixel) { + bg_initial.r = color_data[1].red; + bg_initial.g = color_data[1].green; + bg_initial.b = color_data[1].blue; + + scanned_page = scanned_page_color = scanned_page_reset; + + update_button_by_name(resource.back_Pixel, Xdvi_BG_COLOR_BTN); + + need_redraw = True; + } + if (hl != resource.hl_Pixel) { + XGCValues values; + values.foreground = resource.hl_Pixel; + XChangeGC(DISP, globals.gc.high, GCForeground, &values); + /* hack to update match GC: fake change in inverted property, redraw + so that GC is cleared, then change inverted property back */ + resource.match_highlight_inverted = !resource.match_highlight_inverted; + search_draw_inverted_regions(); + resource.match_highlight_inverted = !resource.match_highlight_inverted; + + update_button_by_name(resource.hl_Pixel, Xdvi_HL_COLOR_BTN); + + need_redraw = True; + } + /* NOTE: pixels for hyperlinks are not stored anywhere; just update always: */ + if (get_widget_by_name(&button, globals.widgets.top_level, Xdvi_VISITED_LINKS_BTN, True)) { + update_button(button, visited); + h_update_hyperlinks(button, visited); /* this already triggers a redraw */ + } + if (get_widget_by_name(&button, globals.widgets.top_level, Xdvi_UNVISITED_LINKS_BTN, True)) { + update_button(button, unvisited); + h_update_hyperlinks(button, unvisited); /* this already triggers a redraw */ + } + return need_redraw; +} + +static void +revert_resources(void) +{ + Pixel curr_fg = resource.fore_Pixel; + Pixel curr_bg = resource.back_Pixel; + Pixel curr_hl = resource.hl_Pixel; + Boolean need_redraw = False; + + /* save some old values */ + int save_shrink = resource.shrinkfactor; + + reload_app_resources(); + + /* revert from saved values */ + resource.use_color = globals.curr_use_color; + resource.gamma = globals.curr_gamma; + resource.paper = globals.curr_paper; + resource.shrinkfactor = save_shrink; + do_set_shrinkfactor(resource.shrinkfactor, True); + + update_preferences_darkness(); + + /* revert expert mode */ + if (resource.expert) + resource.expert_mode = XPRT_SHOW_NONE; + update_expert_mode(); + + toggle_statusline(); +#ifndef MOTIF + if (!BROKEN_RECONFIG) + toggle_scrollbars(); +#else + toggle_scrollbars(); +#endif + +#ifdef MOTIF + toggle_pagelist(); + toggle_toolbar(); + toggle_menubar(); +#else + toggle_buttons(); +#endif + + /* reset tooltips_wait_period, similar to TipAddWidget() in Tip.c */ + resource.tooltips_wait_period = resource.tooltips_wait_period_bak; + if (resource.tooltips_wait_period < 0) { + resource.show_tooltips = False; + } + else if (!resource.show_tooltips) { + if (resource.tooltips_wait_period == 0) + resource.tooltips_wait_period = -1; + else + resource.tooltips_wait_period = -resource.tooltips_wait_period; + } + + update_preferences_expert(); + update_preferences_tooltips(); + update_preferences_search(); + + update_preferences_color(); + update_preferences_hyperlinks(); + + update_preferences_windowsize(); + update_preferences_shrink(); + update_preferences_paper(); + + update_preferences_helpers(); + + need_redraw |= revert_colors(curr_fg, curr_bg, curr_hl); + +/* if (need_redraw) */ + /* just reload it always, there's too many exceptions ... + redraw isn't always sufficient if file has colors. */ + globals.ev.flags |= EV_RELOAD; + +} + +/* add widget w to list of dependent windows */ +void +add_to_deplist(struct prefs_choice *prefs, Widget w) +{ +#if 0 + size_t i; +#endif + prefs->depwin = xrealloc(prefs->depwin, + (prefs->depwin_cnt + 1) * sizeof *(prefs->depwin)); + prefs->depwin[prefs->depwin_cnt] = w; + prefs->depwin_cnt++; + +#if 0 + fprintf(stderr, "deplist after adding:\n"); + for (i = 0; i < prefs->depwin_cnt; i++) { + fprintf(stderr, "%lu: %p\n", (unsigned long)i, prefs->depwin[i]); + } +#endif +} + +static void +reread_prefs_cb(Window w) +{ + if (w != XtWindow(globals.widgets.top_level)) { + XChangeProperty(DISP, w, + atom_reread_prefs(), atom_reread_prefs(), 8, + PropModeReplace, + /* dummy values, since all the other instance needs to do is + reread the ~/.xdvirc.tmp file */ + (unsigned char *)"Y", 1); + } +} + +static void +apply_prefs_cb(XtPointer arg) +{ + struct topic_info *info = (struct topic_info *)arg; + struct prefs_choice *prefs = (struct prefs_choice *)info->data; + size_t i; + Widget colorsel; + + if (get_widget_by_name(&colorsel, globals.widgets.top_level, Xdvi_COLOR_DIALOG_NAME, False)) { + XtPopdown(XtParent(colorsel)); + } + + /* pop down dependent windows */ + TRACE_GUI((stderr, "window count: %lu\n", (unsigned long)prefs->depwin_cnt)); + for (i = 0; i < prefs->depwin_cnt; i++) { + TRACE_GUI((stderr, "popping down %lu: %p", (unsigned long)i, (void *)(prefs->depwin[i]))); + if (XtIsRealized(prefs->depwin[i])) { + XtCallCallbacks(prefs->depwin[i], XmNcancelCallback, NULL); + XSync(DISP, True); /* wait for server to catch up */ + if (XtIsRealized(prefs->depwin[i])) { + TRACE_GUI((stderr, "calling XmNokCallback of %lu: %p", (unsigned long)i, (void *)(prefs->depwin[i]))); + XtCallCallbacks(prefs->depwin[i], XmNokCallback, NULL); + } + } + } + free(prefs->depwin); + prefs->depwin = NULL; + prefs->depwin_cnt = 0; + + if (prefs->db == NULL) /* callback invoked multiple times? */ + return; + + merge_into_user_db(prefs->db); /* this destroys prefs->db */ + prefs->db = NULL; + + /* remember some current values */ + free(globals.curr_paper); + if (resource.paper != NULL) + globals.curr_paper = xstrdup(resource.paper); + + free(globals.curr_editor); + if (resource.editor != NULL) + globals.curr_editor = xstrdup(resource.editor); + + free(globals.curr_browser); + if (resource.browser != NULL) + globals.curr_browser = xstrdup(resource.browser); + +/* fprintf(stderr, "set curr_browser to: |%s|\n", globals.curr_browser); */ +/* fprintf(stderr, "set curr_editor to: |%s|\n", globals.curr_editor); */ + + if (get_xdvi_window_id(False, NULL) && save_user_preferences(False)) { + /* if other instances of xdvi are running, make them reread the + changed preferences by writing them to ~/.xdvirc.tmp and having + them read that file; otherwise they would overwrite the file if + user quits them after the current instance. + */ + get_xdvi_window_id(False, reread_prefs_cb); + } +} + +static void +revert_prefs_cb(XtPointer arg) +{ + struct topic_info *info = (struct topic_info *)arg; + struct prefs_choice *prefs = (struct prefs_choice *)info->data; + size_t i; + + /* pop down dependent windows */ + TRACE_GUI((stderr, "window count: %lu", (unsigned long)prefs->depwin_cnt)); + for (i = 0; i < prefs->depwin_cnt; i++) { + TRACE_GUI((stderr, "popping down %lu: %p", (unsigned long)i, (void *)(prefs->depwin[i]))); + if (XtIsRealized(prefs->depwin[i])) { + XtCallCallbacks(prefs->depwin[i], XmNcancelCallback, NULL); + XSync(DISP, True); /* wait for server to catch up */ + if (XtIsRealized(prefs->depwin[i])) { + TRACE_GUI((stderr, "calling XmNokCallback of %lu: %p", (unsigned long)i, (void *)(prefs->depwin[i]))); + XtCallCallbacks(prefs->depwin[i], XmNokCallback, NULL); + } + } + } + free(prefs->depwin); + prefs->depwin = NULL; + prefs->depwin_cnt = 0; + + if (prefs->db == NULL) { /* callback invoked multiple times, or prefs not changed */ + return; + } + + revert_resources(); + + XrmDestroyDatabase(prefs->db); + prefs->db = NULL; +} + +static void +save_prefs_exit(XtPointer arg) +{ + struct topic_info *info = (struct topic_info *)arg; + apply_prefs_cb(info); + XtPopdown(info->shell); + XSync(DISP, False); + xdvi_exit(EXIT_SUCCESS); +} + +static void +no_save_prefs_exit(XtPointer arg) +{ + struct topic_info *info = (struct topic_info *)arg; + revert_prefs_cb(info); + XtPopdown(info->shell); + XSync(DISP, False); + xdvi_exit(EXIT_SUCCESS); +} + +static void +close_prefs_exit(Widget w, XtPointer arg) +{ + struct topic_info *info = (struct topic_info *)arg; + struct prefs_choice *prefs = (struct prefs_choice *)info->data; +/* Widget dialog; */ +/* if (get_widget_by_name(&dialog, w, Xdvi_MESSAGE_DIALOG_NAME, True)) { */ +/* fprintf(stderr, "!!!!!!!!! removing window from deplist!\n"); */ +/* remove_from_deplist(prefs, dialog); */ +/* } */ + + remove_from_deplist(prefs, w); + +} + +Boolean +preferences_changed(void) +{ + Widget prefs_shell = 0, topic_pane = 0; + + if (get_widget_by_name(&prefs_shell, globals.widgets.top_level, "preferences_window", False) + && get_widget_by_name(&topic_pane, prefs_shell, "topic_pane", False)) { + struct topic_info *info = NULL; + struct prefs_choice *prefs = NULL; + + XtVaGetValues(topic_pane, XmNuserData, &info, NULL); + if (info == NULL) { + return False; + } + prefs = (struct prefs_choice *)info->data; + if (prefs->db != NULL) { /* prefs changed */ + + Widget popup = choice3_dialog(prefs_shell, + MSG_QUESTION, NULL, +#ifndef MOTIF + NULL, +#endif + close_prefs_exit, info, /* pre_callbacks */ + "Save and Exit", save_prefs_exit, info, + "Exit, don't Save", no_save_prefs_exit, info, + "Cancel", NULL, NULL, + "Preferences have been changed, but not saved yet. " + "Save them now?"); + add_to_deplist(prefs, popup); + return True; + } + } + + return False; +} + +void +popup_preferences_dialog(Widget parent, int arg) +{ + static Widget preferences_shell = 0; + static struct topic_info info; + static struct topic_item items[NUM_PREFS_TOPICS]; + static struct prefs_choice *prefs = NULL; + + if (preferences_shell == 0) { /* called 1st time; create widget */ + info.ok_callback = apply_prefs_cb; + info.cancel_callback = revert_prefs_cb; + info.items = items; +/* info.items_size = NUM_PREFS_TOPICS; */ + + prefs = xmalloc(sizeof *prefs); + prefs->depwin_cnt = 0; + prefs->depwin = NULL; +/* prefs->orig = orig_prefs; */ + /* apply_prefs_cb/revert_prefs_cb are responsible for copying + the changed preferences into the current preferences as + appropriate, and free()ing prefs.changed */ +/* prefs->changed = xmalloc(sizeof *(prefs->changed)); */ +/* copy_resources(orig_prefs, prefs->changed); */ + prefs->db = NULL; /* XrmGetStringDatabase(""); */ + info.data = prefs; + + preferences_shell = create_topic_window(parent, + "xdvik: Preferences", + Xdvi_PREFS_DIALOG_NAME, + &info, + initialize_items, + "OK", "Cancel"); + info.shell = preferences_shell; + center_window(preferences_shell, parent); + select_topic(&info, 0); + } + + if (arg >= 0) + select_topic(&info, arg); + + XtPopup(preferences_shell, XtGrabNone); + + if (resource.no_init_file) { + popup_message(preferences_shell, + MSG_WARN, + NULL, + "You specified the resource `noInitFile' or the `-q' command-line option. " + "Any preferences that you set in this dialog will be lost when you exit xdvi."); + } +} + +#else +/* silence `empty compilation unit' warnings */ +static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); } +#endif /* MOTIF */ |