3 * Rob Zimmermann. All rights reserved.
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
13 static const char sccsid
[] = "$Id: m_search.c,v 8.11 1996/12/18 10:26:50 bostic Exp $ (Berkeley) $Date: 1996/12/18 10:26:50 $";
16 #include <sys/queue.h>
20 #include <X11/Intrinsic.h>
21 #include <Xm/DialogS.h>
24 #include <Xm/PushBG.h>
26 #include <Xm/ToggleB.h>
27 #include <Xm/RowColumn.h>
29 #include <bitstring.h>
33 #include "../common/common.h"
34 #include "../ipc/ip.h"
45 static save_dialog
*dialogs
= NULL
;
53 /* globals and constants */
55 static String PatternWidget
= "text";
56 static String pattern
= NULL
;
58 static optData search_toggles
[] = {
59 { optToggle
, "extended", NULL
, VI_SEARCH_EXT
},
60 { optToggle
, "iclower", NULL
, VI_SEARCH_ICL
},
61 { optToggle
, "ignorecase", NULL
, VI_SEARCH_IC
},
62 { optToggle
, "literal", NULL
, VI_SEARCH_LIT
},
63 { optToggle
, "searchincr", NULL
, VI_SEARCH_INCR
},
64 { optToggle
, "wrapscan", NULL
, VI_SEARCH_WR
},
68 static void done_func
__P((Widget
));
69 static void next_func
__P((Widget
));
70 static void prev_func
__P((Widget
));
71 static void search
__P((Widget
, int));
73 static ButtonData button_data
[] = {
74 { "Next", next_func
},
75 { "Previous", prev_func
},
76 { "Cancel", done_func
} /* always last */
83 static Widget
get_child_widget( Widget parent
, String name
)
85 static Widget
get_child_widget( parent
, name
)
92 strcpy( buffer
, "*" );
93 strcat( buffer
, name
);
94 return XtNameToWidget( parent
, buffer
);
98 /* sync the global state */
100 #if defined(__STDC__)
101 static void get_state( Widget w
)
103 static void get_state( w
)
107 #if defined(SelfTest)
112 /* get all the data from the root of the widget tree */
113 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
115 #if defined(SelfTest)
117 for (i
=0; i
<XtNumber(toggle_data
); i
++) {
118 if (( w
= get_child_widget( shell
, toggle_data
[i
].name
)) != NULL
) {
119 XtVaGetValues( w
, XmNset
, &toggle_data
[i
].value
, 0 );
124 /* what's the pattern? */
125 if (( w
= get_child_widget( shell
, PatternWidget
)) != NULL
) {
126 if ( pattern
!= NULL
) XtFree( pattern
);
127 pattern
= XmTextFieldGetString( w
);
132 /* Translate the user's actions into nvi commands */
135 * Action for next button.
146 * Action for previous button.
152 search(w
, VI_SEARCH_REV
);
157 * Perform the search.
169 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
171 /* Get current data from the root of the widget tree?
172 * Do it if we are a child of a dialog shell (assume we
173 * are a 'Find' dialog). Otherwise don't (we are the child
174 * of a menu and being invoked via accelerator)
176 if (XmIsDialogShell(shell
))
179 /* no pattern? probably, we haven't posted a search dialog yet.
180 * there ought to be a better thing to do here.
182 if ( pattern
== NULL
) {
183 vi_info_message( w
, "No previous string specified" );
188 ipb
.len1
= strlen(pattern
);
190 /* Initialize the search flags based on the buttons. */
192 for (opt
= search_toggles
; opt
->kind
!= optTerminator
; ++opt
)
193 if (opt
->value
!= NULL
)
194 ipb
.val1
|= opt
->flags
;
196 ipb
.code
= VI_C_SEARCH
;
200 #if defined(__STDC__)
201 static void done_func( Widget w
)
203 static void done_func( w
)
209 #if defined(SelfTest)
213 while ( ! XtIsShell(w
) ) w
= XtParent(w
);
216 /* save it for later */
217 ptr
= (save_dialog
*) malloc( sizeof(save_dialog
) );
224 /* create a set of push buttons */
226 #define SpacingRatio 4 /* 3:1 button to spaces */
228 #if defined(__STDC__)
229 static Widget
create_push_buttons( Widget parent
,
234 static Widget
create_push_buttons( parent
, data
, count
)
243 base
= SpacingRatio
*count
+ 1;
244 form
= XtVaCreateManagedWidget( "buttons",
247 XmNleftAttachment
, XmATTACH_FORM
,
248 XmNrightAttachment
, XmATTACH_FORM
,
249 XmNfractionBase
, base
,
250 XmNshadowType
, XmSHADOW_ETCHED_IN
,
251 XmNshadowThickness
, 2,
252 XmNverticalSpacing
, 4,
256 while ( count
-- > 0 ) {
257 w
= XtVaCreateManagedWidget(data
->name
,
258 xmPushButtonGadgetClass
,
260 XmNtopAttachment
, XmATTACH_FORM
,
261 XmNbottomAttachment
,XmATTACH_FORM
,
262 XmNleftAttachment
, XmATTACH_POSITION
,
263 XmNleftPosition
, pos
,
264 XmNshowAsDefault
, False
,
265 XmNrightAttachment
, XmATTACH_POSITION
,
266 XmNrightPosition
, pos
+SpacingRatio
-1,
269 XtAddCallback( w
, XmNactivateCallback
, data
->cb
, 0 );
274 /* last button is 'cancel' */
275 XtVaSetValues( XtParent(form
), XmNcancelButton
, w
, 0 );
281 /* create a set of check boxes */
283 #if defined(SelfTest)
285 #if defined(__STDC__)
286 static Widget
create_check_boxes( Widget parent
,
291 static Widget
create_check_boxes( parent
, toggles
, count
)
300 base
= SpacingRatio
*count
+1;
301 form
= XtVaCreateManagedWidget( "toggles",
304 XmNleftAttachment
, XmATTACH_FORM
,
305 XmNrightAttachment
, XmATTACH_FORM
,
306 XmNfractionBase
, base
,
307 XmNverticalSpacing
, 4,
311 while ( count
-- > 0 ) {
312 XtVaCreateManagedWidget(toggles
->name
,
313 xmToggleButtonWidgetClass
,
315 XmNtopAttachment
, XmATTACH_FORM
,
316 XmNbottomAttachment
, XmATTACH_FORM
,
317 XmNleftAttachment
, XmATTACH_POSITION
,
318 XmNleftPosition
, pos
,
319 XmNrightAttachment
, XmATTACH_POSITION
,
320 XmNrightPosition
, pos
+SpacingRatio
-1,
333 /* Routines to handle the text field widget */
335 /* when the user hits 'CR' in a text widget, fire the default pushbutton */
336 #if defined(__STDC__)
337 static void text_cr( Widget w
, void *ptr
, void *ptr2
)
339 static void text_cr( w
, ptr
, ptr2
)
351 * when the user hits any other character, if we are doing incremental
352 * search, send the updated string to nvi
355 * I don't currently see any way to make this work -- incremental search
356 * is going to be really nasty. What makes it worse is that the dialog
357 * box almost certainly obscured a chunk of the text file, so there's no
358 * way to use it even if it works.
360 #if defined(__STDC__)
361 static void value_changed( Widget w
, void *ptr
, void *ptr2
)
363 static void value_changed( w
, ptr
, ptr2
)
369 /* get all the data from the root of the widget tree */
373 #if defined(SelfTest)
374 if ( incremental_search
) send_command( w
);
376 if ( __vi_incremental_search() ) send_command( w
);
382 /* Draw and display a dialog the describes nvi search capability */
384 #if defined(__STDC__)
385 static Widget
create_search_dialog( Widget parent
, String title
)
387 static Widget
create_search_dialog( parent
, title
)
392 Widget box
, form
, label
, text
, checks
, buttons
, form2
;
395 /* use an existing one? */
396 if ( dialogs
!= NULL
) {
397 box
= dialogs
->shell
;
404 box
= XtVaCreatePopupShell( title
,
405 xmDialogShellWidgetClass
,
408 XmNallowShellResize
, False
,
412 form
= XtVaCreateWidget( "form",
415 XmNverticalSpacing
, 4,
416 XmNhorizontalSpacing
, 4,
420 form2
= XtVaCreateManagedWidget( "form",
423 XmNtopAttachment
, XmATTACH_FORM
,
424 XmNleftAttachment
, XmATTACH_FORM
,
425 XmNrightAttachment
, XmATTACH_FORM
,
429 label
= XtVaCreateManagedWidget( "Pattern:",
432 XmNtopAttachment
, XmATTACH_FORM
,
433 XmNbottomAttachment
,XmATTACH_FORM
,
434 XmNleftAttachment
, XmATTACH_FORM
,
438 text
= XtVaCreateManagedWidget( PatternWidget
,
439 xmTextFieldWidgetClass
,
441 XmNtopAttachment
, XmATTACH_FORM
,
442 XmNbottomAttachment
,XmATTACH_FORM
,
443 XmNleftAttachment
, XmATTACH_WIDGET
,
444 XmNleftWidget
, label
,
445 XmNrightAttachment
, XmATTACH_FORM
,
449 XtAddCallback( text
, XmNvalueChangedCallback
, value_changed
, 0 );
451 XtAddCallback( text
, XmNactivateCallback
, text_cr
, 0 );
453 buttons
= create_push_buttons( form
, button_data
, XtNumber(button_data
) );
454 XtVaSetValues( buttons
,
455 XmNbottomAttachment
, XmATTACH_FORM
,
459 #if defined(SelfTest)
460 checks
= create_check_boxes( form
, toggle_data
, XtNumber(toggle_data
) );
462 checks
= (Widget
) __vi_create_search_toggles( form
, search_toggles
);
464 XtVaSetValues( checks
,
465 XmNtopAttachment
, XmATTACH_WIDGET
,
467 XmNbottomAttachment
, XmATTACH_WIDGET
,
468 XmNbottomWidget
, buttons
,
472 XtManageChild( form
);
477 /* Module interface to the outside world
479 * xip_show_search_dialog( parent, title )
480 * pops up a search dialog
483 * simulates a 'next' assuming that a search has been done
486 #if defined(__STDC__)
487 void __vi_show_search_dialog( Widget parent
, String title
)
489 void __vi_show_search_dialog( parent
, data
, cbs
)
494 Widget db
= create_search_dialog( parent
, title
);
497 /* we can handle getting taller and wider or narrower, but not shorter */
498 XtVaGetValues( db
, XmNheight
, &height
, 0 );
499 XtVaSetValues( db
, XmNmaxHeight
, height
, XmNminHeight
, height
, 0 );
501 /* post the dialog */
502 XtPopup( db
, XtGrabNone
);
504 /* request initial focus to the text widget */
505 XmProcessTraversal( get_child_widget( db
, PatternWidget
),
514 * PUBLIC: void __vi_search __P((Widget));
524 #if defined(SelfTest)
526 #if defined(__STDC__)
527 static void show_search( Widget w
, XtPointer data
, XtPointer cbs
)
529 static void show_search( w
, data
, cbs
)
535 __vi_show_search_dialog( data
, "Search" );
538 main( int argc
, char *argv
[] )
541 Widget top_level
, rc
, button
;
544 /* create a top-level shell for the window manager */
545 top_level
= XtVaAppInitialize( &ctx
,
547 NULL
, 0, /* options */
549 argv
, /* might get modified */
554 rc
= XtVaCreateManagedWidget( "rc",
555 xmRowColumnWidgetClass
,
560 button
= XtVaCreateManagedWidget( "Pop up search dialog",
561 xmPushButtonGadgetClass
,
565 XtAddCallback( button
, XmNactivateCallback
, show_search
, rc
);
567 button
= XtVaCreateManagedWidget( "Quit",
568 xmPushButtonGadgetClass
,
572 XtAddCallback( button
, XmNactivateCallback
, exit
, 0 );
574 XtRealizeWidget(top_level
);