/***************************************************************************/
/***************************************************************************/
/* */
/* (c) 1995-1999. The Regents of the University of California. All */
/* rights reserved. */
/* */
/* This work was produced at the University of California, Lawrence */
/* Livermore National Laboratory (UC LLNL) under contract no. */
/* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */
/* (DOE) and The Regents of the University of California (University) */
/* for the operation of UC LLNL. Copyright is reserved to the */
/* University for purposes of controlled dissemination, */
/* commercialization through formal licensing, or other disposition */
/* under terms of Contract 48; DOE policies, regulations and orders; */
/* and U.S. statutes. The rights of the Federal Government are */
/* reserved under Contract 48 subject to the restrictions agreed upon */
/* by the DOE and University. */
/* */
/* */
/* DISCLAIMER */
/* */
/* This software was prepared as an account of work sponsored by an */
/* agency of the United States Government. Neither the United States */
/* Government nor the University of California nor any of their */
/* employees, makes any warranty, express or implied, or assumes any */
/* liability or responsibility for the accuracy, completeness, or */
/* usefulness of any information, apparatus, product, or process */
/* disclosed, or represents that its specific commercial products, */
/* process, or service by trade name, trademark, manufacturer, or */
/* otherwise, does not necessarily constitute or imply its */
/* endorsement, recommendation, or favoring by the United States */
/* Government or the University of California. The views and opinions */
/* of the authors expressed herein do not necessarily state or reflect */
/* those of the United States Government or the University of */
/* California, and shall not be used for advertising or product */
/* endorsement purposes. */
/* */
/* Permission to use, copy, modify and distribute this software and its */
/* documentation for any non-commercial purpose, without fee, is */
/* hereby granted, provided that the above copyright notice and this */
/* permission notice appear in all copies of the software and */
/* supporting documentation, and that all UC LLNL identification in */
/* the user interface remain unchanged. The title to copyright LLNL */
/* XDIR shall at all times remain with The Regents of the University */
/* of California and users agree to preserve same. Users seeking the */
/* right to make derivative works with LLNL XDIR for commercial */
/* purposes may obtain a license from the Lawrence Livermore National */
/* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */
/* Livermore, CA 94550. */
/* */
/***************************************************************************/
/***************************************************************************/
#include <Xm/SelectioB.h>
#include <Xm/TextF.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/Frame.h>
#include <Xm/ToggleBG.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>
#include "xdir.h"
#include "view.h"
#include "str.h"
static struct {
Widget w_dialog;
Widget w_form;
Widget w_patternLabel;
Widget w_pattern;
Widget w_matchCaseLabel;
Widget w_matchRadioBoxFrame;
Widget w_matchRadioBox;
Widget w_matchCaseYesToggle;
Widget w_matchCaseNoToggle;
Widget w_directionLabel;
Widget w_directionRadioBoxFrame;
Widget w_directionRadioBox;
Widget w_searchForwardToggle;
Widget w_searchBackwardToggle;
} find;
static struct find_params_st prev_dialog_values;
static char *find_help[] = {
"This dialog allows you to search the displayed text for a simple",
"text string.\n",
"\n",
"The \"Case Sensitivity\" toggles control whether case (upper or",
"lower) should be considered when looking for a match.\n",
"\n",
"The \"Search Direction\" toggles control the direction of the",
"search. Regardless of the direction, the search will automatically",
"wrap past the end (or beginning) of the text until a match is",
"found, or until the entire text has been searched.\n",
"\n",
"Use general preferences INITIAL SEARCH DEPTH and INITIAL SEARCH",
"CASE MATCH to change the dialog's default values.",
NULL
};
static int saved_prev_dialog_values = False;
extern int initial_match_case;
extern int initial_search_direction;
void cb_find_cancel();
void cb_find_ok();
void cb_find_help();
void cb_map_dialog();
void create_find_dialog();
void save_find_dialog_values();
void init_find_dialog_values();
void find_pattern();
/*
* cb_internal_viewer_find - Callback that pops up Find dialog for
* internal viewer.
*/
void
cb_internal_viewer_find(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct view_dialog *view = (struct view_dialog*)client_data;
char *pattern;
/* Clear error flag */
raise_okflag();
/* Create "Find" dialog */
create_find_dialog(view);
/* Initialize settings in find dialog */
init_find_dialog_values();
/* Pop up dialog */
XtVaSetValues(find.w_dialog, XmNuserData, (XtPointer)view, NULL);
XtManageChild(find.w_dialog);
traverse_to_widget(find.w_pattern);
/* If pattern is already entered, select it */
pattern = XmTextFieldGetString(find.w_pattern);
XmTextFieldSetSelection(find.w_pattern, (XmTextPosition)0,
(XmTextPosition)strlen(pattern), CurrentTime);
XtFree(pattern);
}
/*
* create_find_dialog - Create dialog for finding text pattern in an
* internal viewer (represented by "view").
*/
void
create_find_dialog(view)
struct view_dialog *view;
{
int i;
Arg args[3];
Widget widget;
/* Create prompt dialog for searching */
i = 0;
XtSetArg(args[i], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); i++;
XtSetArg(args[i], XmNdefaultPosition, False); i++;
XtSetArg(args[i], XmNautoUnmanage, False); i++;
find.w_dialog = XmCreatePromptDialog(view->w_shell, "find", args, i);
XtAddCallback(find.w_dialog, XmNokCallback, cb_find_ok, (XtPointer)view);
XtAddCallback(find.w_dialog, XmNcancelCallback, cb_find_cancel,
(XtPointer)NULL);
XtAddCallback(find.w_dialog, XmNhelpCallback, cb_find_help,
(XtPointer)NULL);
XtAddCallback(find.w_dialog, XmNmapCallback, cb_map_dialog,
(XtPointer)XtWindow(view->w_shell));
/* Don't show prompt dialog's selection label and text */
widget = XmSelectionBoxGetChild(find.w_dialog, XmDIALOG_SELECTION_LABEL);
XtUnmanageChild(widget);
widget = XmSelectionBoxGetChild(find.w_dialog, XmDIALOG_TEXT);
XtUnmanageChild(widget);
/* Add callback for the WM_DELETE_WINDOW protocol */
add_wm_delete_window_cb(find.w_dialog, cb_find_cancel, NULL, False);
/* Create form for control area */
find.w_form = XtVaCreateWidget(
"form",
xmFormWidgetClass,
find.w_dialog,
NULL
);
/* Create label for search expression */
find.w_patternLabel = XtVaCreateManagedWidget(
"patternLabel",
xmLabelWidgetClass,
find.w_form,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create textfield for search expression */
find.w_pattern = XtVaCreateManagedWidget(
"text",
xmTextFieldWidgetClass,
find.w_form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, find.w_patternLabel,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create label for match case */
find.w_matchCaseLabel = XtVaCreateManagedWidget(
"matchCaseLabel",
xmLabelWidgetClass,
find.w_form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, find.w_pattern,
XmNtopOffset, 15,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 48,
NULL
);
/* Create radio box frame for match case */
find.w_matchRadioBoxFrame = XtVaCreateManagedWidget(
"matchRadioBoxFrame",
xmFrameWidgetClass,
find.w_form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, find.w_matchCaseLabel,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, find.w_matchCaseLabel,
XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNrightWidget, find.w_matchCaseLabel,
NULL
);
/* Create radio box for match criteria */
i = 0;
XtSetArg(args[i], XmNspacing, 0); i++;
find.w_matchRadioBox = XmCreateRadioBox(find.w_matchRadioBoxFrame,
"matchRadioBox", args, i);
/* Create match case "Yes" toggle */
find.w_matchCaseYesToggle = XtVaCreateManagedWidget(
"matchCaseYesToggle",
xmToggleButtonGadgetClass,
find.w_matchRadioBox,
XmNmarginHeight, 0,
XmNindicatorType, XmONE_OF_MANY,
NULL
);
/* Create match case "No" toggle */
find.w_matchCaseNoToggle = XtVaCreateManagedWidget(
"matchCaseNoToggle",
xmToggleButtonGadgetClass,
find.w_matchRadioBox,
XmNmarginHeight, 0,
XmNindicatorType, XmONE_OF_MANY,
NULL
);
XtManageChild(find.w_matchRadioBox);
/* Create label for search direction */
find.w_directionLabel = XtVaCreateManagedWidget(
"directionLabel",
xmLabelWidgetClass,
find.w_form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, find.w_pattern,
XmNtopOffset, 15,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 52,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create radio box frame for search direction */
find.w_directionRadioBoxFrame = XtVaCreateManagedWidget(
"directionRadioBoxFrame",
xmFrameWidgetClass,
find.w_form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, find.w_directionLabel,
XmNbottomOffset, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, find.w_directionLabel,
XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNrightWidget, find.w_directionLabel,
NULL
);
/* Create radio box for search direction */
i = 0;
XtSetArg(args[i], XmNspacing, 0); i++;
find.w_directionRadioBox = XmCreateRadioBox(find.w_directionRadioBoxFrame,
"directionRadioBoxFrame", args, i);
/* Create "Search Forward" toggle */
find.w_searchForwardToggle = XtVaCreateManagedWidget(
"searchForwardToggle",
xmToggleButtonGadgetClass,
find.w_directionRadioBox,
XmNindicatorType, XmONE_OF_MANY,
XmNmarginHeight, 0,
NULL
);
/* Create "Search Backward" toggle */
find.w_searchBackwardToggle = XtVaCreateManagedWidget(
"searchBackwardToggle",
xmToggleButtonGadgetClass,
find.w_directionRadioBox,
XmNindicatorType, XmONE_OF_MANY,
XmNmarginHeight, 0,
NULL
);
XtManageChild(find.w_directionRadioBox);
XtManageChild(find.w_form);
}
/*
* cb_find_ok - This callback initializes the search.
*/
void
cb_find_ok(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct view_dialog *view = (struct view_dialog *)client_data;
Widget w;
/* "Find Again" menu item no longer needs to be greyed out */
XtSetSensitive(view->w_findAgainItem, True);
/* Get pattern to search for */
XtFree(view->find.pattern);
view->find.pattern = XmTextFieldGetString(find.w_pattern);
if (!strlen(view->find.pattern)) {
warn("No search pattern given.", XtParent(find.w_dialog));
w = XmSelectionBoxGetChild(find.w_dialog, XmDIALOG_OK_BUTTON);
XtUnmanageChild(w);
XtManageChild(w);
traverse_to_widget(find.w_pattern);
return;
}
/* Match case? */
view->find.match_case =
XmToggleButtonGadgetGetState(find.w_matchCaseYesToggle);
/* Get search direction */
if (XmToggleButtonGadgetGetState(find.w_searchForwardToggle))
view->find.direction = FORWARD;
else
view->find.direction = BACKWARD;
/* This might take some time */
use_busy_cursor();
/* Get rid of Find dialog */
save_find_dialog_values();
XtUnmanageChild(find.w_dialog);
XtDestroyWidget(XtParent(find.w_dialog));
/* Perform search */
find_pattern(view);
/* All done */
restore_prev_cursor();
}
void
cb_internal_viewer_find_again(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
struct view_dialog *view = (struct view_dialog *)client_data;
/* Clear error flag */
raise_okflag();
/* This might take some time */
use_busy_cursor();
/* Perform search */
find_pattern(view);
/* All done */
restore_prev_cursor();
}
/*
* cb_find_help - Callback to display help info for Find dialog.
*/
void
cb_find_help(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
help_dialog(widget, True, "Find", find_help);
}
/*
* cb_find_cancel - Callback to handle Find Dialog "Cancel" button.
*/
void
cb_find_cancel(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
/* Get rid of Find Dialog */
save_find_dialog_values();
XtDestroyWidget(XtParent(find.w_dialog));
}
/*
* save_find_dialog_values - Remember current find dialog settings
* for next time find dialog is popped up.
*/
void
save_find_dialog_values()
{
if (saved_prev_dialog_values)
XtFree(prev_dialog_values.pattern);
prev_dialog_values.pattern = XmTextFieldGetString(find.w_pattern);
prev_dialog_values.match_case =
XmToggleButtonGadgetGetState(find.w_matchCaseYesToggle);
if (XmToggleButtonGadgetGetState(find.w_searchForwardToggle))
prev_dialog_values.direction = FORWARD;
else
prev_dialog_values.direction = BACKWARD;
saved_prev_dialog_values = True;
}
/*
* init_find_dialog_values - Initialize the find dialog with values
* saved from the last time the dialog was
* popped up. If this is the first time the
* dialog is popped up, use values from the
* user preferences to initialize the settings.
*/
void
init_find_dialog_values()
{
XmToggleButtonGadgetSetState(find.w_searchForwardToggle, False, True);
XmToggleButtonGadgetSetState(find.w_searchBackwardToggle, False, True);
XmToggleButtonGadgetSetState(find.w_matchCaseYesToggle, False,True);
XmToggleButtonGadgetSetState(find.w_matchCaseNoToggle, False, True);
if (saved_prev_dialog_values) {
XmTextFieldSetString(find.w_pattern, prev_dialog_values.pattern);
if (prev_dialog_values.match_case)
XmToggleButtonGadgetSetState(find.w_matchCaseYesToggle, True, True);
else
XmToggleButtonGadgetSetState(find.w_matchCaseNoToggle, True, True);
if (prev_dialog_values.direction == FORWARD)
XmToggleButtonGadgetSetState(find.w_searchForwardToggle, True,
True);
else
XmToggleButtonGadgetSetState(find.w_searchBackwardToggle, True,
True);
} else {
XmTextFieldSetString(find.w_pattern, "");
if (initial_match_case)
XmToggleButtonGadgetSetState(find.w_matchCaseYesToggle, True, True);
else
XmToggleButtonGadgetSetState(find.w_matchCaseNoToggle, True, True);
if (initial_search_direction == FORWARD)
XmToggleButtonGadgetSetState(find.w_searchForwardToggle, True,
True);
else
XmToggleButtonGadgetSetState(find.w_searchBackwardToggle, True,
True);
}
}
/*
* find_pattern - Find pattern in internal viewer specified by "view".
* view->find contains the search parameters.
*/
void
find_pattern(view)
struct view_dialog *view;
{
long start_pos = (long)XmTextGetInsertionPosition(view->w_text);
long ntext = (long)XmTextGetLastPosition(view->w_text);
long limit;
long i;
int j;
int npattern = strlen(view->find.pattern);
char *p;
/* Make sure that searchable text is available */
if (view->text == NULL) {
view->text = XmTextGetString(view->w_text);
view->text_converted_to_lc = False;
}
/* Adjust the case of the pattern and text */
if (view->find.match_case) {
if (view->text_converted_to_lc) {
XtFree(view->text);
view->text = XmTextGetString(view->w_text);
view->text_converted_to_lc = False;
}
} else {
p = view->find.pattern;
while (*p) {
*p = tolower(*p);
p++;
}
if (!view->text_converted_to_lc) {
p = view->text;
while (*p) {
*p = tolower(*p);
p++;
}
view->text_converted_to_lc = True;
}
}
/* Search text */
if (view->find.direction == FORWARD) {
limit = ntext-npattern;
for (i=start_pos; i<=limit; i++)
for (j=0; j<npattern; j++)
if (view->find.pattern[j] == view->text[i+j]) {
if (j == npattern-1)
goto found;
} else
break;
limit = MIN(start_pos-1, ntext-npattern);
for (i=0; i<=limit; i++)
for (j=0; j<npattern; j++)
if (view->find.pattern[j] == view->text[i+j]) {
if (j == npattern-1)
goto found;
} else
break;
} else {
limit = MIN(start_pos-1, ntext-npattern);
for (i=limit; i>=0; i--)
for (j=0; j<npattern; j++)
if (view->find.pattern[j] == view->text[i+j]) {
if (j == npattern-1)
goto found;
} else
break;
for (i=ntext-npattern; i>=start_pos; i--)
for (j=0; j<npattern; j++)
if (view->find.pattern[j] == view->text[i+j]) {
if (j == npattern-1)
goto found;
} else
break;
}
info_dialog("Match not found.", view->w_shell);
return;
found:
XmTextSetSelection(view->w_text, (XmTextPosition)i,
(XmTextPosition)(i+npattern), CurrentTime);
XmTextShowPosition(view->w_text, (XmTextPosition)i);
if (view->find.direction == BACKWARD)
XmTextSetInsertionPosition(view->w_text, (XmTextPosition)i);
}
syntax highlighted by Code2HTML, v. 0.9.1