5 * Rob Zimmermann. All rights reserved.
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
15 static const char sccsid
[] = "Id: m_search.c,v 8.14 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00";
18 #include <sys/queue.h>
22 #include <X11/Intrinsic.h>
23 #include <Xm/DialogS.h>
26 #include <Xm/PushBG.h>
28 #include <Xm/ToggleB.h>
29 #include <Xm/RowColumn.h>
31 #include <bitstring.h>
36 #include "../common/common.h"
37 #include "../ipc/ip.h"
50 static save_dialog
*dialogs
= NULL
;
58 /* globals and constants */
60 static String PatternWidget
= "text";
61 static String pattern
= NULL
;
63 static optData search_toggles
[] = {
64 { optToggle
, "extended", NULL
, VI_SEARCH_EXT
},
65 { optToggle
, "iclower", NULL
, VI_SEARCH_ICL
},
66 { optToggle
, "ignorecase", NULL
, VI_SEARCH_IC
},
67 { optToggle
, "literal", NULL
, VI_SEARCH_LIT
},
68 { optToggle
, "searchincr", NULL
, VI_SEARCH_INCR
},
69 { optToggle
, "wrapscan", NULL
, VI_SEARCH_WR
},
73 static void done_func
__P((Widget
));
74 static void next_func
__P((Widget
));
75 static void prev_func
__P((Widget
));
76 static void search
__P((Widget
, int));
78 static ButtonData button_data
[] = {
79 { "Next", next_func
},
80 { "Previous", prev_func
},
81 { "Cancel", done_func
} /* always last */
88 static Widget
get_child_widget( Widget parent
, String name
)
90 static Widget
get_child_widget( parent
, name
)
97 strcpy( buffer
, "*" );
98 strcat( buffer
, name
);
99 return XtNameToWidget( parent
, buffer
);
103 /* sync the global state */
105 #if defined(__STDC__)
106 static void get_state( Widget w
)
108 static void get_state( w
)
112 #if defined(SelfTest)
117 /* get all the data from the root of the widget tree */
118 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
120 #if defined(SelfTest)
122 for (i
=0; i
<XtNumber(toggle_data
); i
++) {
123 if (( w
= get_child_widget( shell
, toggle_data
[i
].name
)) != NULL
) {
124 XtVaGetValues( w
, XmNset
, &toggle_data
[i
].value
, 0 );
129 /* what's the pattern? */
130 if (( w
= get_child_widget( shell
, PatternWidget
)) != NULL
) {
131 if ( pattern
!= NULL
) XtFree( pattern
);
132 pattern
= XmTextFieldGetString( w
);
137 /* Translate the user's actions into nvi commands */
140 * Action for next button.
150 * Action for previous button.
155 search(w
, VI_SEARCH_REV
);
160 * Perform the search.
163 search(Widget w
, int flags
)
170 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
172 /* Get current data from the root of the widget tree?
173 * Do it if we are a child of a dialog shell (assume we
174 * are a 'Find' dialog). Otherwise don't (we are the child
175 * of a menu and being invoked via accelerator)
177 if (XmIsDialogShell(shell
))
180 /* no pattern? probably, we haven't posted a search dialog yet.
181 * there ought to be a better thing to do here.
183 if ( pattern
== NULL
) {
184 vi_info_message( w
, "No previous string specified" );
189 ipb
.len1
= strlen(pattern
);
191 /* Initialize the search flags based on the buttons. */
193 for (opt
= search_toggles
; opt
->kind
!= optTerminator
; ++opt
)
194 if (opt
->value
!= NULL
)
195 ipb
.val1
|= opt
->flags
;
197 ipb
.code
= VI_C_SEARCH
;
198 vi_send(vi_ofd
, "a1", &ipb
);
201 #if defined(__STDC__)
202 static void done_func( Widget w
)
204 static void done_func( w
)
210 #if defined(SelfTest)
214 while ( ! XtIsShell(w
) ) w
= XtParent(w
);
217 /* save it for later */
218 ptr
= (save_dialog
*) malloc( sizeof(save_dialog
) );
225 /* create a set of push buttons */
227 #define SpacingRatio 4 /* 3:1 button to spaces */
229 #if defined(__STDC__)
230 static Widget
create_push_buttons( Widget parent
,
235 static Widget
create_push_buttons( parent
, data
, count
)
244 base
= SpacingRatio
*count
+ 1;
245 form
= XtVaCreateManagedWidget( "buttons",
248 XmNleftAttachment
, XmATTACH_FORM
,
249 XmNrightAttachment
, XmATTACH_FORM
,
250 XmNfractionBase
, base
,
251 XmNshadowType
, XmSHADOW_ETCHED_IN
,
252 XmNshadowThickness
, 2,
253 XmNverticalSpacing
, 4,
257 while ( count
-- > 0 ) {
258 w
= XtVaCreateManagedWidget(data
->name
,
259 xmPushButtonGadgetClass
,
261 XmNtopAttachment
, XmATTACH_FORM
,
262 XmNbottomAttachment
,XmATTACH_FORM
,
263 XmNleftAttachment
, XmATTACH_POSITION
,
264 XmNleftPosition
, pos
,
265 XmNshowAsDefault
, False
,
266 XmNrightAttachment
, XmATTACH_POSITION
,
267 XmNrightPosition
, pos
+SpacingRatio
-1,
270 XtAddCallback( w
, XmNactivateCallback
, data
->cb
, 0 );
275 /* last button is 'cancel' */
276 XtVaSetValues( XtParent(form
), XmNcancelButton
, w
, 0 );
282 /* create a set of check boxes */
284 #if defined(SelfTest)
286 #if defined(__STDC__)
287 static Widget
create_check_boxes( Widget parent
,
292 static Widget
create_check_boxes( parent
, toggles
, count
)
301 base
= SpacingRatio
*count
+1;
302 form
= XtVaCreateManagedWidget( "toggles",
305 XmNleftAttachment
, XmATTACH_FORM
,
306 XmNrightAttachment
, XmATTACH_FORM
,
307 XmNfractionBase
, base
,
308 XmNverticalSpacing
, 4,
312 while ( count
-- > 0 ) {
313 XtVaCreateManagedWidget(toggles
->name
,
314 xmToggleButtonWidgetClass
,
316 XmNtopAttachment
, XmATTACH_FORM
,
317 XmNbottomAttachment
, XmATTACH_FORM
,
318 XmNleftAttachment
, XmATTACH_POSITION
,
319 XmNleftPosition
, pos
,
320 XmNrightAttachment
, XmATTACH_POSITION
,
321 XmNrightPosition
, pos
+SpacingRatio
-1,
334 /* Routines to handle the text field widget */
336 /* when the user hits 'CR' in a text widget, fire the default pushbutton */
337 #if defined(__STDC__)
338 static void text_cr( Widget w
, void *ptr
, void *ptr2
)
340 static void text_cr( w
, ptr
, ptr2
)
352 * when the user hits any other character, if we are doing incremental
353 * search, send the updated string to nvi
356 * I don't currently see any way to make this work -- incremental search
357 * is going to be really nasty. What makes it worse is that the dialog
358 * box almost certainly obscured a chunk of the text file, so there's no
359 * way to use it even if it works.
361 #if defined(__STDC__)
362 static void value_changed( Widget w
, void *ptr
, void *ptr2
)
364 static void value_changed( w
, ptr
, ptr2
)
370 /* get all the data from the root of the widget tree */
374 #if defined(SelfTest)
375 if ( incremental_search
) send_command( w
);
377 if ( __vi_incremental_search() ) send_command( w
);
383 /* Draw and display a dialog the describes nvi search capability */
385 #if defined(__STDC__)
386 static Widget
create_search_dialog( Widget parent
, String title
)
388 static Widget
create_search_dialog( parent
, title
)
393 Widget box
, form
, label
, text
, checks
, buttons
, form2
;
396 /* use an existing one? */
397 if ( dialogs
!= NULL
) {
398 box
= dialogs
->shell
;
405 box
= XtVaCreatePopupShell( title
,
406 xmDialogShellWidgetClass
,
409 XmNallowShellResize
, False
,
413 form
= XtVaCreateWidget( "form",
416 XmNverticalSpacing
, 4,
417 XmNhorizontalSpacing
, 4,
421 form2
= XtVaCreateManagedWidget( "form",
424 XmNtopAttachment
, XmATTACH_FORM
,
425 XmNleftAttachment
, XmATTACH_FORM
,
426 XmNrightAttachment
, XmATTACH_FORM
,
430 label
= XtVaCreateManagedWidget( "Pattern:",
433 XmNtopAttachment
, XmATTACH_FORM
,
434 XmNbottomAttachment
,XmATTACH_FORM
,
435 XmNleftAttachment
, XmATTACH_FORM
,
439 text
= XtVaCreateManagedWidget( PatternWidget
,
440 xmTextFieldWidgetClass
,
442 XmNtopAttachment
, XmATTACH_FORM
,
443 XmNbottomAttachment
,XmATTACH_FORM
,
444 XmNleftAttachment
, XmATTACH_WIDGET
,
445 XmNleftWidget
, label
,
446 XmNrightAttachment
, XmATTACH_FORM
,
450 XtAddCallback( text
, XmNvalueChangedCallback
, value_changed
, 0 );
452 XtAddCallback( text
, XmNactivateCallback
, text_cr
, 0 );
454 buttons
= create_push_buttons( form
, button_data
, XtNumber(button_data
) );
455 XtVaSetValues( buttons
,
456 XmNbottomAttachment
, XmATTACH_FORM
,
460 #if defined(SelfTest)
461 checks
= create_check_boxes( form
, toggle_data
, XtNumber(toggle_data
) );
463 checks
= (Widget
) __vi_create_search_toggles( form
, search_toggles
);
465 XtVaSetValues( checks
,
466 XmNtopAttachment
, XmATTACH_WIDGET
,
468 XmNbottomAttachment
, XmATTACH_WIDGET
,
469 XmNbottomWidget
, buttons
,
473 XtManageChild( form
);
478 /* Module interface to the outside world
480 * xip_show_search_dialog( parent, title )
481 * pops up a search dialog
484 * simulates a 'next' assuming that a search has been done
487 #if defined(__STDC__)
488 void __vi_show_search_dialog( Widget parent
, String title
)
490 void __vi_show_search_dialog( parent
, data
, cbs
)
495 Widget db
= create_search_dialog( parent
, title
);
498 /* we can handle getting taller and wider or narrower, but not shorter */
499 XtVaGetValues( db
, XmNheight
, &height
, 0 );
500 XtVaSetValues( db
, XmNmaxHeight
, height
, XmNminHeight
, height
, 0 );
502 /* post the dialog */
503 XtPopup( db
, XtGrabNone
);
505 /* request initial focus to the text widget */
506 XmProcessTraversal( get_child_widget( db
, PatternWidget
),
515 * PUBLIC: void __vi_search __P((Widget));
518 __vi_search(Widget w
)
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
);