/***************************************************************************/ /***************************************************************************/ /* */ /* (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 #include #include #include #include #include #include #include #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; jfind.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; jfind.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; jfind.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; jfind.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); }