diff options
Diffstat (limited to 'Build/source/texk/xdvik/gui/search-dialog.c')
-rw-r--r-- | Build/source/texk/xdvik/gui/search-dialog.c | 1072 |
1 files changed, 1072 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/gui/search-dialog.c b/Build/source/texk/xdvik/gui/search-dialog.c new file mode 100644 index 00000000000..c77fa9d219e --- /dev/null +++ b/Build/source/texk/xdvik/gui/search-dialog.c @@ -0,0 +1,1072 @@ +/* + * Copyright (c) 2003-2004 Stefan Ulrich + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "xdvi-config.h" +#include "xdvi.h" + +#include "events.h" +#include "dvi-init.h" +#include "search-dialog.h" +#include "search-internal.h" +#include "xlwradio.h" +#include "statusline.h" +#include "string-utils.h" +#include "util.h" +#include "message-window.h" +#include "x_util.h" + +#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> +#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> +#endif /* MOTIF */ + +/* #defines for widgets that are used in common code */ +#ifdef MOTIF +# define SHELL_WIDGET xmDialogShellWidgetClass +# define PANED_WIDGET xmPanedWindowWidgetClass +# define FORM_WIDGET xmFormWidgetClass +# define LABEL_WIDGET xmLabelGadgetClass +# define TEXT_WIDGET xmTextFieldWidgetClass +# define CHECKBOX_WIDGET xmToggleButtonGadgetClass +# define CHECKBUTTON_IS_SET XmNset +# define PUSHBUTTON_WIDGET xmPushButtonWidgetClass +# define VALUE_CALLBACK_NAME XmNvalueChangedCallback +# define ACTIVATE_CALLBACK_NAME XmNactivateCallback +#else /* MOTIF */ +# define SHELL_WIDGET transientShellWidgetClass +# define PANED_WIDGET panedWidgetClass +# define FORM_WIDGET formWidgetClass +# define LABEL_WIDGET labelWidgetClass +# define TEXT_WIDGET asciiTextWidgetClass +# ifdef XAW +# define CHECKBOX_WIDGET radioWidgetClass +# else /* XAW */ +# define CHECKBOX_WIDGET toggleWidgetClass +# endif /* XAW */ +# define CHECKBUTTON_IS_SET XtNstate +# define PUSHBUTTON_WIDGET commandWidgetClass +# define VALUE_CALLBACK_NAME XtNcallback +# define ACTIVATE_CALLBACK_NAME XtNcallback +#endif /* MOTIF */ + +static Boolean m_find_popup_active = False; + +/* flags for setting single bits in resource.search_window_defaults */ +static const int SETTINGS_USE_REGEXP_FLAG = 1; +static const int SETTINGS_CASE_SENSITIVE_FLAG = 2; +static const int SETTINGS_BACKWARDS_FLAG = 4; +static const int SETTINGS_IGNORE_LINEBREAKS_FLAG = 8; + + +static void +cb_search_go(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + Widget find_popup; + Position x = 0, y = 0; + + ASSERT(settings != NULL, "client_data cb_search_go mustn't be NULL!"); + UNUSED(call_data); + + TRACE_FIND((stderr, "cb_search_go: settings: searchterm=|%s|, down = %d, re = %d, case = %d", + settings->term, settings->direction, settings->use_regexp, settings->case_sensitive)); + + /* retrieve the find popup window */ + if ((find_popup = XtNameToWidget(globals.widgets.top_level, "*find_popup")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"find_popup\" widget!")); + x = y = 0; + } + else { + XtVaGetValues(find_popup, XtNx, &x, XtNy, &y, NULL); + /* add some offsets */ + settings->x_pos = x + 10; + settings->y_pos = y + 10; + TRACE_GUI((stderr, "SHELL: %ld; x: %d, y: %d", (unsigned long)w, x, y)); + } + + settings->from_page = current_page; + settings->message_window = 0; + TRACE_FIND((stderr, "starting search from page: %d", settings->from_page)); + search_dvi((XtPointer)settings); +} + +static void +show_settings(const char *func_name, struct search_settings *settings) +{ + TRACE_FIND((stderr, "%s: settings: str=|%s|, down = %d, re = %d, " + "case = %d, ignore_hyphens = %d, ignore_linebreaks = %d\n", + func_name, + settings->term, + settings->direction, + settings->use_regexp, + settings->case_sensitive, + settings->ignore_hyphens, + settings->ignore_linebreaks)); + +} + + +static void +cb_regexp_search(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + /* Hack: Since XawToggleUnsetCurrent() will invoke this callback again, + return every second time to avoid multiple popups. This is done by + setting the flag `do_return'. + */ +#if !HAVE_REGEX_H + static Boolean do_return = False; +#endif + ASSERT(settings != NULL, "client_data cb_search_go mustn't be NULL!"); + UNUSED(call_data); + +#if !HAVE_REGEX_H + if (do_return) { + do_return = False; + return; + } + + XBell(DISP, 0); + popup_message(get_matching_parent(w, globals.widgets.top_level, "find_popup", NULL), + MSG_ERR, + NULL, + "Sorry, regular expression support (regex.h) is not available on this platform."); + do_return = True; +#ifdef MOTIF + XmToggleButtonGadgetSetState(w, True, False); +#else + XawToggleUnsetCurrent(w); +#endif + +#else + UNUSED(w); + settings->use_regexp = !(settings->use_regexp); + + /* force re-initialization of search term by resetting utf8_term: */ + free(settings->utf8_term); + settings->utf8_term = NULL; + + show_settings("cb_regexp_search", settings); +#endif + + if (settings->use_regexp) + resource.search_window_defaults |= SETTINGS_USE_REGEXP_FLAG; + else + resource.search_window_defaults &= ~SETTINGS_USE_REGEXP_FLAG; + store_preference(NULL, "searchWindowDefaults", "%u", resource.search_window_defaults); +} + +static void +cb_backwards_search(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + ASSERT(settings != NULL, "client_data cb_search_go mustn't be NULL!"); + UNUSED(w); + UNUSED(call_data); + + switch (settings->direction) { + case SEARCH_UP: settings->direction = SEARCH_DOWN; break; + case SEARCH_DOWN: settings->direction = SEARCH_UP; break; + default: ASSERT(0, "shouldn't happen: settings->direction is neither SEARCH_UP nor SEARCH_DOWN!"); break; + } + + show_settings("cb_backwards_search", settings); + + if (settings->direction == SEARCH_UP) + resource.search_window_defaults |= SETTINGS_BACKWARDS_FLAG; + else + resource.search_window_defaults &= ~SETTINGS_BACKWARDS_FLAG; + store_preference(NULL, "searchWindowDefaults", "%u", resource.search_window_defaults); +} + +static void +cb_match_case(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + ASSERT(settings != NULL, "client_data cb_search_go mustn't be NULL!"); + UNUSED(w); + UNUSED(call_data); + + settings->case_sensitive = !(settings->case_sensitive); + + show_settings("cb_match_case", settings); + + if (settings->case_sensitive) + resource.search_window_defaults |= SETTINGS_CASE_SENSITIVE_FLAG; + else + resource.search_window_defaults &= ~SETTINGS_CASE_SENSITIVE_FLAG; + store_preference(NULL, "searchWindowDefaults", "%u", resource.search_window_defaults); +} + +static void +cb_linebreaks(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + ASSERT(settings != NULL, "client_data cb_search_go mustn't be NULL!"); + UNUSED(w); + UNUSED(call_data); + + settings->ignore_linebreaks = !(settings->ignore_linebreaks); + settings->ignore_hyphens = !(settings->ignore_hyphens); + + show_settings("cb_linebreaks", settings); + + if (settings->ignore_linebreaks) + resource.search_window_defaults |= SETTINGS_IGNORE_LINEBREAKS_FLAG; + else + resource.search_window_defaults &= ~SETTINGS_IGNORE_LINEBREAKS_FLAG; + store_preference(NULL, "searchWindowDefaults", "%u", resource.search_window_defaults); +} + +static void +cb_search_cancel(Widget w, XtPointer client_data, XtPointer call_data) +{ + Widget find_popup; + struct search_settings *settings = (struct search_settings *)client_data; + + UNUSED(w); + UNUSED(call_data); + + /* retrieve the find popup window */ + if ((find_popup = XtNameToWidget(globals.widgets.top_level, "*find_popup")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"find_popup\" widget!")); + return; + } + + /* This flag is checked in the scanning routines, and + will be eventually reset by do_pages() in events.c. + (The scanning routines musn't reset it, since they + might not be called again after this point!) */ + globals.ev.flags |= EV_FIND_CANCEL; + + search_signal_page_changed(); /* Hack to make search restart anew */ + search_erase_highlighting(True); + if (settings->message_window != 0) { + TRACE_GUI((stderr, "kill_message_window: %p\n", (void *)settings->message_window)); + kill_message_window(settings->message_window); + } + XtPopdown(find_popup); + m_find_popup_active = False; +} + +static void +cb_search_get_term_button(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + char *searchterm = NULL; + + Widget searchbox_input, paned, box; + UNUSED(call_data); + + box = XtParent(w); + ASSERT(box != 0, "Parent of button widget mustn't be NULL!"); + paned = XtParent(box); + ASSERT(paned != 0, "Parent of box widget mustn't be NULL!"); + + if ((searchbox_input = XtNameToWidget(paned, "*searchbox_input")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"searchbox_input\" widget!")); + return; + } + +#ifdef MOTIF + XtVaGetValues(searchbox_input, XmNvalue, &searchterm, NULL); +#else + XtVaGetValues(searchbox_input, XtNstring, &searchterm, NULL); +#endif + if (searchterm == NULL) { + XDVI_WARNING((stderr, "Searchterm in cb_search_get_term callback shouldn't be NULL!")); + return; + } + TRACE_FIND((stderr, "searchterm1: |%s|", searchterm)); + settings->term = searchterm; + + cb_search_go(w, settings, NULL); +} + +static void +search_cancel(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct search_settings *settings = NULL; + void *ptr; + UNUSED(event); + + ASSERT(*num_params > 0, "params in search_cancel must be > 0!"); + ASSERT(*params != NULL, "params in search_cancel mustn't be NULL!"); + + /* + * the *params char pointer contains the pointer value (address) of `settings'; + * convert it back to a pointer: + */ + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + settings = (struct search_settings *)ptr; + TRACE_GUI((stderr, "Pointer address: |%p|", (void *)settings)); + ASSERT(settings != NULL, "Shouldn't happen: Couldn't get string representation of argument pointer."); + + cb_search_cancel(w, settings, NULL); +} + +#ifdef MOTIF + +static void +cb_search_get_term(Widget w, XtPointer client_data, XtPointer call_data) +{ + struct search_settings *settings = (struct search_settings *)client_data; + char *searchterm = NULL; + Widget form, paned, searchbox_form; + Widget button; + XEvent ev; + UNUSED(call_data); + + /* retrieve the `Find' button widget */ + searchbox_form = XtParent(w); + ASSERT(searchbox_form != 0, "Parent of button widget mustn't be NULL!"); + form = XtParent(searchbox_form); + ASSERT(form != 0, "Parent of searchbox_form widget mustn't be NULL!"); + paned = XtParent(form); + ASSERT(paned != 0, "Parent of form widget mustn't be NULL!"); + if ((button = XtNameToWidget(paned, "*find_button")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"find_button\" widget!")); + return; + } + + if (settings != NULL) { + /* retrieve search term from text input field */ + XtVaGetValues(w, XmNvalue, &searchterm, NULL); + if (searchterm == NULL) { + XDVI_WARNING((stderr, "Searchterm in cb_search_get_term callback shouldn't be NULL!")); + return; + } + + TRACE_FIND((stderr, "searchterm2: |%s|", searchterm)); + settings->term = (const char *)searchterm; + } + + /* make the `Find' button think it got pushed. + Also synthetisize an event, just to be sure ... */ + synthetisize_event(&ev, button); + + XtCallActionProc(button, "ArmAndActivate", &ev, NULL, 0); + /* the following don't make the button appear visually pressed: */ + /* XtCallCallbacks(button, XmNarmCallback, NULL); */ + /* XtCallCallbacks(button, XmNactivateCallback, NULL); */ +} + +static void +xm_search_go(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct search_settings *settings = NULL; + void *ptr; + Widget input; + + UNUSED(w); + UNUSED(event); + + if (params != NULL) { /* re-initialize search term */ + ASSERT(*num_params == 1, "num_params in xm_search_go should be 1 if *params != NULL"); + /* + * the *params char pointer contains the pointer value (address) of `settings'; + * convert it back to a pointer: + */ + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + settings = (struct search_settings *)ptr; + TRACE_GUI((stderr, "Pointer address: |%p|", (void *)settings)); + ASSERT(settings != NULL, "Shouldn't happen: Couldn't get string representation of argument pointer."); + } + + if ((input = XtNameToWidget(globals.widgets.top_level, "*searchbox_input")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"searchbox_input\" widget!")); + return; + } + cb_search_get_term(input, settings, NULL); +} + +#else /* MOTIF */ + +static void +xaw_unset_button(XtPointer client_data, XtIntervalId *id) +{ + XEvent ev; + Widget button = (Widget)client_data; + + UNUSED(id); + + synthetisize_event(&ev, button); + XtCallActionProc(button, "unset", &ev, NULL, 0); +} + +static void +xaw_search_go(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + struct search_settings *settings = NULL; + void *ptr; + char *searchterm = NULL; + Widget button, input; + XtIntervalId timeout; + + UNUSED(w); + + /* retrieve the `Find' button widget */ + if ((button = XtNameToWidget(globals.widgets.top_level, "*find_button")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"find_button\" widget!")); + return; + } + if ((input = XtNameToWidget(globals.widgets.top_level, "*searchbox_input")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"searchbox_input\" widget!")); + return; + } + + XtVaGetValues(input, XtNstring, &searchterm, NULL); + if (searchterm == NULL) { + XDVI_WARNING((stderr, "Searchterm in xaw_search_go callback shouldn't be NULL!")); + return; + } + + if (params != NULL) { /* re-initialize search term */ + ASSERT(*num_params == 1, "num_params in xaw_search_go should be 1 if *params != NULL"); + /* + * the *params char pointer contains the pointer value (address) of `settings'; + * convert it back to a pointer: + */ + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + settings = (struct search_settings *)ptr; + TRACE_GUI((stderr, "Pointer address: |%p|", (void *)settings)); + ASSERT(settings != NULL, "Shouldn't happen: Couldn't get string representation of argument pointer."); + + settings->term = (const char *)searchterm; + } + + /* + * Again, we want the button to appear activated when <RETURN> is pressed. + * For this, we explicitly invoke set()notify(), and unset() after a timeout + * of 150 milliseconds, which seems to correspond to the Motif default. + */ + XtCallActionProc(button, "set", event, NULL, 0); + XtCallActionProc(button, "notify", event, NULL, 0); + XSync(DISP, False); + timeout = XtAppAddTimeOut(app, 150, xaw_unset_button, (XtPointer)button); +} + + +/* + * Restart search from within another popup (confirmation) window. + */ +static void +xaw_search_restart(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + void *ptr; + struct search_settings *settings; + + UNUSED(event); + UNUSED(w); + + ASSERT(*num_params > 0, "params in xaw_search_restart must be > 0!"); + ASSERT(*params != NULL, "params in xaw_search_restart mustn't be NULL!"); + + TRACE_GUI((stderr, "Pointer string value: |%s|", *params)); + sscanf(*params, "%p", &ptr); + settings = (struct search_settings *)ptr; + + search_restart((XtPointer)settings); +} + +static XtActionsRec xaw_search_actions[] = { + { "do-search-restart", xaw_search_restart }, + { "do-search", xaw_search_go }, +}; +#endif /* MOTIF */ + +static XtActionsRec search_actions[] = { + { "do-search", +#ifdef MOTIF + xm_search_go +#else + xaw_search_go +#endif + }, + { "cancel-search", search_cancel }, +}; + +static Widget +create_search_window(struct search_settings *settings) +{ + Widget top_level_shell; + Atom WM_DELETE_WINDOW; + Widget form, find_paned, box; + unsigned char curr_state; + + Widget searchbox_form, searchbox_label, searchbox_input; + /* left and right column */ + Widget options_left_form, options_right_form; + /* checkboxes in left column */ + Widget regexp_checkbox, matchcase_checkbox, backwards_checkbox; + /* checkboxes in right column */ + Widget linebreaks_checkbox; + Widget find_button, cancel_button; + + XtTranslations xlats; + char *translation_str = NULL; +#ifdef MOTIF + XmString str; +#else /* MOTIF */ + XtTranslations wm_translations; + int ddist; +#endif + + XtAddActions(search_actions, XtNumber(search_actions)); + +#ifndef MOTIF + + XtAddActions(xaw_search_actions, XtNumber(xaw_search_actions)); +#define HORIZONTAL_RESIZING_NO XtNleft, XtChainLeft, XtNright, XtChainLeft +#define HORIZONTAL_RESIZING_YES XtNleft, XtChainLeft, XtNright, XtChainRight +#define VERTICAL_RESIZING_NO XtNtop, XtChainTop, XtNbottom, XtChainTop + + /* + * hacky: Since translations can only contain strings, pass + * the pointer address as string in the callback. But the only + * portability problem should be the size of the pointer + * representation, and we deal with that by using VSNPRINTF(). + */ + translation_str = get_string_va("<Message>WM_PROTOCOLS: cancel-search(%p)\nCtrl<Key>g:find-next()", + (void *)settings); + wm_translations = XtParseTranslationTable(translation_str); + free(translation_str); + translation_str = NULL; +#endif /* not MOTIF */ + + top_level_shell = XtVaCreatePopupShell("find_popup", + SHELL_WIDGET, + globals.widgets.top_level, + XtNtitle, "xdvik: Find in DVI file", + XtNmappedWhenManaged, False, /* so that we can center it first */ + XtNtransientFor, globals.widgets.top_level, + XtNallowShellResize, True, +#ifdef MOTIF + XmNdeleteResponse, XmDO_NOTHING, /* we'll take care of that ourselves */ +#else + XtNtranslations, wm_translations, +#endif + NULL); + + TRACE_GUI((stderr, "toplevel: %ld", (unsigned long)top_level_shell)); + + WM_DELETE_WINDOW = XInternAtom(XtDisplay(top_level_shell), "WM_DELETE_WINDOW", False); +#ifdef MOTIF + XmAddWMProtocolCallback(top_level_shell, WM_DELETE_WINDOW, cb_search_cancel, settings); +#endif + + find_paned = XtVaCreateWidget("find_paned", + PANED_WIDGET, + top_level_shell, +#ifdef MOTIF + /* make sashes invisible */ + XmNsashWidth, 1, + XmNsashHeight, 1, +#endif + NULL); + + form = XtVaCreateWidget("form", + FORM_WIDGET, + find_paned, +#ifdef MOTIF + XmNhorizontalSpacing, DDIST_MAJOR, + XmNverticalSpacing, DDIST_MAJOR, + XmNautoUnmanage, False, +#else + XtNallowResize, True, +#endif + NULL); + +#ifdef MOTIF + str = XmStringCreateLocalized("Find:"); +#else + XtVaGetValues(form, XtNdefaultDistance, &ddist, NULL); +#endif + + /* search term input field */ + searchbox_form = XtVaCreateWidget("searchbox_form", + FORM_WIDGET, + form, +#ifdef MOTIF + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNhorizontalSpacing, DDIST, + XmNverticalSpacing, DDIST, +#else + XtNborderWidth, 0, + HORIZONTAL_RESIZING_YES, +#endif + NULL); + searchbox_label = XtVaCreateManagedWidget("searchbox_label", + LABEL_WIDGET, + searchbox_form, +#ifdef MOTIF + XmNlabelString, str, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + XmNalignment, XmALIGNMENT_BEGINNING, +#else + XtNlabel, "Find:", + XtNborderWidth, 0, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, +#endif + NULL); + + searchbox_input = XtVaCreateManagedWidget("searchbox_input", + TEXT_WIDGET, + searchbox_form, +#ifdef MOTIF + XmNtopAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, searchbox_label, + XmNbottomAttachment, XmATTACH_FORM, +#else + XtNwidth, 260, + XtNdataCompression, False, + XtNeditType, XawtextEdit, + XtNfromHoriz, searchbox_label, + HORIZONTAL_RESIZING_YES, + VERTICAL_RESIZING_NO, +#endif + NULL); + + + if (settings->term != NULL) { + XtVaSetValues(searchbox_input, +#ifdef MOTIF + XmNvalue, +#else + XtNstring, +#endif + settings->term, NULL); + } + + XtManageChild(searchbox_form); + +#ifdef MOTIF + XtAddCallback(searchbox_input, XmNactivateCallback, cb_search_get_term, settings); +#endif + + /* + * form for left row of options checkbuttons + */ + options_left_form = XtVaCreateManagedWidget("options_left_form", + FORM_WIDGET, + form, +#ifdef MOTIF + XmNhorizontalSpacing, DDIST, + XmNverticalSpacing, DDIST, + XmNresizable, True, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, searchbox_form, + XmNleftAttachment, XmATTACH_FORM, +/* XmNrightAttachment, XmATTACH_FORM, */ +/* XmNbottomAttachment, XmATTACH_FORM, */ +#else + XtNborderWidth, 0, + XtNfromVert, searchbox_form, + HORIZONTAL_RESIZING_NO, +#endif + NULL); + /* + * form for right row of options checkbuttons + */ + options_right_form = XtVaCreateManagedWidget("options_right_form", + FORM_WIDGET, + form, +#ifdef MOTIF + XmNhorizontalSpacing, DDIST, + XmNverticalSpacing, DDIST, + XmNresizable, True, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, searchbox_form, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, options_left_form, + XmNrightAttachment, XmATTACH_FORM, +/* XmNbottomAttachment, XmATTACH_FORM, */ +#else + XtNborderWidth, 0, + XtNfromVert, searchbox_form, + XtNfromHoriz, options_left_form, + HORIZONTAL_RESIZING_NO, +#endif + NULL); +#ifdef MOTIF + XmStringFree(str); + str = XmStringCreateLocalized("Regular expression"); +#endif + + regexp_checkbox = XtVaCreateManagedWidget("regexp_checkbox", + CHECKBOX_WIDGET, + options_left_form, +#ifdef MOTIF + XmNlabelString, str, + XmNindicatorType, XmN_OF_MANY, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, +#else + XtNlabel, "Regular expression", + XtNborderWidth, 0, + XtNisRadio, False, + XtNhighlightThickness, 1, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, +#endif + NULL); + + XtAddCallback(regexp_checkbox, VALUE_CALLBACK_NAME, cb_regexp_search, settings); + +#ifdef MOTIF + XmStringFree(str); + str = XmStringCreateLocalized("Find backwards"); +#endif + + backwards_checkbox = XtVaCreateManagedWidget("backwards_checkbox", + CHECKBOX_WIDGET, + options_left_form, +#ifdef MOTIF + XmNlabelString, str, + XmNindicatorType, XmN_OF_MANY, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, regexp_checkbox, + XmNleftAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, +#else + XtNlabel, "Find backwards", + XtNfromVert, regexp_checkbox, + XtNborderWidth, 0, + XtNisRadio, False, + XtNhighlightThickness, 1, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, +#endif + NULL); + + XtAddCallback(backwards_checkbox, VALUE_CALLBACK_NAME, cb_backwards_search, settings); + +#ifdef MOTIF + XmStringFree(str); + str = XmStringCreateLocalized("Case sensitive"); +#endif + + matchcase_checkbox = XtVaCreateManagedWidget("matchcase_checkbox", + CHECKBOX_WIDGET, + options_right_form, +#ifdef MOTIF + XmNlabelString, str, + XmNindicatorType, XmN_OF_MANY, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, +#else + XtNlabel, "Case sensitive", + XtNborderWidth, 0, + XtNisRadio, False, + XtNhighlightThickness, 1, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, +#endif + NULL); + + XtAddCallback(matchcase_checkbox, VALUE_CALLBACK_NAME, cb_match_case, settings); + +#ifdef MOTIF + XmStringFree(str); + str = XmStringCreateLocalized("Ignore newlines/hyphens"); +#endif + + linebreaks_checkbox = XtVaCreateManagedWidget("linebreaks_checkbox", + CHECKBOX_WIDGET, + options_right_form, +#ifdef MOTIF + XmNlabelString, str, + XmNindicatorType, XmN_OF_MANY, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, matchcase_checkbox, + XmNleftAttachment, XmATTACH_FORM, +#else + XtNlabel, "Ignore newlines/hyphens", + XtNfromVert, matchcase_checkbox, + XtNborderWidth, 0, + XtNisRadio, False, + XtNhighlightThickness, 1, + HORIZONTAL_RESIZING_NO, + VERTICAL_RESIZING_NO, +#endif + NULL); + + XtAddCallback(linebreaks_checkbox, VALUE_CALLBACK_NAME, cb_linebreaks, settings); + + /* + * box for Find/Cancel buttons + */ + box = XtVaCreateManagedWidget("box", + FORM_WIDGET, + find_paned, +#ifdef MOTIF + XmNskipAdjust, True, /* don't resize this area */ +#else + /* 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, +#endif + NULL); + +#ifdef MOTIF + XmStringFree(str); + str = XmStringCreateLocalized("Find"); +#endif + + find_button = XtVaCreateManagedWidget("find_button", + PUSHBUTTON_WIDGET, + box, +#ifdef MOTIF + 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, +#else + XtNlabel, "Find", + XtNaccelerators, G_accels_cr, + XtNtop, XtChainTop, + XtNbottom, XtChainBottom, + HORIZONTAL_RESIZING_NO, +#endif + NULL); +#ifdef MOTIF + XmStringFree(str); + str = XmStringCreateLocalized("Cancel"); +#endif + + cancel_button = XtVaCreateManagedWidget("cancel_button", + PUSHBUTTON_WIDGET, + box, +#ifdef MOTIF + 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, +#else + XtNlabel, "Cancel", + XtNfromHoriz, find_button, + XtNbottom, XtChainBottom, + XtNjustify, XtJustifyRight, + XtNleft, XtChainRight, + XtNright, XtChainRight, +#endif + NULL); + +#ifdef MOTIF + XmStringFree(str); +#endif + + XtAddCallback(cancel_button, ACTIVATE_CALLBACK_NAME, cb_search_cancel, settings); + XtAddCallback(find_button, ACTIVATE_CALLBACK_NAME, cb_search_get_term_button, settings); + + translation_str = get_string_va( +#ifdef MOTIF + "<Key>osfCancel:cancel-search(%p)\n" +#else + "<Key>Escape:cancel-search(%p)\n" +#endif + "<Key>Return:do-search(%p)\n" + "Ctrl<Key>g:find-next()", + (void *)settings, (void *)settings); + + xlats = XtParseTranslationTable(translation_str); + free(translation_str); + + XtOverrideTranslations(searchbox_form, xlats); + XtOverrideTranslations(options_left_form, xlats); + XtOverrideTranslations(options_right_form, xlats); + XtOverrideTranslations(regexp_checkbox, xlats); + XtOverrideTranslations(matchcase_checkbox, xlats); + XtOverrideTranslations(backwards_checkbox, xlats); + XtOverrideTranslations(box, xlats); + XtOverrideTranslations(find_button, xlats); + XtOverrideTranslations(cancel_button, xlats); + XtOverrideTranslations(searchbox_input, xlats); + + /* following doesn't help to force input to textbox in xaw: */ + /* XtInstallAllAccelerators(find_paned, find_paned); */ + /* XtInstallAllAccelerators(searchbox_input, find_paned); */ + + XtManageChild(form); + XtManageChild(find_paned); + + { /* set all buttons to same size */ + Dimension w1, w2, max; + XtVaGetValues(find_button, XtNwidth, &w1, NULL); + XtVaGetValues(cancel_button, XtNwidth, &w2, NULL); + max = MAX(w1, w2); + XtVaSetValues(find_button, XtNwidth, max, NULL); + XtVaSetValues(cancel_button, XtNwidth, max, NULL); + } + + XtManageChild(top_level_shell); + /* don't center this one - would just get in the way in this case. */ + /* center_window(top_level_shell, globals.widgets.top_level); */ + XtPopup(top_level_shell, XtGrabNone); + m_find_popup_active = True; + +#ifdef MOTIF + XmProcessTraversal(searchbox_input, XmTRAVERSE_CURRENT); +/* XmProcessTraversal(find_button, XmTRAVERSE_CURRENT); */ +#endif + XSetWMProtocols(XtDisplay(top_level_shell), XtWindow(top_level_shell), &WM_DELETE_WINDOW, 1); + + /* check if we have default values from resource.search_window_defaults */ + if (resource.search_window_defaults & SETTINGS_USE_REGEXP_FLAG) + XtVaSetValues(regexp_checkbox, CHECKBUTTON_IS_SET, True, NULL); + if (resource.search_window_defaults & SETTINGS_CASE_SENSITIVE_FLAG) + XtVaSetValues(matchcase_checkbox, CHECKBUTTON_IS_SET, True, NULL); + if (resource.search_window_defaults & SETTINGS_BACKWARDS_FLAG) + XtVaSetValues(backwards_checkbox, CHECKBUTTON_IS_SET, True, NULL); + if (resource.search_window_defaults & SETTINGS_IGNORE_LINEBREAKS_FLAG) + XtVaSetValues(linebreaks_checkbox, CHECKBUTTON_IS_SET, True, NULL); + + /* initialize `settings' values according to the checkbox states + (in case user has assigned values via X defaults): */ + XtVaGetValues(regexp_checkbox, CHECKBUTTON_IS_SET, &curr_state, NULL); + settings->use_regexp = curr_state; + XtVaGetValues(matchcase_checkbox, CHECKBUTTON_IS_SET, &curr_state, NULL); + settings->case_sensitive = curr_state; + XtVaGetValues(backwards_checkbox, CHECKBUTTON_IS_SET, &curr_state, NULL); + settings->direction = curr_state ? SEARCH_UP : SEARCH_DOWN; + XtVaGetValues(linebreaks_checkbox, CHECKBUTTON_IS_SET, &curr_state, NULL); + settings->ignore_hyphens = settings->ignore_linebreaks = curr_state; + +#ifndef MOTIF + +#undef HORIZONTAL_RESIZING_NO +#undef HORIZONTAL_RESIZING_YES +#undef VERTICAL_RESIZING_NO + +#endif /* MOTIF */ + return top_level_shell; +} + +void +dvi_find_string(const char *str, Boolean find_next) +{ + /* Synthesize a RET keystroke for the find dialog. + * Also pops up the find dialog, to make it easier for user to + * edit options, change direction etc. */ + Widget find_popup; + if ((find_popup = XtNameToWidget(globals.widgets.top_level, "*find_popup")) == 0) { + static struct search_settings settings; + static struct search_info searchinfo = { False, False, False, 0, 0, 0, 0 }; + settings.term = str; + settings.use_regexp = False; + settings.case_sensitive = False; + settings.direction = SEARCH_DOWN; + settings.ignore_hyphens = False; + settings.ignore_linebreaks = False; + settings.x_pos = -1; + settings.y_pos = -1; + settings.searchinfo = &searchinfo; + settings.hyphen_delta = 0; + + find_popup = create_search_window(&settings); + + if (find_next) + return; + } + else if (str != NULL) { /* change the search term */ + Widget searchbox_input; + if ((searchbox_input = XtNameToWidget(find_popup, "*searchbox_input")) == 0) { + XDVI_WARNING((stderr, "Couldn't find \"searchbox_input\" widget!")); + return; + } + XtVaSetValues(searchbox_input, +#ifdef MOTIF + XmNvalue, +#else + XtNstring, +#endif + str, NULL); + } + if (m_find_popup_active) { + XRaiseWindow(DISP, XtWindow(find_popup)); + } + else { + XtPopup(find_popup, XtGrabNone); + m_find_popup_active = True; + } + + if (str != NULL || find_next) { +#ifdef MOTIF + xm_search_go(NULL, NULL, NULL, NULL); +#else + xaw_search_go(NULL, NULL, NULL, NULL); +#endif + } +} + |