diff options
Diffstat (limited to 'Build/source/texk/xdvik/gui/print-dialog.c')
-rw-r--r-- | Build/source/texk/xdvik/gui/print-dialog.c | 2973 |
1 files changed, 2973 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/gui/print-dialog.c b/Build/source/texk/xdvik/gui/print-dialog.c new file mode 100644 index 00000000000..c7187be6100 --- /dev/null +++ b/Build/source/texk/xdvik/gui/print-dialog.c @@ -0,0 +1,2973 @@ +/* + * Copyright (c) 2002-2004 Paul Vojta and 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. + */ + +/* + SU: Adapted from non-k xdvi's popups.c + + This implements a print popup (and a `save to file' popup). My idea + was to use the same window layout framework for both tasks, since + there's a big overlap in the widgets needed. However after looking + at the mess I've created, I'm no longer convinced this was a good + idea. (I reckon it's slightly better than the code duplication when + doing it in separate files, but only *slightly* ...) + + We need a more intelligent approach that bans this ugly kind of + `data proliferation' (those global arrays of widgets and helper + structures). Custom Widgets? Factory methods? Needs investigation. + + Also, in the long run, I guess we want the `Save' window to be more + similar to the file browser (i.e. to contain a file browser e.g. + in the upper part); in that case, the code will be moved into another + module anyway. + + Moreover, the GUI code should be completely separated from the backend + code. +*/ + +#include <string.h> +#include "xdvi-config.h" +#include "xdvi.h" +#include "my-vsnprintf.h" +#include <ctype.h> + +#include "print-dialog.h" +#include "print-log.h" +#include "print-internal.h" +#include "events.h" +#include "dvi-init.h" +#include "string-utils.h" +#include "util.h" +#include "x_util.h" +#include "message-window.h" +#include "pagesel.h" +#include "my-snprintf.h" +#include "sfSelFile.h" +#include "dvisel.h" /* for select_marked_pages() */ +#include "xlwradio.h" +#include "statusline.h" +#include "search-dialog.h" +#include "search-internal.h" +#include "special.h" + +/* Xlib and Xutil are already included */ + + +#include <X11/Xatom.h> +#include <X11/StringDefs.h> + +#ifdef MOTIF +# include <Xm/BulletinB.h> +# include <Xm/DialogS.h> +# include <Xm/PanedW.h> +# include <Xm/MessageB.h> +# include <Xm/LabelG.h> +# include <Xm/Form.h> +# include <Xm/Frame.h> +# include <Xm/ToggleBG.h> +# include <Xm/Text.h> +# include <Xm/TextF.h> +# include <Xm/PushB.h> +# include <Xm/Protocols.h> +# include <Xm/AtomMgr.h> +#define XTranslations XmNtranslations +#else /* MOTIF */ +# include <X11/Shell.h> +# include <X11/Xaw/Paned.h> +# include <X11/Xaw/Box.h> +# include <X11/Xaw/Form.h> +# include <X11/Xaw/Label.h> +# include <X11/Xaw/Command.h> +# include <X11/Xaw/Toggle.h> +# include <X11/Xaw/AsciiText.h> +# include <X11/Xaw/SimpleMenu.h> +# include <X11/Xaw/MenuButton.h> +# include <X11/Xaw/Sme.h> +# include <X11/Xaw/SmeBSB.h> +#if 0 +#include "xaw_bitmaps.h" +static Pixmap menu_double_arrow_bitmap; +#endif +#define XTranslations XtNtranslations +#endif /* MOTIF */ + +struct output_format_mapping { + const char *fmt_string; + outputFormatT fmt; + const char *extension; +} output_format_mapping[] = { + { "Postscript", FMT_PS , ".ps" }, + { "PDF", FMT_PS2PDF, ".pdf" }, + { "DVI", FMT_DVI, ".dvi" }, + { "Plain Text (ISO_8859-1)",FMT_ISO_8859_1, ".txt" }, + { "Plain Text (UTF-8)", FMT_UTF8, ".txt" }, + { NULL, FMT_NONE, NULL } +}; + +typedef enum printRadioT_ { + NO_PRINT_VAL = -1, + PRINT_TO_PRINTER = 1, + PRINT_TO_FILE, + SAVE_TO_FILE +} printRadioT; + + +typedef enum pageRadioT_ { + NO_PAGE_VAL = -1, + PRINT_ALL = 1, + PRINT_MARKED, + PRINT_RANGE, + SAVE_ALL, + SAVE_MARKED, + SAVE_RANGE +} pageRadioT; + +static Boolean is_print_button(pageRadioT flag) { + return (flag <= PRINT_RANGE); +} + +struct dialog_info { + char *printer_name; + char *file_name; + /* fully canonicalized filename, not visible in window, but used in error messages. + It is either NULL, or a malloc()ed buffer (which is free()d immediately before use). */ + char *expanded_filename; + char *dvips_options; + char *from_page; + char *to_page; + printRadioT print_radio; + pageRadioT range_radio; + outputFormatT output_format; +}; + +/* + global widgets, and arrays of global widgets (mosly, one + for the printing and one for the saving dialog). Needs + cleanup! +*/ + +#define FORMAT_SEL_CNT 5 + +/* top-level widgets: one for printing, one for saving to file */ +static Widget print_shell = NULL; +static Widget save_shell = NULL; + +/* global structures for saving print info between invocations */ +static struct dialog_info save_pr_info = { + NULL, NULL, NULL, NULL, NULL, NULL, NO_PRINT_VAL, NO_PAGE_VAL, FMT_NONE +}; +static struct dialog_info save_save_info = { + NULL, NULL, NULL, NULL, NULL, NULL, NO_PRINT_VAL, NO_PAGE_VAL, FMT_NONE +}; + +/* + these contain the currently selected values, or defaults; + used in communication between callbacks +*/ +static struct dialog_info curr_pr_info = { + NULL, NULL, NULL, NULL, NULL, NULL, PRINT_TO_PRINTER, PRINT_ALL, FMT_NONE +}; +static struct dialog_info curr_save_info = { + NULL, NULL, NULL, NULL, NULL, NULL, SAVE_TO_FILE, SAVE_ALL, FMT_NONE +}; + +static void print_precheck1(XtPointer info); +static void print_precheck2(XtPointer info); + +/* access methods ... */ +const char * +get_printer_options(void) +{ + return save_pr_info.printer_name; +} + +char * +get_dvips_options(printOrSaveActionT act) +{ + if (act == FILE_PRINT) + return save_pr_info.dvips_options; + else + return save_save_info.dvips_options; +} + +#ifdef MOTIF +static Widget from_label[FILE_ALL] = { None, None }; +static Widget format_selection_option; +XmString format_selection_texts[FORMAT_SEL_CNT]; + +#else /* MOTIF */ + +static Widget format_selection_label; +static Widget format_selection_button; +#if 0 +static Widget format_selection_b1; +#endif +static Widget format_selection_popup; +static Widget format_selection_menu[FORMAT_SEL_CNT]; + +static void xaw_print_save_act_go(Widget, XEvent *, String *, Cardinal *); + +#endif /* MOTIF */ + +static void print_cancel(Widget, XEvent *, String *, Cardinal *); +static void save_cancel(Widget, XEvent *, String *, Cardinal *); + +static Widget to_printer_radio; +static Widget to_file_radio_or_label[FILE_ALL] = { None, None }; +static Widget to_label[FILE_ALL] = { None, None }; +static Widget of_label[FILE_ALL] = { None, None }; +static Widget range_all_radio[FILE_ALL] = { None, None }; +static Widget range_marked_radio[FILE_ALL] = { None, None }; +static Widget range_from_to_radio[FILE_ALL] = { None, None }; +static Widget cancel_button[FILE_ALL] = { None, None }; +static Widget ok_button[FILE_ALL] = { None, None }; +static Widget print_to_printer_text; +static Widget print_to_file_text[FILE_ALL] = { None, None }; +static Widget print_to_file_button[FILE_ALL] = { None, None }; +static Widget dvips_options_text[FILE_ALL] = { None, None }; +static Widget page_from_text[FILE_ALL] = { None, None }; +static Widget page_to_text[FILE_ALL] = { None, None }; + +static int print_is_active = False; /* False if window is unmanaged or not created yet, True if managed */ +static int save_is_active = False; /* False if window is unmanaged or not created yet, True if managed */ + + +static XtActionsRec print_actions[] = { +#ifndef MOTIF + {"saveInternal", xaw_print_save_act_go }, + {"printInternal", xaw_print_save_act_go}, +#endif + {"WM_print_cancel", print_cancel }, + {"WM_save_cancel", save_cancel }, +}; + +/* + ============================================================ + generic utility functions + ============================================================ +*/ + +/* + Return the printer name, eventually followed by `-P$PRINTER', + since the `-o' option of dvips doesn't evaluate the environment + variable. +*/ +static char * +get_printer_name(void) +{ + char *printcmd, *printer; + + if (resource.dvips_printer_str != NULL && strlen(resource.dvips_printer_str) > 0) { + return xstrdup(resource.dvips_printer_str); + } + printcmd = xstrdup("lpr"); + printer = getenv("PRINTER"); + if (printer != NULL) { + printcmd = xstrcat(printcmd, " -P"); + printcmd = xstrcat(printcmd, printer); + } + return printcmd; +} + +/* return basename of `old_name' with `old_ext' replaced by `new_ext', in fresh memory */ +static char * +get_new_file_name(const char *old_name, const char *old_ext, const char *new_ext) +{ + /* old_name contains the normalized DVI file name, with path and extension */ + char *basename, *new_name; + size_t len; + + basename = strrchr(old_name, DIR_SEPARATOR); + + if (basename != NULL) { + basename++; + new_name = xmalloc(strlen(basename) + strlen(new_ext) + 1); + new_name = strcpy(new_name, basename); + } + else { + new_name = xmalloc(strlen(old_name) + strlen(new_ext) + 1); + new_name = strcpy(new_name, old_name); + } + + len = strlen(new_name); + strcpy(new_name + len - strlen(old_ext), new_ext); + return new_name; +} + +/* + * Translate `non-standard' paper sizes for xdvi into options suitable + * for dvips. We don't do this always, since it would override the papersize + * specials inserted by e.g. + * \usepackage[dvips]{geometry} + * which is the preferred way to specify the papersize. If the papersize + * has been explicitly set by such a special, this function returns NULL. + * Else it returns the value of the `paper' resource, without the trailing + * `r', and sets the `landscape' argument to True if a trailing `r' was + * present. + * + * Note that we don't check/warn about whether the current paper + * resource is valid for dvips; dvips will ignore invalid paper sizes. + */ +static char * +get_dvips_papersize(Boolean *landscape) +{ + char *papersize; + if (have_papersize_special()) + return NULL; + + papersize = xstrdup(resource.paper); + *landscape = False; + if (papersize[strlen(papersize) - 1] == 'r') { /* landscape size */ + papersize[strlen(papersize) - 1] = '\0'; + *landscape = True; + } + TRACE_GUI((stderr, "Using dvips arguments: `%s', %s", papersize, *landscape ? "landscape" : "portrait")); + return papersize; +} + +static void +set_outfile_name(struct dialog_info *info, struct dialog_info *save_info, printOrSaveActionT act) +{ + free(info->file_name); + if (act == FILE_PRINT) { + info->file_name = get_new_file_name(globals.dvi_name, ".dvi", ".ps"); + } + else { /* saving to file */ + if (save_info->range_radio == SAVE_ALL) { + info->file_name = get_new_file_name(globals.dvi_name, ".dvi", + output_format_mapping[resource.default_saving_format].extension); + } + else { + char *tmp = xstrdup("_pp"); + tmp = xstrcat(tmp, output_format_mapping[resource.default_saving_format].extension); + + info->file_name = get_new_file_name(globals.dvi_name, ".dvi", tmp); + free(tmp); + } + } +} + +/* get initial values for dialog texts */ +static void +get_initial_dialog_values(struct dialog_info *info, printOrSaveActionT act) +{ + if (act == FILE_PRINT && info->printer_name == NULL) + info->printer_name = get_printer_name(); + + if (info->dvips_options == NULL) { + info->dvips_options = xstrdup(""); + + /* add -t option if not already present */ + if (resource.dvips_options_str != NULL + && strstr(resource.dvips_options_str, "-t ") == NULL) { + Boolean dvips_landscape = False; + char *dvips_paper_size = get_dvips_papersize(&dvips_landscape); + if (dvips_paper_size != NULL) { + info->dvips_options = xstrdup("-t "); + info->dvips_options = xstrcat(info->dvips_options, dvips_paper_size); + free(dvips_paper_size); + if (dvips_landscape) { + info->dvips_options = xstrcat(info->dvips_options, " -t landscape"); + } + } + } + + if (resource.dvips_options_str != NULL) { + if (strlen(info->dvips_options) > 0) + info->dvips_options = xstrcat(info->dvips_options, " "); + info->dvips_options = xstrcat(info->dvips_options, resource.dvips_options_str); + } + } + + if (info->from_page == NULL) { + info->from_page = xmalloc(LENGTH_OF_INT + 1); + sprintf(info->from_page, "%d", current_page + globals.pageno_correct); + } + + if (info->to_page == NULL) { + info->to_page = xmalloc(LENGTH_OF_INT + 1); + sprintf(info->to_page, "%d", current_page + globals.pageno_correct); + } +} + + +#if MOTIF +static void +set_sensitivity(int i) +{ + Boolean sensitivity; + +/* if (i == curr_pr_info.print_radio) /\* if no change *\/ */ +/* return; */ + + curr_pr_info.print_radio = i; + + sensitivity = (i == PRINT_TO_PRINTER); + XtSetSensitive(print_to_printer_text, sensitivity); + +/* sensitivity ^= (True ^ False); */ + XtSetSensitive(print_to_file_text[FILE_PRINT], !sensitivity); + XtSetSensitive(print_to_file_button[FILE_PRINT], !sensitivity); +} +#endif /* MOTIF */ + +static void +update_dvips_options_sensitivity(int idx, Widget top) +{ + Widget dvips_label; + +#if MOTIF + Widget dvips_options; + + if (get_widget_by_name(&dvips_label, top, "dvips_options_name", True) && + get_widget_by_name(&dvips_options, top, "dvips_options_text", True)) { + if (output_format_mapping[idx].fmt == FMT_PS || + output_format_mapping[idx].fmt == FMT_PS2PDF) { + XtSetSensitive(dvips_label, True); + XtSetSensitive(dvips_options, True); + } + else { + XtSetSensitive(dvips_label, False); + XtSetSensitive(dvips_options, False); + } + } +#else + if (get_widget_by_name(&dvips_label, top, "dvips_options_name", True)) { + XtSetSensitive(XtParent(dvips_label), + output_format_mapping[idx].fmt == FMT_PS || + output_format_mapping[idx].fmt == FMT_PS2PDF); + } +#endif +} + +/* callbacks */ + +static void +select_format_cb(Widget w, XtPointer client_data, XtPointer call_data) +{ + Widget file_text, top; + + char *filename; + int i; +#ifdef MOTIF + Widget f1, f2; + char *ptr; + + i = (int)client_data; + UNUSED(call_data); + f1 = XtParent(w); + ASSERT(f1 != 0, "Parent of widget musn't be NULL!\n"); + f2 = XtParent(f1); + ASSERT(f2 != 0, "Parent of f1 musn't be NULL!\n"); + top = XtParent(f2); + ASSERT(top != 0, "Parent of f2 musn't be NULL!\n"); + + if ((file_text = XtNameToWidget(top, "*file_text")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"file_text\" widget!")); + return; + } + XtVaGetValues(file_text, XmNvalue, &filename, NULL); + if ((ptr = strrchr(filename, '.')) != NULL) { + char buf[1024]; + replace_extension(filename, output_format_mapping[i].extension, buf, sizeof buf); + XtVaSetValues(file_text, XmNvalue, buf, NULL); + } +#else /* MOTIF */ + + Widget popup, button; + char *ptr1, *ptr2; + char buf[1024]; + + UNUSED(call_data); + popup = XtParent(w); + ASSERT(popup != 0, "Parent of menu musn't be NULL!\n"); + button = XtParent(popup); + ASSERT(button != 0, "Parent of popup musn't be NULL!\n"); + + top = (Widget)client_data; + + if ((file_text = XtNameToWidget(top, "*file_text")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"file_text\" widget!")); + return; + } + + XtVaGetValues(file_text, XtNstring, &filename, NULL); +/* fprintf(stderr, "file text: |%s|\n", filename); */ + + /* swap title strings */ + XtVaGetValues(button, XtNlabel, &ptr1, NULL); + XtVaGetValues(w, XtNlabel, &ptr2, NULL); + strncpy(buf, ptr1, sizeof buf); + + for (i = 0; output_format_mapping[i].fmt_string != NULL; i++) { + if (strcmp(ptr2, output_format_mapping[i].fmt_string) == 0) { + char buf2[1024]; + replace_extension(filename, output_format_mapping[i].extension, buf2, sizeof buf2); + XtVaSetValues(file_text, XtNstring, buf2, NULL); + + break; + } + } + if (output_format_mapping[i].fmt_string == NULL) { + popup_message(get_matching_parent(w, globals.widgets.top_level, "print_popup", "save_popup", NULL), + MSG_WARN, + REPORT_XDVI_BUG_TEMPLATE, + "Unrecognized string in format selector: |%s|", ptr2); + } + XtVaSetValues(button, XtNlabel, ptr2, NULL); + XtVaSetValues(w, XtNlabel, buf, NULL); + +#endif /* MOTIF */ + + save_save_info.output_format = curr_save_info.output_format = output_format_mapping[i].fmt; + + update_dvips_options_sensitivity(i, save_shell); + + resource.default_saving_format = save_save_info.output_format; + set_outfile_name(&save_save_info, &curr_save_info, FILE_SAVE); +} + +static void +cb_print_cancel(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct save_or_print_info *info = (struct save_or_print_info *)client_data; + UNUSED(w); + UNUSED(call_data); + + ASSERT(info != NULL, "client_data in cb_print_cancel musn't be NULL!"); + if (info->message_popup != 0) { + kill_message_window(info->message_popup); + } + XtPopdown(print_shell); + print_is_active = False; +} + +static void +cb_save_cancel(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct save_or_print_info *info = (struct save_or_print_info *)client_data; + UNUSED(w); + UNUSED(call_data); + + ASSERT(info != NULL, "client_data in cb_save_cancel musn't be NULL!"); + if (info->message_popup != 0) { + kill_message_window(info->message_popup); + } + XtPopdown(save_shell); + save_is_active = False; +} + +static void +cb_print_or_save(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct save_or_print_info *info = (struct save_or_print_info *)client_data; + UNUSED(w); + UNUSED(call_data); + + print_precheck1((XtPointer)info); +} + +/* access from outside the module */ +void +cancel_saving(struct save_or_print_info *info) +{ + cb_save_cancel(NULL, info, NULL); +} + + +static void +print_cancel(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct save_or_print_info *info = NULL; + void *ptr; + + UNUSED(w); + UNUSED(event); + + ASSERT(*num_params > 0, "params in print_cancel must be > 0!"); + ASSERT(*params != NULL, "params in print_cancel mustn't be NULL!"); + + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + info = (struct save_or_print_info *)ptr; + + cb_print_cancel(NULL, info, NULL); +} + +static void +save_cancel(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct save_or_print_info *info = NULL; + void *ptr; + + UNUSED(w); + UNUSED(event); + + ASSERT(*num_params > 0, "params in save_cancel must be > 0!"); + ASSERT(*params != NULL, "params in save_cancel mustn't be NULL!"); + + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + info = (struct save_or_print_info *)ptr; + + cb_save_cancel(NULL, info, NULL); +} + +#ifndef MOTIF + +/* + enable the `print to' button if user presses key or mouse button + inside that input field +*/ +static void +xaw_print_handle_key(Widget widget, XtPointer closure, XEvent *ev, Boolean *cont) +{ + char *number; + int i; + + number = (char *)closure; + i = atoi(number); + ASSERT(i == 2 || i == 3, "Button index should be 2 or 3"); + UNUSED(widget); + UNUSED(ev); + UNUSED(cont); + + if (i == 2) { + XawToggleSetCurrent(to_printer_radio, (XtPointer)PRINT_TO_PRINTER); + } + else { + ASSERT(to_file_radio_or_label[FILE_PRINT] != NULL, ""); + XawToggleSetCurrent(to_file_radio_or_label[FILE_PRINT], (XtPointer)PRINT_TO_FILE); + } +} + +/* + enable the `print range' button if user presses key or mouse button + inside that input field +*/ +static void +xaw_range_handle_key(Widget widget, XtPointer closure, XEvent *ev, Boolean *cont) +{ + printOrSaveActionT act = (printOrSaveActionT)closure; + UNUSED(widget); + UNUSED(ev); + UNUSED(cont); + + if (act == FILE_PRINT && curr_pr_info.range_radio != PRINT_RANGE) { + ASSERT(range_all_radio[act] != NULL, "button should have been initialized"); + XawToggleSetCurrent(range_all_radio[act], (XtPointer)PRINT_RANGE); + } + else if (act == FILE_SAVE && curr_save_info.range_radio != SAVE_RANGE) { + ASSERT(range_all_radio[act] != NULL, "button should have been initialized"); + XawToggleSetCurrent(range_all_radio[act], (XtPointer)SAVE_RANGE); + } +} + + +static void +xaw_print_save_act_go(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct save_or_print_info *info = NULL; + void *ptr; + + UNUSED(w); + UNUSED(event); + + ASSERT(*num_params > 0, "params in search_cancel must be > 0!"); + ASSERT(*params != NULL, "params in search_cancel mustn't be NULL!"); + + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + info = (struct save_or_print_info *)ptr; + + print_precheck1((XtPointer)info); +} + +#if 0 +static void +xaw_popup_menu_cb(Widget w, XtPointer client_data, XtPointer call_data) +{ + Position x, y; + Dimension h; + int pos_x, pos_y; + Window dummy; + + Widget popup = (Widget)client_data; + fprintf(stderr, "popup: %p\n", popup); + XtVaGetValues(w, XtNx, &x, XtNy, &y, XtNheight, &h, NULL); + fprintf(stderr, "x: %d, y: %d, h: %d\n", x, y, h); + XTranslateCoordinates(DISP, XtWindow(w), RootWindowOfScreen(SCRN), + x, y, &pos_x, &pos_y, &dummy); + XtRealizeWidget(popup); + /* WRONG - would need to use x position of its left widget ... */ + XtVaSetValues(popup, XtNx, pos_x, XtNy, pos_y + h + 1, NULL); + XtPopup(popup, XtGrabNone); +} +#endif /* 0 */ + +#endif /* not MOTIF */ + +static void +cb_print_vs_file(Widget w, XtPointer client_data, XtPointer call_data) +{ +#ifdef MOTIF + Boolean to_printer = False, to_file = False; + if (((XmToggleButtonCallbackStruct *)call_data)->set) { + if (w == to_printer_radio) + to_printer = True; + else + to_file = True; + + } + else { + if (w == to_printer_radio) + to_file = True; + else + to_printer = True; + } + + XmToggleButtonGadgetSetState(to_file_radio_or_label[FILE_PRINT], to_file, False); + XmToggleButtonGadgetSetState(to_printer_radio, to_printer, False); + + set_sensitivity((int)client_data); + XmProcessTraversal(curr_pr_info.print_radio == PRINT_TO_PRINTER + ? print_to_printer_text + : print_to_file_text[FILE_PRINT], + XmTRAVERSE_CURRENT); +#else /* MOTIF */ + int i = (int) XawToggleGetCurrent(to_printer_radio); + + UNUSED(w); + UNUSED(client_data); + UNUSED(call_data); + + /* + NOTE: Unlike non-k xdvi, we don't use set_sensitivity for the + Xaw version, since the text inside the textfield cannot be made + insensitive, so it won't be obvious to users why they cannot + change the text. Also, the page range isn't set insensitive + either. + */ + if (i != 0) + curr_pr_info.print_radio = i; +#endif /* MOTIF */ + +} + + + +static void +cb_range(Widget w, XtPointer client_data, XtPointer call_data) +{ + pageRadioT flag = (pageRadioT)client_data; + printOrSaveActionT act; + +#ifdef MOTIF + + Boolean sensitivity; + UNUSED(call_data); + ASSERT(flag != PRINT_MARKED || flag != SAVE_MARKED || pageinfo_have_marked_pages(), + "PRINT_MARKED or SAVE_MARKED shouldn't be togglable if there are no marked pages!"); + + if (is_print_button(flag)) { + curr_pr_info.range_radio = (int)client_data; + sensitivity = (curr_pr_info.range_radio == PRINT_RANGE); + act = FILE_PRINT; + } + else { + curr_save_info.range_radio = (int)client_data; + sensitivity = (curr_save_info.range_radio == SAVE_RANGE); + act = FILE_SAVE; + } + + /* switch off other radio buttons, switch on current one */ + XmToggleButtonGadgetSetState(range_all_radio[act], False, False); + XmToggleButtonGadgetSetState(range_marked_radio[act], False, False); + XmToggleButtonGadgetSetState(range_from_to_radio[act], False, False); + XmToggleButtonGadgetSetState(w, True, False); + + /* set from-to range to sensitive if appropriate */ + XtSetSensitive(from_label[act], sensitivity); + XtSetSensitive(page_from_text[act], sensitivity); + XtSetSensitive(to_label[act], sensitivity); + XtSetSensitive(page_to_text[act], sensitivity); + XtSetSensitive(of_label[act], sensitivity); + +#else /* MOTIF */ + + int i; + UNUSED(call_data); + if (is_print_button(flag)) { + act = FILE_PRINT; + } + else { + act = FILE_SAVE; + } + + UNUSED(w); + + i = (int) XawToggleGetCurrent(range_all_radio[act]); + + if (i != 0) { + ASSERT(i != PRINT_MARKED || i != SAVE_MARKED || pageinfo_have_marked_pages(), + "PRINT_MARKED or SAVE_MARKED shouldn't be togglable if there are no marked pages!"); + + if (act == FILE_PRINT) + curr_pr_info.range_radio = i; + else + curr_save_info.range_radio = i; + } + +#endif /* MOTIF */ +} + +static void +set_filename_callback(const char *fname, void *data) +{ + if (fname != NULL) { + Widget w = (Widget)data; + XtVaSetValues(w, +#ifdef MOTIF + XmNvalue, fname, + XmNcursorPosition, strlen(fname), +#else + XtNstring, fname, +#endif + NULL); + } +} + + +static void +cb_browse(Widget w, XtPointer client_data, XtPointer call_data) +{ +/* char *fname; */ + struct save_or_print_info *info = (struct save_or_print_info *)client_data; + printOrSaveActionT act = info->act; +/* Widget ret_widget; */ + Widget parent; + + UNUSED(call_data); +#ifdef MOTIF + UNUSED(w); +#else + if (act == FILE_PRINT) + xaw_print_handle_key(w, (XtPointer)"3", NULL, NULL); +#endif + + if (act == FILE_SAVE) { + static struct filesel_callback cb; /* static so that we can pass its address */ + cb.title = "Xdvi: Save to file"; + cb.prompt = "Save to file:"; + cb.ok = "OK"; + cb.cancel = "Cancel"; + cb.init_path = NULL; + cb.filemask = "*.dvi"; + cb.must_exist = False; + cb.exit_on_cancel = False; + cb.func_ptr = set_filename_callback; + cb.data = print_to_file_text[act]; + + if (!get_widget_by_name(&parent, globals.widgets.top_level, Xdvi_SAVE_SHELL_NAME, True)) + parent = globals.widgets.top_level; + XsraSelFile(parent, &cb); +/* fprintf(stderr, "done saving: return widget = %p\n", ret_widget); */ + } + else { + static struct filesel_callback cb; /* static so that we can pass its address */ + cb.title = "Xdvi: Print to file"; + cb.prompt = "Print to file:"; + cb.ok = "OK"; + cb.cancel = "Cancel"; + cb.init_path = NULL; + cb.filemask = "*.ps"; + cb.must_exist = False; + cb.exit_on_cancel = False; + cb.func_ptr = set_filename_callback; + cb.data = print_to_file_text[act]; + + if (!get_widget_by_name(&parent, globals.widgets.top_level, Xdvi_PRINT_SHELL_NAME, True)) + parent = globals.widgets.top_level; + XsraSelFile(parent, &cb); +/* fname = XsraSelFile(parent, "Xdvi: Print to file", "Print to file:", */ +/* "OK", "Cancel", */ +/* NULL, */ +/* "*.ps", False, &ret_widget); */ +/* fprintf(stderr, "done printing: return widget = %p\n", ret_widget); */ + } + +/* if (fname != NULL) { */ +/* XtVaSetValues(print_to_file_text[act], */ +/* #ifdef MOTIF */ +/* XmNvalue, fname, XmNcursorPosition, strlen(fname), */ +/* #else */ +/* XtNstring, fname, */ +/* #endif */ +/* NULL); */ +/* } */ +/* free(fname); */ +} + +/* create a popup dialog for printing a DVI file OR saving pages from a DVI file */ +static Widget +create_print_or_save_window(struct save_or_print_info *info, char *ofstring) +{ + printOrSaveActionT act = info->act; + Widget top_level_shell; + Atom WM_DELETE_WINDOW; +#ifndef MOTIF + Widget form, paned, box; + Widget f01form, f02form; /* dummy forms to get indentation consistent */ + Widget r1form; + Widget r1label; + Widget r2form, r3form, r4form = 0; + Widget r4label; + Widget r5label; + Widget r6form; + Widget r61form; + Widget r7form; + char *str; + + XtTranslations xlats, xlats2, wm_translations; + XtAccelerators accels2; + int ddist; + + static Dimension w_avg = 220; + Dimension w_curr; + + /* handy abbrevs */ +#define HORIZONTAL_RESIZING_NO XtNleft, XtChainLeft, XtNright, XtChainLeft +#define HORIZONTAL_RESIZING_YES XtNleft, XtChainLeft, XtNright, XtChainRight +#define VERTICAL_RESIZING_NO XtNtop, XtChainTop, XtNbottom, XtChainTop + + XtAddActions(print_actions, XtNumber(print_actions)); + + if (act == FILE_SAVE) { + str = get_string_va("<Message>WM_PROTOCOLS: WM_save_cancel(%p)\n" + "<Key>Escape:WM_save_cancel(%p)\n" + "<Key>q:WM_save_cancel(%p)", + info, info, info); + wm_translations = XtParseTranslationTable(str); + free(str); + } + else { + str = get_string_va("<Message>WM_PROTOCOLS: WM_print_cancel(%p)\n" + "<Key>Escape:WM_print_cancel(%p)\n" + "<Key>q:WM_print_cancel(%p)", + info, info, info); + wm_translations = XtParseTranslationTable(str); + free(str); + } + + top_level_shell = XtVaCreatePopupShell(act == FILE_SAVE ? Xdvi_SAVE_SHELL_NAME : Xdvi_PRINT_SHELL_NAME, + transientShellWidgetClass, + globals.widgets.top_level, + XtNtitle, act == FILE_SAVE ? "xdvik: Save file" : "xdvik: Print DVI file", + XtNmappedWhenManaged, False, + XtNtransientFor, globals.widgets.top_level, + XtNallowShellResize, True, + XtNtranslations, wm_translations, + NULL); + + WM_DELETE_WINDOW = XInternAtom(XtDisplay(top_level_shell), "WM_DELETE_WINDOW", False); + + paned = XtVaCreateManagedWidget(act == FILE_SAVE ? "save_paned" : "print_paned", + panedWidgetClass, top_level_shell, NULL); + + form = XtVaCreateManagedWidget("form", formWidgetClass, + paned, + XtNallowResize, True, + NULL); + XtVaGetValues(form, XtNdefaultDistance, &ddist, NULL); +/* fprintf(stderr, "form1: %ld\n", (long)form); */ + + xlats = XtParseTranslationTable("<EnterWindow>:highlight(Always)\n" + "<LeaveWindow>:unhighlight()\n" + "<Btn1Down>,<Btn1Up>:set()notify()"); + + if (act == FILE_PRINT) { + str = get_string_va("<Key>Return:printInternal(%p)", info); + xlats2 = XtParseTranslationTable(str); + } + else { + str = get_string_va("<Key>Return:saveInternal(%p)", info); + xlats2 = XtParseTranslationTable(str); + } + free(str); + + if (act == FILE_PRINT) { /* selection `to printer/to file' */ + /* FIXME: set real sizes here */ +/* Dimension w_curr; */ + f01form = XtVaCreateManagedWidget("dummy_print_to_label_form", formWidgetClass, + form, + XtNresizable, True, + XtNborderWidth, 0, + /* XtNvertDistance, 10, */ + HORIZONTAL_RESIZING_YES, + NULL); + r1label = XtVaCreateManagedWidget("print_to", labelWidgetClass, + f01form, + XtNlabel, "Print to: ", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + NULL); + + r2form = XtVaCreateManagedWidget("print_to_printer_form", formWidgetClass, + form, + XtNresizable, True, + XtNborderWidth, 0, + XtNvertDistance, 0, + XtNfromVert, f01form, + HORIZONTAL_RESIZING_YES, + XtNallowResize, True, + NULL); + + accels2 = XtParseAcceleratorTable("<Btn1Down>,<Btn1Up>:set()notify()"); + + to_printer_radio = XtVaCreateManagedWidget("to_printer", +#ifdef XAW + radioWidgetClass, +#else + toggleWidgetClass, +#endif + r2form, + XtNlabel, "Printer: ", + XtNborderWidth, 0, + XtNhighlightThickness, 1, + XtNradioData, PRINT_TO_PRINTER, + XtNstate, resource.default_printing_target == PRINT_TO_PRINTER, + XtNtranslations, xlats, + XtNaccelerators, accels2, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + + XtAddCallback(to_printer_radio, XtNcallback, cb_print_vs_file, NULL); + XtInstallAccelerators(r2form, to_printer_radio); + + print_to_printer_text = XtVaCreateManagedWidget("printer_text", asciiTextWidgetClass, + r2form, + XtNwidth, w_avg, + XtNdataCompression, False, + XtNeditType, XawtextEdit, + /* XtNresize, XawtextResizeWidth, */ + XtNfromHoriz, to_printer_radio, + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, + /* XtNscrollHorizontal, XawtextScrollAlways, */ + NULL); + XtOverrideTranslations(print_to_printer_text, xlats2); + XtAddEventHandler(print_to_printer_text, KeyPressMask | ButtonPressMask, False, + xaw_print_handle_key, (XtPointer)"2"); + + adjust_vertically(to_printer_radio, print_to_printer_text, ddist); + + r3form = XtVaCreateManagedWidget("print_to_file_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNvertDistance, 0, + XtNfromVert, r2form, + HORIZONTAL_RESIZING_YES, + NULL); + + to_file_radio_or_label[act] = XtVaCreateManagedWidget("to_file", +#ifdef XAW + radioWidgetClass, +#else + toggleWidgetClass, +#endif + r3form, + XtNhighlightThickness, 1, + XtNborderWidth, 0, + XtNlabel, "File: ", + XtNstate, resource.default_printing_target == PRINT_TO_FILE, + XtNradioGroup, to_printer_radio, + XtNradioData, PRINT_TO_FILE, + XtNtranslations, xlats, + XtNaccelerators, accels2, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + XtAddCallback(to_file_radio_or_label[act], XtNcallback, cb_print_vs_file, NULL); + XtInstallAccelerators(r3form, to_file_radio_or_label[act]); + + print_to_file_text[act] = XtVaCreateManagedWidget("file_text", asciiTextWidgetClass, + r3form, + XtNwidth, w_avg, + XtNdataCompression, False, + XtNeditType, XawtextEdit, + XtNfromHoriz, to_file_radio_or_label[act], + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, + NULL); + XtOverrideTranslations(print_to_file_text[act], xlats2); + XtAddEventHandler(print_to_file_text[act], KeyPressMask | ButtonPressMask, False, + xaw_print_handle_key, (XtPointer)"3"); + } + else { /* not printing, but saving */ + int i; + Dimension max_entry_width = 0; + f01form = XtVaCreateManagedWidget("dummy_save_as_form", formWidgetClass, + form, + XtNresizable, True, + XtNborderWidth, 0, + /* XtNvertDistance, 10, */ + HORIZONTAL_RESIZING_YES, + NULL); + r1label = XtVaCreateManagedWidget("save_as", labelWidgetClass, + f01form, + XtNlabel, "Save as: ", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + NULL); + r1form = XtVaCreateManagedWidget("save_to_file_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNfromVert, f01form, + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, + NULL); +/* fprintf(stderr, "formr1: %ld\n", (long)r1form); */ +#if 0 + menu_double_arrow_bitmap + = XCreateBitmapFromData(XtDisplay(globals.widgets.top_level), + RootWindowOfScreen(XtScreen(globals.widgets.top_level)), + (char *)menu_double_arrow_bits, MENU_DOUBLE_ARROW_W, MENU_DOUBLE_ARROW_H); +#endif + format_selection_label = XtVaCreateManagedWidget("format_selection_label", labelWidgetClass, + r1form, + XtNlabel, "Format: ", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + format_selection_button = XtVaCreateManagedWidget("format_selection_button", menuButtonWidgetClass, + r1form, + XtNmenuName, "format_selection_popup", + XtNlabel, output_format_mapping[resource.default_saving_format].fmt_string, + XtNjustify, XtJustifyLeft, + XtNborderWidth, resource.btn_border_width, + XtNfromHoriz, format_selection_label, +#if 0 + XtNhighlightThickness, 0, +#endif + NULL); +#if 0 /* Hack for arrow - menuButtonWidget cannot have a XtNrightBitmap!!! */ + format_selection_b1 = XtVaCreateManagedWidget("format_selection_b1", commandWidgetClass, + r1form, + XtNborderWidth, resource.btn_border_width, + XtNfromHoriz, format_selection_button, + XtNhorizDistance, -1, + XtNhighlightThickness, 0, + XtNbitmap, menu_double_arrow_bitmap, + NULL); + adjust_heights(format_selection_button, format_selection_b1, NULL); +#endif + format_selection_popup = XtCreatePopupShell("format_selection_popup", simpleMenuWidgetClass, + format_selection_button, +/* globals.widgets.top_level, */ + NULL, 0); +#if 0 + XtAddCallback(format_selection_b1, XtNcallback, xaw_popup_menu_cb, format_selection_popup); +#endif + for (i = 1; i < FORMAT_SEL_CNT; i++) { + char name[1024]; + Dimension curr_entry_width; + SNPRINTF(name, sizeof name, "format_selection_pulldown_%d", i); + format_selection_menu[i] = XtVaCreateManagedWidget(name, smeBSBObjectClass, + format_selection_popup, + XtNjustify, XtJustifyLeft, + XtNlabel, + i == resource.default_saving_format + ? output_format_mapping[0].fmt_string + : output_format_mapping[i].fmt_string, + NULL); + XtVaGetValues(format_selection_menu[i], XtNwidth, &curr_entry_width, NULL); + if (curr_entry_width > max_entry_width) + max_entry_width = curr_entry_width; + XtAddCallback(format_selection_menu[i], XtNcallback, select_format_cb, form); + } + XtVaSetValues(format_selection_button, XtNwidth, max_entry_width, NULL); + + r3form = XtVaCreateManagedWidget("to_file_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNfromVert, r1form, + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, + NULL); + to_file_radio_or_label[act] = XtVaCreateManagedWidget("to_file", labelWidgetClass, + r3form, + XtNlabel, "File name: ", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + print_to_file_text[act] = XtVaCreateManagedWidget("file_text", asciiTextWidgetClass, + r3form, + XtNwidth, w_avg, + XtNdataCompression, False, + /* XtNvertDistance, ddist + 5, */ + XtNeditType, XawtextEdit, + XtNfromHoriz, to_file_radio_or_label[act], + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, + NULL); + XtOverrideTranslations(print_to_file_text[act], xlats2); + + + { /* align left edges of format selection pulldown and filename field */ + Dimension w1, w2, w_max; + XtVaGetValues(format_selection_label, XtNwidth, &w1, NULL); + XtVaGetValues(to_file_radio_or_label[act], XtNwidth, &w2, NULL); + w_max = MAX(w1, w2); + XtVaSetValues(format_selection_button, XtNhorizDistance, ddist + (w_max - w1), NULL); + XtVaSetValues(print_to_file_text[act], XtNhorizDistance, ddist + (w_max - w2), NULL); + } + } + +#define DIST_1 8 /* FIXME */ + print_to_file_button[act] = XtVaCreateManagedWidget("file_button", commandWidgetClass, + r3form, + XtNlabel, "Browse ...", + XtNfromHoriz, print_to_file_text[act], + XtNhorizDistance, DIST_1, + /* attach to right of form, no resizing: */ + XtNleft, XtChainRight, XtNright, XtChainRight, + VERTICAL_RESIZING_NO, + NULL); + + XtVaGetValues(print_to_file_button[act], XtNwidth, &w_curr, NULL); + XtVaSetValues(print_to_file_text[act], XtNwidth, w_avg - w_curr - DIST_1 - 2, NULL); +#undef DIST_1 + + adjust_vertically(to_file_radio_or_label[act], print_to_file_text[act], ddist + 5); + adjust_vertically(print_to_file_text[act], to_file_radio_or_label[act], ddist + 5); + adjust_vertically(print_to_file_button[act], to_file_radio_or_label[act], ddist + 5); + + XtAddCallback(print_to_file_button[act], XtNcallback, cb_browse, (XtPointer)info); + + /* other dvips options */ + r4form = XtVaCreateManagedWidget("dvips_options_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNfromVert, r3form, + XtNvertDistance, 0, + HORIZONTAL_RESIZING_YES, + NULL); + + r4label = XtVaCreateManagedWidget("dvips_options_name", labelWidgetClass, + r4form, + XtNlabel, "Dvips Options:", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + + dvips_options_text[act] = XtVaCreateManagedWidget("dvips_options_text", asciiTextWidgetClass, + r4form, + XtNwidth, w_avg, + XtNdataCompression, False, + XtNeditType, XawtextEdit, + XtNfromHoriz, r4label, + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, + NULL); + XtOverrideTranslations(dvips_options_text[act], xlats2); + + { /* align left edges of input fields */ + Dimension w1, w2, w3, w_max; + + if (act == FILE_PRINT) + XtVaGetValues(to_printer_radio, XtNwidth, &w1, NULL); + else + XtVaGetValues(format_selection_label, XtNwidth, &w1, NULL); + + XtVaGetValues(to_file_radio_or_label[act], XtNwidth, &w2, NULL); + XtVaGetValues(r4label, XtNwidth, &w3, NULL); + + w_max = MAX(MAX(w1, w2), w3); + + if (act == FILE_PRINT) + XtVaSetValues(print_to_printer_text, XtNhorizDistance, ddist + (w_max - w1), NULL); + else + XtVaSetValues(format_selection_button, XtNhorizDistance, ddist + (w_max - w1), NULL); + + XtVaSetValues(print_to_file_text[act], XtNhorizDistance, ddist + (w_max - w2), NULL); + XtVaSetValues(dvips_options_text[act], XtNhorizDistance, ddist + (w_max - w3), NULL); + } + + /* page selection */ + + f02form = XtVaCreateManagedWidget("dummy_pages_form", formWidgetClass, + form, + XtNfromVert, r4form, + XtNresizable, True, + XtNborderWidth, 0, + /* XtNvertDistance, 10, */ + HORIZONTAL_RESIZING_NO, + NULL); + + r5label = XtVaCreateManagedWidget("range_lab", labelWidgetClass, + f02form, + XtNlabel, "Pages:", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + NULL); + + r6form = XtVaCreateManagedWidget("page_range_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNfromVert, f02form, + /* XtNvertDistance, 0, */ + HORIZONTAL_RESIZING_NO, + NULL); + + accels2 = XtParseAcceleratorTable("<Btn1Down>,<Btn1Up>:set()notify()"); + range_all_radio[act] = XtVaCreateManagedWidget("range_all", +#ifdef XAW + radioWidgetClass, +#else + toggleWidgetClass, +#endif + r6form, + XtNlabel, "All ", + XtNborderWidth, 0, + XtNhighlightThickness, 1, + XtNradioData, act == FILE_PRINT ? PRINT_ALL : SAVE_ALL, + XtNstate, True, /* enable this button by default */ + XtNtranslations, xlats, + XtNaccelerators, accels2, + /* XtNvertDistance, 0, */ + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + if (act == FILE_PRINT) + XtAddCallback(range_all_radio[act], XtNcallback, cb_range, (XtPointer)PRINT_ALL); + else + XtAddCallback(range_all_radio[act], XtNcallback, cb_range, (XtPointer)SAVE_ALL); + XtInstallAccelerators(r6form, range_all_radio[act]); + + r61form = XtVaCreateManagedWidget("range_marked_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNfromVert, r6form, + /* XtNvertDistance, 0, */ + HORIZONTAL_RESIZING_NO, + NULL); + + range_marked_radio[act] = XtVaCreateManagedWidget("range_marked", +#ifdef XAW + radioWidgetClass, +#else + toggleWidgetClass, +#endif + + r61form, + XtNlabel, "Marked ", + XtNborderWidth, 0, + XtNhighlightThickness, 1, + XtNradioGroup, range_all_radio[act], + XtNradioData, act == FILE_PRINT ? PRINT_MARKED : SAVE_MARKED, + XtNtranslations, xlats, + XtNaccelerators, accels2, + /* XtNvertDistance, 0, */ + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + if (act == FILE_PRINT) + XtAddCallback(range_marked_radio[act], XtNcallback, cb_range, (XtPointer)PRINT_RANGE); + else + XtAddCallback(range_marked_radio[act], XtNcallback, cb_range, (XtPointer)SAVE_RANGE); + XtInstallAccelerators(r61form, range_marked_radio[act]); + + r7form = XtVaCreateManagedWidget("range_from_to_form", formWidgetClass, + form, + XtNborderWidth, 0, + XtNfromVert, r61form, + /* XtNvertDistance, 0, */ + XtNresizable, True, + /* HORIZONTAL_RESIZING_NO, */ + NULL); + + range_from_to_radio[act] = XtVaCreateManagedWidget("range_from_to", +#ifdef XAW + radioWidgetClass, +#else + toggleWidgetClass, +#endif + r7form, + XtNlabel, "From: ", + XtNborderWidth, 0, + XtNhighlightThickness, 1, + XtNradioGroup, range_all_radio[act], + XtNradioData, act == FILE_PRINT ? PRINT_RANGE : SAVE_RANGE, + XtNtranslations, xlats, + XtNaccelerators, accels2, + /* XtNvertDistance, 0, */ + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + if (act == FILE_PRINT) + XtAddCallback(range_from_to_radio[act], XtNcallback, cb_range, (XtPointer)PRINT_RANGE); + else + XtAddCallback(range_from_to_radio[act], XtNcallback, cb_range, (XtPointer)SAVE_RANGE); + XtInstallAccelerators(r7form, range_from_to_radio[act]); + + page_from_text[act] = XtVaCreateManagedWidget("range_from", asciiTextWidgetClass, + r7form, + XtNdataCompression, False, + XtNeditType, XawtextEdit, + XtNwidth, 50, + XtNfromHoriz, range_from_to_radio[act], + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + XtOverrideTranslations(page_from_text[act], xlats2); + XtAddEventHandler(page_from_text[act], KeyPressMask | ButtonPressMask, False, + xaw_range_handle_key, (XtPointer)act); + + to_label[act] = XtVaCreateManagedWidget("range_to_lab", labelWidgetClass, + r7form, + XtNlabel, "to: ", + XtNborderWidth, 0, + XtNfromHoriz, page_from_text[act], + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + + page_to_text[act] = XtVaCreateManagedWidget("range_to", asciiTextWidgetClass, + r7form, + XtNdataCompression, False, + XtNeditType, XawtextEdit, + XtNwidth, 50, + XtNfromHoriz, to_label[act], + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, + NULL); + XtOverrideTranslations(page_to_text[act], xlats2); + XtAddEventHandler(page_to_text[act], KeyPressMask | ButtonPressMask, False, + xaw_range_handle_key, (XtPointer)act); + + of_label[act] = XtVaCreateManagedWidget("range_of", labelWidgetClass, + r7form, + XtNlabel, ofstring, + XtNborderWidth, 0, + XtNresizable, True, + XtNfromHoriz, page_to_text[act], + /* HORIZONTAL_RESIZING_NO, */ + XtNleft, XtChainLeft, + VERTICAL_RESIZING_NO, + NULL); + + adjust_vertically(range_from_to_radio[act], page_from_text[act], ddist); + adjust_vertically(to_label[act], page_from_text[act], ddist); + adjust_vertically(of_label[act], page_from_text[act], ddist); + + /* box for the OK/Cancel button */ + box = XtVaCreateManagedWidget("box", formWidgetClass, + paned, + /* resizing by user isn't needed */ + XtNshowGrip, False, + XtNdefaultDistance, 6, /* some padding */ + /* resizing the window shouldn't influence this box, + * but only the pane widget + */ + XtNskipAdjust, True, + XtNaccelerators, G_accels_cr, + NULL); + + ok_button[act] = XtVaCreateManagedWidget(act == FILE_PRINT ? "print_button" : "save_button", + commandWidgetClass, box, + XtNlabel, act == FILE_PRINT ? "Print" : "Save", + XtNaccelerators, G_accels_cr, + XtNtop, XtChainTop, + XtNbottom, XtChainBottom, + HORIZONTAL_RESIZING_NO, + NULL); + if (act == FILE_PRINT) + XtAddCallback(ok_button[act], XtNcallback, cb_print_or_save, (XtPointer)info); + else + XtAddCallback(ok_button[act], XtNcallback, cb_print_or_save, (XtPointer)info); + + XtInstallAccelerators(form, ok_button[act]); + if (act == FILE_PRINT) + XtInstallAccelerators(print_to_printer_text, ok_button[act]); + XtInstallAccelerators(print_to_file_text[act], ok_button[act]); + + cancel_button[act] = XtVaCreateManagedWidget("cancel", commandWidgetClass, + box, + XtNlabel, "Cancel", + XtNfromHoriz, ok_button[act], + XtNbottom, XtChainBottom, + XtNjustify, XtJustifyRight, + XtNleft, XtChainRight, + XtNright, XtChainRight, + NULL); + if (act == FILE_PRINT) + XtAddCallback(cancel_button[act], XtNcallback, cb_print_cancel, (XtPointer)info); + else + XtAddCallback(cancel_button[act], XtNcallback, cb_save_cancel, (XtPointer)info); + + XtManageChild(top_level_shell); + center_window(top_level_shell, globals.widgets.top_level); + XtMapWidget(top_level_shell); + XSetWMProtocols(XtDisplay(top_level_shell), XtWindow(top_level_shell), &WM_DELETE_WINDOW, 1); + + if (pageinfo_have_marked_pages()) { + XawToggleSetCurrent(range_all_radio[act], + act == FILE_PRINT ? (XtPointer)PRINT_MARKED : (XtPointer)SAVE_MARKED); + } + else if ((act == FILE_PRINT && save_pr_info.range_radio == PRINT_MARKED) + || (act == FILE_SAVE && save_save_info.range_radio == SAVE_MARKED)) { + XawToggleSetCurrent(range_all_radio[act], + act == FILE_PRINT ? (XtPointer)PRINT_ALL : (XtPointer)SAVE_ALL); + } + +#else /* not MOTIF */ + Widget form, pane, box; + Widget frame1, f1label, f1child; + Widget r4label; + Widget frame2, f2label, f2child; + XmString str; + XtTranslations xlats; + + XtAddActions(print_actions, XtNumber(print_actions)); + + if (act == FILE_SAVE) { + char *ptr = get_string_va("#override \n<Key>osfCancel:WM_save_cancel(%p)", info); + xlats = XtParseTranslationTable(ptr); + free(ptr); + } + else { + char *ptr = get_string_va("#override \n<Key>osfCancel:WM_print_cancel(%p)", info); + xlats = XtParseTranslationTable(ptr); + free(ptr); + } + + top_level_shell = XtVaCreatePopupShell(act == FILE_SAVE ? "save_popup" : "print_popup", + xmDialogShellWidgetClass, globals.widgets.top_level, + XmNtitle, act == FILE_SAVE ? "Save file" : "Print DVI file", + XmNallowShellResize, True, + XmNdeleteResponse, XmDO_NOTHING, /* we'll take care of that ourselves */ + XmNmappedWhenManaged, False, /* so that we can center it first */ + NULL); + + /* make the window manager destroy action just pop down the dialog */ + WM_DELETE_WINDOW = XmInternAtom(XtDisplay(top_level_shell), "WM_DELETE_WINDOW", False); + if (act == FILE_SAVE) + XmAddWMProtocolCallback(top_level_shell, WM_DELETE_WINDOW, cb_save_cancel, (XtPointer)info); + else + XmAddWMProtocolCallback(top_level_shell, WM_DELETE_WINDOW, cb_print_cancel, (XtPointer)info); + + + pane = XtVaCreateWidget(act == FILE_SAVE ? "save_paned" : "print_paned", + xmPanedWindowWidgetClass, top_level_shell, + /* make sashes invisible */ + XmNsashWidth, 1, + XmNsashHeight, 1, + /* turn separator off, since it gives visual noise with the frames */ + XmNseparatorOn, False, + NULL); + + + form = XtVaCreateWidget("form", xmFormWidgetClass, + pane, + XmNhorizontalSpacing, DDIST_MAJOR, + XmNverticalSpacing, DDIST_MAJOR, + XmNautoUnmanage, False, + XTranslations, xlats, + NULL); + + if (act == FILE_PRINT) { + /* First frame: print to printer or file */ + + frame1 = XtVaCreateWidget("print_to_frame", xmFrameWidgetClass, form, + XmNmarginWidth, DDIST, + XmNmarginHeight, DDIST, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XTranslations, xlats, + NULL); + + str = XmStringCreateLocalized("Print to:"); + f1label = XtVaCreateManagedWidget("title", xmLabelGadgetClass, + frame1, + XmNchildType, XmFRAME_TITLE_CHILD, + XmNlabelString, str, + NULL); + XmStringFree(str); + + f1child = XtVaCreateWidget("form", xmFormWidgetClass, frame1, + XmNhorizontalSpacing, DDIST, + XmNverticalSpacing, DDIST, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XTranslations, xlats, + NULL); + + str = XmStringCreateLocalized("Printer:"); + to_printer_radio = XtVaCreateManagedWidget("to_printer", + xmToggleButtonGadgetClass, f1child, + XmNlabelString, str, + XmNindicatorType, XmONE_OF_MANY, + XmNset, resource.default_printing_target == PRINT_TO_PRINTER, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 0, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 0, + NULL); + XmStringFree(str); + XtAddCallback(to_printer_radio, XmNvalueChangedCallback, cb_print_vs_file, (XtPointer)1); + + XtOverrideTranslations(to_printer_radio, xlats); + + print_to_printer_text = XtVaCreateManagedWidget("print_text", xmTextFieldWidgetClass, + f1child, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 0, + XmNleftAttachment, XmATTACH_WIDGET, + XmNrightAttachment, XmATTACH_FORM, + XmNleftWidget, to_printer_radio, + XTranslations, xlats, + NULL); + XtAddCallback(print_to_printer_text, XmNactivateCallback, cb_print_or_save, info); + + adjust_heights(to_printer_radio, print_to_printer_text, NULL); + + str = XmStringCreateLocalized("File:"); + to_file_radio_or_label[act] = XtVaCreateManagedWidget("to_file", xmToggleButtonGadgetClass, + f1child, + XmNlabelString, str, + XmNindicatorType, XmONE_OF_MANY, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, print_to_printer_text, + XmNleftAttachment, XmATTACH_FORM, + XmNset, resource.default_printing_target == PRINT_TO_FILE, + XmNleftOffset, 0, + NULL); + XmStringFree(str); + XtAddCallback(to_file_radio_or_label[act], XmNvalueChangedCallback, cb_print_vs_file, (XtPointer)2); + + str = XmStringCreateLocalized("Browse ..."); + print_to_file_button[act] = XtVaCreateManagedWidget("file_button", xmPushButtonWidgetClass, + f1child, + XmNlabelString, str, + XmNsensitive, resource.default_printing_target == PRINT_TO_FILE, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, print_to_printer_text, + XmNrightAttachment, XmATTACH_FORM, + NULL); + XmStringFree(str); + + XtOverrideTranslations(to_file_radio_or_label[act], xlats); + XtOverrideTranslations(print_to_file_button[act], xlats); + + print_to_file_text[act] = XtVaCreateManagedWidget("file_text", xmTextFieldWidgetClass, + f1child, + XmNsensitive, resource.default_printing_target == PRINT_TO_FILE, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, print_to_printer_text, + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightWidget, print_to_file_button[act], + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, to_file_radio_or_label[act], + XTranslations, xlats, + NULL); + + adjust_heights(to_file_radio_or_label[act], print_to_file_button[act], print_to_file_text[act], NULL); + + XtAddCallback(print_to_file_text[act], XmNactivateCallback, cb_print_or_save, (XtPointer)info); + XtAddCallback(print_to_file_button[act], XmNactivateCallback, cb_browse, (XtPointer)info); + + XtManageChild(f1child); + XtManageChild(frame1); + + } /* saving, not printing */ + else { + frame1 = XtVaCreateWidget("save_as_frame", xmFrameWidgetClass, + form, + XmNmarginWidth, DDIST, + XmNmarginHeight, DDIST, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + + str = XmStringCreateLocalized("Save as:"); + f1label = XtVaCreateManagedWidget("title", xmLabelGadgetClass, + frame1, + XmNchildType, XmFRAME_TITLE_CHILD, + XmNlabelString, str, + NULL); + XmStringFree(str); + + f1child = XtVaCreateWidget("form", xmFormWidgetClass, frame1, + XmNhorizontalSpacing, DDIST, + XmNverticalSpacing, DDIST, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XTranslations, xlats, + NULL); +/* fprintf(stderr, "CHILD: 0x%x\n", (long)f1child); */ + str = XmStringCreateLocalized("Format:"); + format_selection_texts[0] = XmStringCreateLocalized((char *)output_format_mapping[0].fmt_string); + format_selection_texts[1] = XmStringCreateLocalized((char *)output_format_mapping[1].fmt_string); + format_selection_texts[2] = XmStringCreateLocalized((char *)output_format_mapping[2].fmt_string); + format_selection_texts[3] = XmStringCreateLocalized((char *)output_format_mapping[3].fmt_string); + format_selection_texts[4] = XmStringCreateLocalized((char *)output_format_mapping[4].fmt_string); + format_selection_option + = XmVaCreateSimpleOptionMenu(f1child, "format_selection_option", + str, 'F', + resource.default_saving_format, /*initial menu selection*/ + select_format_cb, /* callback */ + XmVaPUSHBUTTON, format_selection_texts[0], 'P', NULL, NULL, + XmVaPUSHBUTTON, format_selection_texts[1], 'F', NULL, NULL, + XmVaPUSHBUTTON, format_selection_texts[2], 'D', NULL, NULL, + XmVaPUSHBUTTON, format_selection_texts[3], 'T', NULL, NULL, + XmVaPUSHBUTTON, format_selection_texts[4], 'U', NULL, NULL, + NULL); + + XmStringFree(str); + XmStringFree(format_selection_texts[0]); + XmStringFree(format_selection_texts[1]); + XmStringFree(format_selection_texts[2]); + XmStringFree(format_selection_texts[3]); + XmStringFree(format_selection_texts[4]); + + str = XmStringCreateLocalized("File name:"); + to_file_radio_or_label[act] = XtVaCreateManagedWidget("to_file", xmLabelGadgetClass, + f1child, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, format_selection_option, + XmNleftAttachment, XmATTACH_FORM, + /* XmNchildType, XmFRAME_TITLE_CHILD, */ + XmNlabelString, str, + NULL); + XmStringFree(str); + str = XmStringCreateLocalized("Browse ..."); + print_to_file_button[act] = XtVaCreateManagedWidget("file_button", xmPushButtonWidgetClass, + f1child, + XmNlabelString, str, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, format_selection_option, + XmNrightAttachment, XmATTACH_FORM, + XTranslations, xlats, + NULL); + print_to_file_text[act] = XtVaCreateManagedWidget("file_text", xmTextFieldWidgetClass, + f1child, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, format_selection_option, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, to_file_radio_or_label[act], + XmNrightAttachment, XmATTACH_WIDGET, + XmNrightWidget, print_to_file_button[act], + XTranslations, xlats, + NULL); + + adjust_heights(to_file_radio_or_label[act], print_to_file_button[act], print_to_file_text[act], NULL); + XtAddCallback(print_to_file_button[act], XmNactivateCallback, cb_browse, (XtPointer)info); + } + +#if 1 + { /* align left edges of widgets */ + Dimension w1, w2; + + XtVaGetValues(to_file_radio_or_label[act], XmNwidth, &w2, NULL); + if (act == FILE_PRINT) + XtVaGetValues(to_printer_radio, XmNwidth, &w1, NULL); + else { + Widget w; + if (get_widget_by_name(&w, format_selection_option, "OptionLabel", True)) { + XtVaGetValues(w, XmNwidth, &w1, NULL); + } + else { + w1 = w2; + } + } + + if (w1 > w2) { + Dimension offset = DDIST; + offset += w1 - w2; + XtVaSetValues(print_to_file_text[act], XmNleftOffset, offset, NULL); + } + else if (w2 > w1) { + Dimension offset = DDIST; + offset += w2 - w1; + if (act == FILE_PRINT) + XtVaSetValues(print_to_printer_text, XmNleftOffset, offset, NULL); + else { + Widget w; + if (get_widget_by_name(&w, format_selection_option, "OptionLabel", True)) { + /* FIXME: Setting width would be cleaner, but it doesn't work ...? + Dimension curr_w; + XtVaGetValues(w, XmNwidth, &curr_w, NULL); + XtVaSetValues(w, XmNwidth, curr_w + offset, NULL); + */ + /* fprintf(stderr, "Setting width from %d to: %d\n", curr_w, curr_w + offset); */ + XtVaSetValues(w, + XmNmarginRight, offset, + XmNalignment, XmALIGNMENT_BEGINNING, + NULL); + } + + } + } + } +#endif /* 0 */ + + if (act == FILE_SAVE) { + XtManageChild(format_selection_option); + XtManageChild(f1child); + XtManageChild(frame1); + } + + /* additional dvips options */ + str = XmStringCreateLocalized("Dvips Options:"); + r4label = XtVaCreateManagedWidget("dvips_options_name", xmLabelGadgetClass, + form, + XmNlabelString, str, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, frame1, + XmNleftAttachment, XmATTACH_FORM, + NULL); + XmStringFree(str); + + dvips_options_text[act] = XtVaCreateManagedWidget("dvips_options_text", xmTextFieldWidgetClass, + form, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, frame1, + XmNleftAttachment, XmATTACH_WIDGET, + XmNrightAttachment, XmATTACH_FORM, + XmNleftWidget, r4label, + XmNcolumns, 20, + XTranslations, xlats, + NULL); + XtAddCallback(dvips_options_text[act], XmNactivateCallback, cb_print_or_save, (XtPointer)info); + adjust_heights(r4label, dvips_options_text[act], NULL); + + /* page selection */ + frame2 = XtVaCreateWidget(act == FILE_PRINT ? "print_page_frame" : "save_page_frame", xmFrameWidgetClass, + form, + XmNmarginWidth, DDIST, + XmNmarginHeight, DDIST, + XmNresizable, True, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, dvips_options_text[act], + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XTranslations, xlats, + NULL); + + str = XmStringCreateLocalized("Pages:"); + f2label = XtVaCreateManagedWidget("title", xmLabelGadgetClass, + frame2, + XmNchildType, XmFRAME_TITLE_CHILD, + XmNlabelString, str, + NULL); + XmStringFree(str); + + f2child = XtVaCreateWidget("form", xmFormWidgetClass, frame2, + XmNhorizontalSpacing, DDIST, + XmNverticalSpacing, DDIST, + XmNresizable, True, + XTranslations, xlats, + XTranslations, xlats, + NULL); + + str = XmStringCreateLocalized("All"); + range_all_radio[act] = XtVaCreateManagedWidget("all", + xmToggleButtonGadgetClass, f2child, + XmNlabelString, str, + XmNindicatorType, XmONE_OF_MANY, + XmNset, True, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 0, + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 0, + XTranslations, xlats, + NULL); + XmStringFree(str); + if (act == FILE_PRINT) { + XtAddCallback(range_all_radio[act], XmNvalueChangedCallback, cb_range, (XtPointer)PRINT_ALL); + } + else { + XtAddCallback(range_all_radio[act], XmNvalueChangedCallback, cb_range, (XtPointer)SAVE_ALL); + } + + str = XmStringCreateLocalized("Marked"); + range_marked_radio[act] = XtVaCreateManagedWidget("marked", + xmToggleButtonGadgetClass, f2child, + XmNlabelString, str, + XmNindicatorType, XmONE_OF_MANY, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_all_radio[act], + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 0, + XTranslations, xlats, + NULL); + XmStringFree(str); + if (act == FILE_PRINT) { + XtAddCallback(range_marked_radio[act], XmNvalueChangedCallback, cb_range, (XtPointer)PRINT_MARKED); + } + else { + XtAddCallback(range_marked_radio[act], XmNvalueChangedCallback, cb_range, (XtPointer)SAVE_MARKED); + } + + str = XmStringCreateLocalized("Range:"); + range_from_to_radio[act] = XtVaCreateManagedWidget("range", + xmToggleButtonGadgetClass, f2child, + XmNlabelString, str, + XmNindicatorType, XmONE_OF_MANY, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_marked_radio[act], + XmNleftAttachment, XmATTACH_FORM, + XmNleftOffset, 0, + XTranslations, xlats, + NULL); + XmStringFree(str); + + if (act == FILE_PRINT) { + XtAddCallback(range_from_to_radio[act], XmNvalueChangedCallback, cb_range, (XtPointer)PRINT_RANGE); + } + else { + XtAddCallback(range_from_to_radio[act], XmNvalueChangedCallback, cb_range, (XtPointer)SAVE_RANGE); + } + str = XmStringCreateLocalized("From"); + from_label[act] = XtVaCreateManagedWidget("from", xmLabelGadgetClass, + f2child, + XmNlabelString, str, + XmNsensitive, False, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_marked_radio[act], + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, range_from_to_radio[act], + NULL); + XmStringFree(str); + + page_from_text[act] = XtVaCreateManagedWidget("from_page", + xmTextFieldWidgetClass, f2child, + XmNcolumns, 5, + XmNsensitive, False, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_marked_radio[act], + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, from_label[act], + XTranslations, xlats, + NULL); + XtAddCallback(page_from_text[act], XmNactivateCallback, cb_print_or_save, (XtPointer)info); + + str = XmStringCreateLocalized("to"); + to_label[act] = XtVaCreateManagedWidget("to", xmLabelGadgetClass, + f2child, + XmNlabelString, str, + XmNsensitive, False, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_marked_radio[act], + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, page_from_text[act], + NULL); + XmStringFree(str); + + page_to_text[act] = XtVaCreateManagedWidget("to_page", xmTextFieldWidgetClass, + f2child, + XmNcolumns, 5, + XmNsensitive, False, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_marked_radio[act], + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, to_label[act], + XTranslations, xlats, + NULL); + XtAddCallback(page_to_text[act], XmNactivateCallback, cb_print_or_save, (XtPointer)info); + + str = XmStringCreateLocalized(ofstring); + of_label[act] = XtVaCreateManagedWidget("of", xmLabelGadgetClass, + f2child, + XmNlabelString, str, + XmNsensitive, False, + XmNresizable, True, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, range_marked_radio[act], + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, page_to_text[act], + NULL); + XmStringFree(str); + + adjust_heights(range_from_to_radio[act], + from_label[act], page_from_text[act], + to_label[act], page_to_text[act], + of_label[act], + NULL); + + XtManageChild(f2child); + XtManageChild(frame2); + + /* box for the OK/Cancel button */ + box = XtVaCreateManagedWidget("box", xmFormWidgetClass, + pane, + XmNskipAdjust, True, /* don't resize this area */ + XTranslations, xlats, + NULL); + + if (act == FILE_PRINT) + str = XmStringCreateLocalized("Print"); + else + str = XmStringCreateLocalized("Save"); + ok_button[act] = XtVaCreateManagedWidget(act == FILE_PRINT ? "print_button" : "save_button", + xmPushButtonWidgetClass, box, + XmNlabelString, str, + XmNshowAsDefault, True, + XmNdefaultButtonShadowThickness, 1, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + /* to mimick appearance of native dialog buttons: */ + XmNmarginWidth, 6, + XmNmarginHeight, 4, + XmNtopOffset, 10, + XmNbottomOffset, 10, + XmNleftOffset, 10, + NULL); + XmStringFree(str); + if (act == FILE_PRINT) + XtAddCallback(ok_button[act], XmNactivateCallback, cb_print_or_save, (XtPointer)info); + else + XtAddCallback(ok_button[act], XmNactivateCallback, cb_print_or_save, (XtPointer)info); + + XtOverrideTranslations(ok_button[act], XtParseTranslationTable("<Key>Return:ArmAndActivate()")); + + str = XmStringCreateLocalized("Cancel"); + cancel_button[act] = XtVaCreateManagedWidget("cancel", + xmPushButtonWidgetClass, box, + XmNlabelString, str, + XmNdefaultButtonShadowThickness, 1, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + /* to mimick appearance of native dialog buttons: */ + XmNmarginWidth, 6, + XmNmarginHeight, 4, + XmNtopOffset, 10, + XmNbottomOffset, 10, + XmNrightOffset, 10, + NULL); + XmStringFree(str); + + XtOverrideTranslations(range_all_radio[act], xlats); + XtOverrideTranslations(range_marked_radio[act], xlats); + XtOverrideTranslations(range_from_to_radio[act], xlats); + XtOverrideTranslations(ok_button[act], xlats); + XtOverrideTranslations(cancel_button[act], xlats); + + if (act == FILE_PRINT) + XtAddCallback(cancel_button[act], XmNactivateCallback, cb_print_cancel, (XtPointer)info); + else + XtAddCallback(cancel_button[act], XmNactivateCallback, cb_save_cancel, (XtPointer)info); + + { /* make the buttons the same size: */ + Dimension w1, w2; + XtVaGetValues(ok_button[act], XtNwidth, &w1, NULL); + XtVaGetValues(cancel_button[act], XtNwidth, &w2, NULL); + if (w1 < w2) + XtVaSetValues(ok_button[act], XtNwidth, w2, NULL); + else if (w2 > w1) + XtVaSetValues(cancel_button[act], XtNwidth, w1, NULL); + } + + if (pageinfo_have_marked_pages()) { + XmToggleButtonGadgetSetState(range_marked_radio[act], True, True); + } + else if (save_pr_info.range_radio == PRINT_MARKED) { + XmToggleButtonGadgetSetState(range_all_radio[act], True, True); + } + + XtManageChild(form); + XtManageChild(pane); + center_window(top_level_shell, globals.widgets.top_level); + XtMapWidget(top_level_shell); + XmProcessTraversal(ok_button[act], XmTRAVERSE_CURRENT); +#endif /* not MOTIF */ + + /* set default output format */ + save_save_info.output_format = curr_save_info.output_format = + output_format_mapping[resource.default_saving_format].fmt; + + if (act == FILE_SAVE) + update_dvips_options_sensitivity(resource.default_saving_format, top_level_shell); + + return top_level_shell; +} +#undef HORIZONTAL_RESIZING_NO +#undef HORIZONTAL_RESIZING_YES +#undef VERTICAL_RESIZING_NO + + +static void +set_target_radio(struct dialog_info *save_info, struct dialog_info *curr_info, printOrSaveActionT act) +{ +#ifdef MOTIF + if (save_info->print_radio > 0 && save_info->print_radio != curr_info->print_radio) { + XmToggleButtonGadgetSetState(save_info->print_radio == PRINT_TO_PRINTER + ? to_printer_radio + : to_file_radio_or_label[act], True, True); + } +#else /* MOTIF */ + UNUSED(act); + UNUSED(curr_info); + XawToggleSetCurrent(to_printer_radio, (XtPointer)save_info->print_radio); +#endif /* MOTIF */ +} + +static void +set_range_radio(struct dialog_info *save_info, struct dialog_info *curr_info, printOrSaveActionT act) +{ +#ifdef MOTIF + if (save_info->range_radio > 0 && save_info->range_radio != curr_info->range_radio) { + Widget selected = 0; + switch (save_info->range_radio) { + case PRINT_ALL: + case SAVE_ALL: + selected = range_all_radio[act]; + break; + case PRINT_MARKED: + case SAVE_MARKED: + selected = range_marked_radio[act]; + break; + case PRINT_RANGE: + case SAVE_RANGE: + selected = range_from_to_radio[act]; + break; + default: + ASSERT(0, "wrong button type in set_range_radio()"); + } + XmToggleButtonGadgetSetState(selected, True, True); + } +#else /* MOTIF */ + UNUSED(curr_info); + XawToggleSetCurrent(range_all_radio[act], (XtPointer)save_info->range_radio); +#endif /* MOTIF */ +} + +void +save_or_print_callback(struct save_or_print_info *info) +{ + printOrSaveActionT act = info->act; + static char ofstring[1024]; /* should be ample */ + struct dialog_info *save_info = NULL, *curr_info = NULL; + + if (act == FILE_PRINT) { + save_info = &save_pr_info; + curr_info = &curr_pr_info; + if (print_is_active) { + XBell(DISP, 0); + XRaiseWindow(DISP, XtWindow(print_shell)); + return; + } + + if (printlog_raise_active()) { + XBell(DISP, 0); + return; + } + } + else if (act == FILE_SAVE) { + save_info = &save_save_info; + curr_info = &curr_save_info; + if (save_is_active) { + XBell(DISP, 0); + XRaiseWindow(DISP, XtWindow(save_shell)); + return; + } + } + else { + ASSERT(0, "wrong action type in save_or_print_callback()"); + } + + if (globals.dvi_file.bak_fp == NULL) { + popup_message(globals.widgets.top_level, + MSG_ERR, + NULL, + "Empty or incomplete DVI file. " + "Please select a new DVI file via File -> Open."); + return; + } + + if (globals.pageno_correct == 1) + sprintf(ofstring, "of %d physical pages", total_pages); + else + sprintf(ofstring, "of %d to %d pages", globals.pageno_correct, total_pages + globals.pageno_correct - 1); + + if (act == FILE_PRINT && print_shell == NULL) { + curr_info->print_radio = resource.default_printing_target; + print_shell = create_print_or_save_window(info, ofstring); +#ifdef MOTIF + set_sensitivity(resource.default_printing_target); +#endif + } + else if (act == FILE_SAVE && save_shell == NULL) + save_shell = create_print_or_save_window(info, ofstring); + else { /* if the window was already created */ +#ifdef MOTIF + XmString str; +#endif + /* XXX: is this actually needed??? */ + /* XXX: To test, remove the following */ + if (!pageinfo_have_marked_pages()) { + if (act == FILE_PRINT && save_pr_info.range_radio == PRINT_MARKED) { + save_pr_info.range_radio = PRINT_ALL; + } + else if (act == FILE_SAVE && save_save_info.range_radio == SAVE_MARKED) { + save_save_info.range_radio = SAVE_ALL; + } + } + + if (act == FILE_PRINT) + set_target_radio(save_info, curr_info, act); + set_range_radio(save_info, curr_info, act); +#ifdef MOTIF + str = XmStringCreateLocalized(ofstring); + XtVaSetValues(of_label[act], XmNlabelString, str, NULL); + XmStringFree(str); + + /* FIXME: this seems neccessary, otherwise labels are misaligned + again if window is closed and opened a second time? */ + adjust_heights(range_from_to_radio[act], + from_label[act], page_from_text[act], + to_label[act], page_to_text[act], + of_label[act], + NULL); + + if (save_info->dvips_options != NULL) { + XtVaSetValues(dvips_options_text[act], XmNvalue, save_info->dvips_options, + XmNcursorPosition, strlen(save_info->dvips_options), NULL); + } + else { + XtVaSetValues(dvips_options_text[act], XmNvalue, "", NULL); + } +#else /* MOTIF */ + XtVaSetValues(of_label[act], XtNlabel, ofstring, NULL); + + if (save_info->dvips_options != NULL) { + XtVaSetValues(dvips_options_text[act], XtNstring, save_info->dvips_options, NULL); + XawTextSetInsertionPoint(dvips_options_text[act], strlen(save_info->dvips_options)); + } + else { + XtVaSetValues(dvips_options_text[act], XtNstring, "", NULL); + } +#endif /* MOTIF */ + } + + get_initial_dialog_values(save_info, act); + +#ifdef MOTIF + if (act == FILE_PRINT) + XtVaSetValues(print_to_printer_text, XmNvalue, save_info->printer_name, + XmNcursorPosition, strlen(save_info->printer_name), NULL); + + XtVaSetValues(dvips_options_text[act], XmNvalue, save_info->dvips_options, + XmNcursorPosition, strlen(save_info->dvips_options), NULL); + + XtVaSetValues(page_from_text[act], XmNvalue, save_info->from_page, + XmNcursorPosition, strlen(save_info->from_page), NULL); + + XtVaSetValues(page_to_text[act], XmNvalue, save_info->to_page, + XmNcursorPosition, strlen(save_info->to_page), NULL); +#else /* MOTIF */ + if (act == FILE_PRINT) { + XtVaSetValues(print_to_printer_text, XtNstring, save_info->printer_name, NULL); + XawTextSetInsertionPoint(print_to_printer_text, strlen(save_info->printer_name)); + } + + XtVaSetValues(dvips_options_text[act], XtNstring, save_info->dvips_options, NULL); + XawTextSetInsertionPoint(dvips_options_text[act], strlen(save_info->dvips_options)); + + XtVaSetValues(page_from_text[act], XtNstring, save_info->from_page, NULL); + XawTextSetInsertionPoint(page_from_text[act], strlen(save_info->from_page)); + + XtVaSetValues(page_to_text[act], XtNstring, save_info->to_page, NULL); + XawTextSetInsertionPoint(page_to_text[act], strlen(save_info->to_page)); +#endif /* MOTIF */ + + if (act == FILE_PRINT) { + if (pageinfo_have_marked_pages()) { + XtSetSensitive(range_marked_radio[FILE_PRINT], True); + } + else { + XtSetSensitive(range_marked_radio[FILE_PRINT], False); + } + ASSERT(save_pr_info.range_radio != PRINT_MARKED || pageinfo_have_marked_pages(), + "PRINT_MARKED shouldn't be togglable if there are no marked pages!"); + } + else if (act == FILE_SAVE) { + if (pageinfo_have_marked_pages()) { + XtSetSensitive(range_marked_radio[FILE_SAVE], True); + } + else { + XtSetSensitive(range_marked_radio[FILE_SAVE], False); + } + ASSERT(save_save_info.range_radio != SAVE_MARKED || pageinfo_have_marked_pages(), + "SAVE_MARKED shouldn't be togglable if there are no marked pages!"); + } + + set_outfile_name(save_info, &curr_save_info, act); + +#ifdef MOTIF + XtVaSetValues(print_to_file_text[act], XmNvalue, save_info->file_name, + XmNcursorPosition, strlen(save_info->file_name), NULL); +#else /* MOTIF */ + XtVaSetValues(print_to_file_text[act], XtNstring, save_info->file_name, NULL); + XawTextSetInsertionPoint(print_to_file_text[act], strlen(save_info->file_name)); +#endif /* MOTIF */ + + if (act == FILE_PRINT) { + XtPopup(print_shell, XtGrabNone); + print_is_active = True; + } + else { + XtPopup(save_shell, XtGrabNone); + save_is_active = True; + } +} + +static int +getpageno(Widget w) +{ + char *s, *p; + int pageno; +#ifndef MOTIF + XtVaGetValues(w, XtNstring, &s, NULL); +#else /* MOTIF */ + s = XmTextFieldGetString(w); +#endif + p = s; + if (*p == '-') + ++p; + if (!isdigit((int)*p)) { + return 0; + } + do { + ++p; + } while (isdigit((int)*p)); + if (*p != '\0') + return 0; + + pageno = atoi(s) - globals.pageno_correct; +#ifdef MOTIF + XtFree(s); +#endif + return pageno; +} + + +/* + return text value of Widget w in newly allocated memory, + free()ing old_val as appropriate. Returns NULL if + text value starts with '\0'. +*/ +static char * +get_saved_command(char **old_val, Widget w) +{ + char *val = NULL; + + if (*old_val != NULL) { +#if MOTIF + XtFree((char *)*old_val); +#else + free((char*)*old_val); +#endif + *old_val = NULL; + } +#if MOTIF + val = XmTextFieldGetString(w); + if (*val == '\0') { + XtFree((char *)val); + val = NULL; + } +#else + XtVaGetValues(w, XtNstring, &val, NULL); + if (*val == '\0') { + val = NULL; + } + else { + val = xstrdup(val); + } +#endif + return val; +} + +/* fill curr_print_info and save_print_info with current values */ +static void +get_save_window_state(struct dialog_info *save_info, struct dialog_info *curr_info, printOrSaveActionT act) +{ + save_info->print_radio = curr_info->print_radio; + save_info->range_radio = curr_info->range_radio; + + if (act == FILE_PRINT) { + save_info->printer_name = get_saved_command(&(save_info->printer_name), print_to_printer_text); + curr_info->printer_name = get_saved_command(&(curr_info->printer_name), print_to_printer_text); + } + save_info->file_name = get_saved_command(&(save_info->file_name), print_to_file_text[act]); + curr_info->file_name = get_saved_command(&(curr_info->file_name), print_to_file_text[act]); + + save_info->dvips_options = get_saved_command(&(save_info->dvips_options), dvips_options_text[act]); + curr_info->dvips_options = get_saved_command(&(curr_info->dvips_options), dvips_options_text[act]); + + save_info->from_page = get_saved_command(&(save_info->from_page), page_from_text[act]); + save_info->to_page = get_saved_command(&(save_info->to_page), page_to_text[act]); + + TRACE_GUI((stderr, "saved options:\nprinter: |%s|, file: |%s|, dvips: |%s|, from: |%s|, to: |%s|\n", + save_info->printer_name ? save_info->printer_name : "<NULL>", + save_info->file_name ? save_info->file_name : "<NULL>", + save_info->dvips_options ? save_info->dvips_options : "<NULL>", + save_info->from_page ? save_info->from_page : "<NULL>", + save_info->to_page ? save_info->to_page : "<NULL>")); +} + +static void +popdown_dialog_and_print_or_save(XtPointer myinfo) +{ + struct save_or_print_info *info = (struct save_or_print_info *)myinfo; + struct select_pages_info *pinfo = (struct select_pages_info *)info->pinfo; + struct dialog_info *curr_info = NULL; + + /* pop down the dialog */ + if (pinfo->act == FILE_PRINT) { + curr_info = &save_pr_info; + cb_print_cancel(NULL, info, NULL); + /* when printing to file, set ps_out.fname to non-NULL; this will + notify called routines that printing should go to the file */ + if (curr_info->print_radio == PRINT_TO_FILE) { + pinfo->finfo->ps_out.fname = xstrdup(curr_info->expanded_filename); + } + } + else { + curr_info = &save_save_info; + cb_save_cancel(NULL, info, NULL); + } + + if (globals.dvi_file.bak_fp == NULL) { /* shouldn't happen */ + info->message_popup = popup_message(globals.widgets.top_level, + MSG_ERR, NULL, + "No active DVI file"); + return; + } + + ASSERT(pinfo->finfo->dvi_in.fp != NULL, "DVI input FILE * must have been set!"); + + /* when saving, set the final file names */ + if (curr_info->range_radio == SAVE_RANGE + || curr_info->range_radio == SAVE_MARKED + || curr_info->range_radio == SAVE_ALL) { + switch (curr_info->output_format) { + case FMT_DVI: + pinfo->finfo->dvi_out.fname = xstrdup(curr_info->expanded_filename); + TRACE_GUI((stderr, "DVI out_name: |%s|", pinfo->finfo->dvi_out.fname)); + break; + case FMT_PS: + pinfo->finfo->ps_out.fname = xstrdup(curr_info->expanded_filename); + TRACE_GUI((stderr, "PS out_name: |%s|", pinfo->finfo->ps_out.fname)); + break; + case FMT_PS2PDF: + pinfo->finfo->pdf_out.fname = xstrdup(curr_info->expanded_filename); + TRACE_GUI((stderr, "PDF out_name: |%s|", pinfo->finfo->pdf_out.fname)); + break; + case FMT_ISO_8859_1: + case FMT_UTF8: + pinfo->finfo->txt_out.fname = xstrdup(curr_info->expanded_filename); + TRACE_GUI((stderr, "TXT out_name: |%s|", pinfo->finfo->txt_out.fname)); + break; + case FMT_NONE: + break; + } + } + + /* add info about page ranges */ + switch (curr_info->range_radio) { + case SAVE_RANGE: + case PRINT_RANGE: + /* convert from 1-based to 0-based */ + pinfo->from = strtoul(curr_info->from_page, (char **)NULL, 10) - 1; + pinfo->to = strtoul(curr_info->to_page, (char **)NULL, 10) - 1; + pinfo->callback = check_pagerange; + break; + case SAVE_MARKED: + case PRINT_MARKED: + pinfo->callback = check_marked; + break; + case SAVE_ALL: + case PRINT_ALL: + pinfo->callback = NULL; + break; + case NO_PAGE_VAL: + ASSERT(0, "Shouldn't happen: NO_PAGE_VAL passed to popdown_dialog_and_print_or_save()"); + break; + } + + store_preference(NULL, "dvipsOptionsString", "%s", save_pr_info.dvips_options ? save_pr_info.dvips_options : ""); + if (pinfo->act == FILE_PRINT) { + store_preference(NULL, "defaultPrintingTarget", "%d", save_pr_info.print_radio); + store_preference(NULL, "dvipsPrinterString", "%s", save_pr_info.printer_name ? save_pr_info.printer_name : ""); + internal_print(pinfo); + } + else { + store_preference(NULL, "defaultSavingFormat", "%d", save_save_info.output_format); + internal_save(pinfo, curr_info->output_format); + } +} + +/* Clean up after user has aborted printing/saving */ +static void +do_cleanup(XtPointer arg) +{ + struct save_or_print_info *info = (struct save_or_print_info *)arg; + struct select_pages_info *pinfo = (struct select_pages_info *)info->pinfo; + struct file_info *finfo = pinfo->finfo; + + cancel_saving(info); + unlink(finfo->dvi_tmp.fname); +} + +/* XXX: is the save_* stuff actually *needed*??? */ +static Boolean +validate_and_save_values(struct save_or_print_info *info) +{ + int page_range_begin, page_range_end; + printOrSaveActionT act = info->act; + + if ((act == FILE_PRINT && curr_pr_info.range_radio == PRINT_RANGE) + || (act == FILE_SAVE && curr_save_info.range_radio == SAVE_RANGE)) { + page_range_begin = getpageno(page_from_text[act]); + page_range_end = getpageno(page_to_text[act]); + if (page_range_begin + 1 < 1) { + info->message_popup = + popup_message(act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, + "Please specify a valid page range.", + "Invalid page range: start (%d) < 1.", + page_range_begin + 1); + return False; + } + else if (page_range_begin > page_range_end) { + info->message_popup = + popup_message(act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, + "Please specify a valid page range.", + "Invalid page range: start (%d) > end (%d).", + page_range_begin + 1, page_range_end + 1); + return False; + } + else if (page_range_end + 1 > total_pages) { + info->message_popup = + popup_message(act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, + "Please specify a valid page range.", + "Invalid page range: end (%d) > total_pages (%d).", + page_range_end + 1, total_pages); + return False; + } + + if (act == FILE_PRINT) { + curr_pr_info.from_page = xrealloc(curr_pr_info.from_page, LENGTH_OF_INT + 1); + curr_pr_info.to_page = xrealloc(curr_pr_info.to_page, LENGTH_OF_INT + 1); + sprintf(curr_pr_info.from_page, "%d", page_range_begin); + sprintf(curr_pr_info.to_page, "%d", page_range_end); + } + else { + curr_save_info.from_page = xrealloc(curr_save_info.from_page, LENGTH_OF_INT + 1); + curr_save_info.to_page = xrealloc(curr_save_info.to_page, LENGTH_OF_INT + 1); + sprintf(curr_save_info.from_page, "%d", page_range_begin); + sprintf(curr_save_info.to_page, "%d", page_range_end); + } + } + + if (act == FILE_PRINT) + get_save_window_state(&save_pr_info, &curr_pr_info, act); + else + get_save_window_state(&save_save_info, &curr_save_info, act); + + return True; +} + +/* + * Routines for freeing allocated resources in file_info: + * close file pointers, and free file name memory. + */ +static void +free_file_info(struct file_IO *info) +{ + if (info->fp != NULL) { + fclose(info->fp); + info->fp = NULL; + } + free(info->fname); + info->fname = NULL; +} + +static void +reset_file_info(struct file_info *finfo) +{ + free_file_info(&(finfo->dvi_in)); + free_file_info(&(finfo->dvi_tmp)); + free_file_info(&(finfo->dvi_out)); + free_file_info(&(finfo->ps_out)); + free_file_info(&(finfo->pdf_out)); + free_file_info(&(finfo->txt_out)); +} + +/* + First round of sanity checks. Note the use of curr_pr_info here; + this is before the values are saved to save_pr_info. +*/ +static void +print_precheck1(XtPointer myinfo) +{ + /* Initialize structures with defaults. Note: structures are + static, so that they survive between calls, and to make memory + management with callbacks (and all the stuff in print-internal.c) + easier. + */ + struct save_or_print_info *info = (struct save_or_print_info *)myinfo; + printOrSaveActionT act = info->act; + static struct select_pages_info pinfo = { + FILE_ALL, 0, 0, NULL, check_marked, { 0, NULL }, NO_ERROR + }; + static struct file_info finfo = { + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL } + }; + char *ok_button_str = NULL; + FILE *fin = NULL; + + /* Return if there are active popups; otherwise, the print process + may get messed up */ + if (raise_message_windows()) { + XBell(DISP, 0); +/* popup_message(pinfo.act == FILE_PRINT ? print_shell : save_shell, */ +/* MSG_WARN, NULL, */ +/* "Please close other open message windows first!"); */ + return; + } + + /* free all pointers in case we've been called again */ + reset_file_info(&finfo); + + pinfo.finfo= &finfo; /* pass finfo in data field of pinfo to callbacks etc. */ + pinfo.act = act; + info->pinfo = &pinfo; + + /* Validate page ranges, and if they are correct, save them to the + * appropriate save_save_info/save_print_info structure. + * NOTE: From here on, always use the save_* variants to retrieve values! + */ + if (!validate_and_save_values(info)) + return; + + /* We need to create a temporary DVI file containing the selected or all pages + if we want to do one of the following: + - print the marked pages + - save to a DVI file + - print only the marked pages to a PS or a PDF file. + */ + if ((pinfo.act == FILE_PRINT && curr_pr_info.range_radio == PRINT_MARKED) + || (pinfo.act == FILE_SAVE + && (save_save_info.output_format == FMT_DVI + || ((save_save_info.output_format == FMT_PS || save_save_info.output_format == FMT_PS2PDF) + && save_save_info.range_radio == SAVE_MARKED)))) { + /* need to create a temporary DVI file containing the selected pages */ + int tmp_fd = xdvi_temp_fd(&(finfo.dvi_tmp.fname)); /* this allocates finfo.dvi_tmp.fname */ + + if (tmp_fd == -1) { + info->message_popup = + popup_message(pinfo.act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, NULL, + "Couldn't create temporary DVI file for printing: %s", strerror(errno)); + return; + } + /* don't use XFOPEN here, since we don't want to treat an error in opening the file as fatal. */ + /* `b' in mode won't hurt ... */ + if ((finfo.dvi_tmp.fp = try_fdopen(tmp_fd, "wb+")) == NULL) { /* failure */ + info->message_popup = + popup_message(pinfo.act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, + "Xdvi needs to create a temporary file containing the " + "currently marked pages, but creating that file failed. " + "Try to fix the cause of the problem, or choose " + "\"Print selected pages\" as a workaround.", + "Could not open temp file for writing: %s.\n", + strerror(errno)); + return; + } + } + /* We try to use the original DVI file unless it's corrupted, in which case + we ask the user if they want to save the cached copy instead */ + if ((fin = fopen(globals.dvi_name, "rb")) == NULL + || !find_postamble(fin, &(pinfo.errflag))) { + Boolean could_not_open = False; + if (fin == NULL) + could_not_open = True; + if (fin) + fclose(fin); + + /* if we can't use the temporary file as source for our copy, this is a fatal error */ + if (!resource.use_temp_fp) { + info->message_popup = + popup_message(pinfo.act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, NULL, + "Could not copy DVI file %s: The file %s", + globals.dvi_name, could_not_open ? "doesn't exist any more" : "seems to be corrupted"); + return; + } + + /* else, we'll try to use the cached copy of the DVI file */ + if ((fin = fopen(get_tmp_dvi_name(), "rb")) == NULL) { + info->message_popup = + popup_message(pinfo.act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, NULL, + "Something's very wrong here - opening of both the " + "original DVI file and the cached copy failed!"); + return; + } + + if (!find_postamble(fin, &(pinfo.errflag))) { + info->message_popup = + popup_message(pinfo.act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, NULL, + "Shouldn't happen: Cached copy of the DVI file seems corrupted!"); + return; + } + finfo.dvi_in.fp = fin; + + /* tell user about it */ + if (pinfo.act == FILE_PRINT) + ok_button_str = "Print Copy"; + else + ok_button_str = "Save Copy"; + + info->message_popup = + choice_dialog(pinfo.act == FILE_PRINT ? print_shell : save_shell, + MSG_QUESTION, NULL, +#ifndef MOTIF + NULL, /* TODO: binding for RET? */ +#endif /* MOTIF */ + NULL, NULL, /* no pre_callbacks */ + ok_button_str, print_precheck2, (XtPointer)info, + "Cancel", do_cleanup, (XtPointer)info, + "The DVI file %s %s. Do you want to %s a cached copy of the file?", + globals.dvi_name, + could_not_open ? "doesn't exist any more" : "seems to be corrupted", + pinfo.act == FILE_PRINT ? "print" : "save"); + } + else { /* original DVI file is OK, copy it */ + finfo.dvi_in.fp = fin; + print_precheck2((XtPointer)info); + } +} + +static void +print_precheck2(XtPointer myinfo) +{ + struct save_or_print_info *info = (struct save_or_print_info *)myinfo; + char *expanded_filename = NULL; + struct select_pages_info *pinfo = (struct select_pages_info *)info->pinfo; + printOrSaveActionT act = pinfo->act; + const char *fname; + + /* Return if there are active popups; otherwise, the print process + will be messed up. */ + if (raise_message_windows()) { + XBell(DISP, 0); + return; + } + + /* expand and canonicalize path name */ + if (act == FILE_PRINT) + fname = save_pr_info.file_name; + else + fname = save_save_info.file_name; + + if (fname == NULL) { + info->message_popup = + popup_message(act == FILE_PRINT ? print_shell : save_shell, + MSG_WARN, + NULL, + "No filename specified!"); + return; + } + expanded_filename = expand_homedir(fname); /* this allocates expanded_filename */ + if (expanded_filename == NULL) { + info->message_popup = + popup_message(act == FILE_PRINT ? print_shell : save_shell, + MSG_WARN, + "Please specify either a filename or a full path, without using \"~\" or \"~user\".", + "Couldn't expand filename \"%s\" to a full path.", + fname); + return; + } + + if (act == FILE_PRINT) { + free(save_pr_info.expanded_filename); + save_pr_info.expanded_filename = expanded_filename; + } + else { + free(save_save_info.expanded_filename); + save_save_info.expanded_filename = expanded_filename; + } + + + if (act == FILE_SAVE && save_save_info.output_format == FMT_DVI) { /* canonicalize filename */ + char *tmp = expand_filename_append_dvi(save_save_info.expanded_filename, USE_CWD_PATH, False); + if (strcmp(tmp, globals.dvi_name) == 0) { + info->message_popup = + popup_message(act == FILE_PRINT ? print_shell : save_shell, + MSG_ERR, + NULL, + "Cannot overwrite the current DVI file (%s). " + "Please select a different file name.", + save_save_info.expanded_filename); + free(tmp); + return; + } + free(save_save_info.expanded_filename); + save_save_info.expanded_filename = tmp; + } + if (act == FILE_SAVE || (act == FILE_PRINT && curr_pr_info.print_radio == PRINT_TO_FILE)) { + /* check whether to clobber existing file */ + struct stat statbuf; + + if ((act == FILE_SAVE + && stat(save_save_info.expanded_filename, &statbuf) == 0 + && S_ISREG(statbuf.st_mode)) + || (act == FILE_PRINT + && stat(save_pr_info.expanded_filename, &statbuf) == 0 + && S_ISREG(statbuf.st_mode))) { + + info->message_popup = + choice_dialog(act == FILE_PRINT ? print_shell : save_shell, + MSG_QUESTION, NULL, +#ifndef MOTIF + NULL, /* TODO: binding for RET */ +#endif + NULL, NULL, /* no pre_callbacks */ + "Replace", popdown_dialog_and_print_or_save, (XtPointer)info, + /* + do nothing if user selects `cancel'; this will return to the + printing dialog, since user hasn't changed their mind about + printing, but would probably just like to choose another filename + */ + "Cancel", NULL, (XtPointer)NULL, + "%s already exists.\nDo you want to replace it?", + act == FILE_SAVE + ? save_save_info.expanded_filename + : save_pr_info.expanded_filename); + return; + } + else { + popdown_dialog_and_print_or_save(info); + } + } + else { + popdown_dialog_and_print_or_save(info); + } +} + +/* called from pagesel.c if user marks or unmarks a page in the page list */ +void +notify_print_dialog_have_marked(Boolean flag) +{ + /* Note: check for *both* windows, save and print: */ + + static pageRadioT old_value = NO_PAGE_VAL; + + if (save_is_active) { + if (!flag && curr_save_info.range_radio == SAVE_MARKED) { + /* switch button from `marked' to its previous value */ + switch (old_value) { + case SAVE_ALL: +#ifdef MOTIF + XmToggleButtonGadgetSetState(range_all_radio[FILE_SAVE], True, True); +#else + XawToggleSetCurrent(range_all_radio[FILE_SAVE], (XtPointer)old_value); +#endif + break; + case SAVE_RANGE: +#ifdef MOTIF + XmToggleButtonGadgetSetState(range_from_to_radio[FILE_SAVE], True, True); +#else + XawToggleSetCurrent(range_from_to_radio[FILE_SAVE], (XtPointer)old_value); +#endif + break; + default: break; + } + } + else if (flag) { + /* switch button to `marked', saving the current value */ + if (curr_save_info.range_radio != SAVE_MARKED) /* guard for second invocation on mouse release */ + old_value = curr_save_info.range_radio; +#ifdef MOTIF + XmToggleButtonGadgetSetState(range_marked_radio[FILE_SAVE], True, True); +#else + XawToggleSetCurrent(range_marked_radio[FILE_SAVE], (XtPointer)SAVE_MARKED); +#endif /* MOTIF */ + } + XtSetSensitive(range_marked_radio[FILE_SAVE], flag); + } + + if (print_is_active) { + if (!flag && curr_pr_info.range_radio == PRINT_MARKED) { + /* switch button from `marked' to its previous value */ + switch (old_value) { + case PRINT_ALL: +#ifdef MOTIF + XmToggleButtonGadgetSetState(range_all_radio[FILE_PRINT], True, True); +#else + XawToggleSetCurrent(range_all_radio[FILE_PRINT], (XtPointer)old_value); +#endif + break; + case PRINT_RANGE: +#ifdef MOTIF + XmToggleButtonGadgetSetState(range_from_to_radio[FILE_PRINT], True, True); +#else + XawToggleSetCurrent(range_from_to_radio[FILE_PRINT], (XtPointer)old_value); +#endif + break; + default: break; + } + } + else if (flag) { + /* switch button to `marked', saving the current value */ + if (curr_pr_info.range_radio != PRINT_MARKED) /* guard for second invocation on mouse release */ + old_value = curr_pr_info.range_radio; +#ifdef MOTIF + XmToggleButtonGadgetSetState(range_marked_radio[FILE_PRINT], True, True); +#else + XawToggleSetCurrent(range_marked_radio[FILE_PRINT], (XtPointer)PRINT_MARKED); +#endif /* MOTIF */ + } + XtSetSensitive(range_marked_radio[FILE_PRINT], flag); + } +} |