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.13 2001/06/25 15:19:28 skimo Exp $ (Berkeley) $Date: 2001/06/25 15:19:28 $";
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"
47 static save_dialog
*dialogs
= NULL
;
55 /* globals and constants */
57 static String PatternWidget
= "text";
58 static String pattern
= NULL
;
60 static optData search_toggles
[] = {
61 { optToggle
, "extended", NULL
, VI_SEARCH_EXT
},
62 { optToggle
, "iclower", NULL
, VI_SEARCH_ICL
},
63 { optToggle
, "ignorecase", NULL
, VI_SEARCH_IC
},
64 { optToggle
, "literal", NULL
, VI_SEARCH_LIT
},
65 { optToggle
, "searchincr", NULL
, VI_SEARCH_INCR
},
66 { optToggle
, "wrapscan", NULL
, VI_SEARCH_WR
},
70 static void done_func
__P((Widget
));
71 static void next_func
__P((Widget
));
72 static void prev_func
__P((Widget
));
73 static void search
__P((Widget
, int));
75 static ButtonData button_data
[] = {
76 { "Next", next_func
},
77 { "Previous", prev_func
},
78 { "Cancel", done_func
} /* always last */
85 static Widget
get_child_widget( Widget parent
, String name
)
87 static Widget
get_child_widget( parent
, name
)
94 strcpy( buffer
, "*" );
95 strcat( buffer
, name
);
96 return XtNameToWidget( parent
, buffer
);
100 /* sync the global state */
102 #if defined(__STDC__)
103 static void get_state( Widget w
)
105 static void get_state( w
)
109 #if defined(SelfTest)
114 /* get all the data from the root of the widget tree */
115 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
117 #if defined(SelfTest)
119 for (i
=0; i
<XtNumber(toggle_data
); i
++) {
120 if (( w
= get_child_widget( shell
, toggle_data
[i
].name
)) != NULL
) {
121 XtVaGetValues( w
, XmNset
, &toggle_data
[i
].value
, 0 );
126 /* what's the pattern? */
127 if (( w
= get_child_widget( shell
, PatternWidget
)) != NULL
) {
128 if ( pattern
!= NULL
) XtFree( pattern
);
129 pattern
= XmTextFieldGetString( w
);
134 /* Translate the user's actions into nvi commands */
137 * Action for next button.
147 * Action for previous button.
152 search(w
, VI_SEARCH_REV
);
157 * Perform the search.
160 search(Widget w
, int flags
)
167 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
169 /* Get current data from the root of the widget tree?
170 * Do it if we are a child of a dialog shell (assume we
171 * are a 'Find' dialog). Otherwise don't (we are the child
172 * of a menu and being invoked via accelerator)
174 if (XmIsDialogShell(shell
))
177 /* no pattern? probably, we haven't posted a search dialog yet.
178 * there ought to be a better thing to do here.
180 if ( pattern
== NULL
) {
181 vi_info_message( w
, "No previous string specified" );
186 ipb
.len1
= strlen(pattern
);
188 /* Initialize the search flags based on the buttons. */
190 for (opt
= search_toggles
; opt
->kind
!= optTerminator
; ++opt
)
191 if (opt
->value
!= NULL
)
192 ipb
.val1
|= opt
->flags
;
194 ipb
.code
= VI_C_SEARCH
;
195 vi_send(vi_ofd
, "a1", &ipb
);
198 #if defined(__STDC__)
199 static void done_func( Widget w
)
201 static void done_func( w
)
207 #if defined(SelfTest)
211 while ( ! XtIsShell(w
) ) w
= XtParent(w
);
214 /* save it for later */
215 ptr
= (save_dialog
*) malloc( sizeof(save_dialog
) );
222 /* create a set of push buttons */
224 #define SpacingRatio 4 /* 3:1 button to spaces */
226 #if defined(__STDC__)
227 static Widget
create_push_buttons( Widget parent
,
232 static Widget
create_push_buttons( parent
, data
, count
)
241 base
= SpacingRatio
*count
+ 1;
242 form
= XtVaCreateManagedWidget( "buttons",
245 XmNleftAttachment
, XmATTACH_FORM
,
246 XmNrightAttachment
, XmATTACH_FORM
,
247 XmNfractionBase
, base
,
248 XmNshadowType
, XmSHADOW_ETCHED_IN
,
249 XmNshadowThickness
, 2,
250 XmNverticalSpacing
, 4,
254 while ( count
-- > 0 ) {
255 w
= XtVaCreateManagedWidget(data
->name
,
256 xmPushButtonGadgetClass
,
258 XmNtopAttachment
, XmATTACH_FORM
,
259 XmNbottomAttachment
,XmATTACH_FORM
,
260 XmNleftAttachment
, XmATTACH_POSITION
,
261 XmNleftPosition
, pos
,
262 XmNshowAsDefault
, False
,
263 XmNrightAttachment
, XmATTACH_POSITION
,
264 XmNrightPosition
, pos
+SpacingRatio
-1,
267 XtAddCallback( w
, XmNactivateCallback
, data
->cb
, 0 );
272 /* last button is 'cancel' */
273 XtVaSetValues( XtParent(form
), XmNcancelButton
, w
, 0 );
279 /* create a set of check boxes */
281 #if defined(SelfTest)
283 #if defined(__STDC__)
284 static Widget
create_check_boxes( Widget parent
,
289 static Widget
create_check_boxes( parent
, toggles
, count
)
298 base
= SpacingRatio
*count
+1;
299 form
= XtVaCreateManagedWidget( "toggles",
302 XmNleftAttachment
, XmATTACH_FORM
,
303 XmNrightAttachment
, XmATTACH_FORM
,
304 XmNfractionBase
, base
,
305 XmNverticalSpacing
, 4,
309 while ( count
-- > 0 ) {
310 XtVaCreateManagedWidget(toggles
->name
,
311 xmToggleButtonWidgetClass
,
313 XmNtopAttachment
, XmATTACH_FORM
,
314 XmNbottomAttachment
, XmATTACH_FORM
,
315 XmNleftAttachment
, XmATTACH_POSITION
,
316 XmNleftPosition
, pos
,
317 XmNrightAttachment
, XmATTACH_POSITION
,
318 XmNrightPosition
, pos
+SpacingRatio
-1,
331 /* Routines to handle the text field widget */
333 /* when the user hits 'CR' in a text widget, fire the default pushbutton */
334 #if defined(__STDC__)
335 static void text_cr( Widget w
, void *ptr
, void *ptr2
)
337 static void text_cr( w
, ptr
, ptr2
)
349 * when the user hits any other character, if we are doing incremental
350 * search, send the updated string to nvi
353 * I don't currently see any way to make this work -- incremental search
354 * is going to be really nasty. What makes it worse is that the dialog
355 * box almost certainly obscured a chunk of the text file, so there's no
356 * way to use it even if it works.
358 #if defined(__STDC__)
359 static void value_changed( Widget w
, void *ptr
, void *ptr2
)
361 static void value_changed( w
, ptr
, ptr2
)
367 /* get all the data from the root of the widget tree */
371 #if defined(SelfTest)
372 if ( incremental_search
) send_command( w
);
374 if ( __vi_incremental_search() ) send_command( w
);
380 /* Draw and display a dialog the describes nvi search capability */
382 #if defined(__STDC__)
383 static Widget
create_search_dialog( Widget parent
, String title
)
385 static Widget
create_search_dialog( parent
, title
)
390 Widget box
, form
, label
, text
, checks
, buttons
, form2
;
393 /* use an existing one? */
394 if ( dialogs
!= NULL
) {
395 box
= dialogs
->shell
;
402 box
= XtVaCreatePopupShell( title
,
403 xmDialogShellWidgetClass
,
406 XmNallowShellResize
, False
,
410 form
= XtVaCreateWidget( "form",
413 XmNverticalSpacing
, 4,
414 XmNhorizontalSpacing
, 4,
418 form2
= XtVaCreateManagedWidget( "form",
421 XmNtopAttachment
, XmATTACH_FORM
,
422 XmNleftAttachment
, XmATTACH_FORM
,
423 XmNrightAttachment
, XmATTACH_FORM
,
427 label
= XtVaCreateManagedWidget( "Pattern:",
430 XmNtopAttachment
, XmATTACH_FORM
,
431 XmNbottomAttachment
,XmATTACH_FORM
,
432 XmNleftAttachment
, XmATTACH_FORM
,
436 text
= XtVaCreateManagedWidget( PatternWidget
,
437 xmTextFieldWidgetClass
,
439 XmNtopAttachment
, XmATTACH_FORM
,
440 XmNbottomAttachment
,XmATTACH_FORM
,
441 XmNleftAttachment
, XmATTACH_WIDGET
,
442 XmNleftWidget
, label
,
443 XmNrightAttachment
, XmATTACH_FORM
,
447 XtAddCallback( text
, XmNvalueChangedCallback
, value_changed
, 0 );
449 XtAddCallback( text
, XmNactivateCallback
, text_cr
, 0 );
451 buttons
= create_push_buttons( form
, button_data
, XtNumber(button_data
) );
452 XtVaSetValues( buttons
,
453 XmNbottomAttachment
, XmATTACH_FORM
,
457 #if defined(SelfTest)
458 checks
= create_check_boxes( form
, toggle_data
, XtNumber(toggle_data
) );
460 checks
= (Widget
) __vi_create_search_toggles( form
, search_toggles
);
462 XtVaSetValues( checks
,
463 XmNtopAttachment
, XmATTACH_WIDGET
,
465 XmNbottomAttachment
, XmATTACH_WIDGET
,
466 XmNbottomWidget
, buttons
,
470 XtManageChild( form
);
475 /* Module interface to the outside world
477 * xip_show_search_dialog( parent, title )
478 * pops up a search dialog
481 * simulates a 'next' assuming that a search has been done
484 #if defined(__STDC__)
485 void __vi_show_search_dialog( Widget parent
, String title
)
487 void __vi_show_search_dialog( parent
, data
, cbs
)
492 Widget db
= create_search_dialog( parent
, title
);
495 /* we can handle getting taller and wider or narrower, but not shorter */
496 XtVaGetValues( db
, XmNheight
, &height
, 0 );
497 XtVaSetValues( db
, XmNmaxHeight
, height
, XmNminHeight
, height
, 0 );
499 /* post the dialog */
500 XtPopup( db
, XtGrabNone
);
502 /* request initial focus to the text widget */
503 XmProcessTraversal( get_child_widget( db
, PatternWidget
),
512 * PUBLIC: void __vi_search __P((Widget));
515 __vi_search(Widget w
)
521 #if defined(SelfTest)
523 #if defined(__STDC__)
524 static void show_search( Widget w
, XtPointer data
, XtPointer cbs
)
526 static void show_search( w
, data
, cbs
)
532 __vi_show_search_dialog( data
, "Search" );
535 main( int argc
, char *argv
[] )
538 Widget top_level
, rc
, button
;
541 /* create a top-level shell for the window manager */
542 top_level
= XtVaAppInitialize( &ctx
,
544 NULL
, 0, /* options */
546 argv
, /* might get modified */
551 rc
= XtVaCreateManagedWidget( "rc",
552 xmRowColumnWidgetClass
,
557 button
= XtVaCreateManagedWidget( "Pop up search dialog",
558 xmPushButtonGadgetClass
,
562 XtAddCallback( button
, XmNactivateCallback
, show_search
, rc
);
564 button
= XtVaCreateManagedWidget( "Quit",
565 xmPushButtonGadgetClass
,
569 XtAddCallback( button
, XmNactivateCallback
, exit
, 0 );
571 XtRealizeWidget(top_level
);