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.12 2000/06/28 20:20:40 skimo Exp $ (Berkeley) $Date: 2000/06/28 20:20:40 $";
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.
148 * Action for previous button.
154 search(w
, VI_SEARCH_REV
);
159 * Perform the search.
171 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
173 /* Get current data from the root of the widget tree?
174 * Do it if we are a child of a dialog shell (assume we
175 * are a 'Find' dialog). Otherwise don't (we are the child
176 * of a menu and being invoked via accelerator)
178 if (XmIsDialogShell(shell
))
181 /* no pattern? probably, we haven't posted a search dialog yet.
182 * there ought to be a better thing to do here.
184 if ( pattern
== NULL
) {
185 vi_info_message( w
, "No previous string specified" );
190 ipb
.len1
= strlen(pattern
);
192 /* Initialize the search flags based on the buttons. */
194 for (opt
= search_toggles
; opt
->kind
!= optTerminator
; ++opt
)
195 if (opt
->value
!= NULL
)
196 ipb
.val1
|= opt
->flags
;
198 ipb
.code
= VI_C_SEARCH
;
199 vi_send(vi_ofd
, "a1", &ipb
);
202 #if defined(__STDC__)
203 static void done_func( Widget w
)
205 static void done_func( w
)
211 #if defined(SelfTest)
215 while ( ! XtIsShell(w
) ) w
= XtParent(w
);
218 /* save it for later */
219 ptr
= (save_dialog
*) malloc( sizeof(save_dialog
) );
226 /* create a set of push buttons */
228 #define SpacingRatio 4 /* 3:1 button to spaces */
230 #if defined(__STDC__)
231 static Widget
create_push_buttons( Widget parent
,
236 static Widget
create_push_buttons( parent
, data
, count
)
245 base
= SpacingRatio
*count
+ 1;
246 form
= XtVaCreateManagedWidget( "buttons",
249 XmNleftAttachment
, XmATTACH_FORM
,
250 XmNrightAttachment
, XmATTACH_FORM
,
251 XmNfractionBase
, base
,
252 XmNshadowType
, XmSHADOW_ETCHED_IN
,
253 XmNshadowThickness
, 2,
254 XmNverticalSpacing
, 4,
258 while ( count
-- > 0 ) {
259 w
= XtVaCreateManagedWidget(data
->name
,
260 xmPushButtonGadgetClass
,
262 XmNtopAttachment
, XmATTACH_FORM
,
263 XmNbottomAttachment
,XmATTACH_FORM
,
264 XmNleftAttachment
, XmATTACH_POSITION
,
265 XmNleftPosition
, pos
,
266 XmNshowAsDefault
, False
,
267 XmNrightAttachment
, XmATTACH_POSITION
,
268 XmNrightPosition
, pos
+SpacingRatio
-1,
271 XtAddCallback( w
, XmNactivateCallback
, data
->cb
, 0 );
276 /* last button is 'cancel' */
277 XtVaSetValues( XtParent(form
), XmNcancelButton
, w
, 0 );
283 /* create a set of check boxes */
285 #if defined(SelfTest)
287 #if defined(__STDC__)
288 static Widget
create_check_boxes( Widget parent
,
293 static Widget
create_check_boxes( parent
, toggles
, count
)
302 base
= SpacingRatio
*count
+1;
303 form
= XtVaCreateManagedWidget( "toggles",
306 XmNleftAttachment
, XmATTACH_FORM
,
307 XmNrightAttachment
, XmATTACH_FORM
,
308 XmNfractionBase
, base
,
309 XmNverticalSpacing
, 4,
313 while ( count
-- > 0 ) {
314 XtVaCreateManagedWidget(toggles
->name
,
315 xmToggleButtonWidgetClass
,
317 XmNtopAttachment
, XmATTACH_FORM
,
318 XmNbottomAttachment
, XmATTACH_FORM
,
319 XmNleftAttachment
, XmATTACH_POSITION
,
320 XmNleftPosition
, pos
,
321 XmNrightAttachment
, XmATTACH_POSITION
,
322 XmNrightPosition
, pos
+SpacingRatio
-1,
335 /* Routines to handle the text field widget */
337 /* when the user hits 'CR' in a text widget, fire the default pushbutton */
338 #if defined(__STDC__)
339 static void text_cr( Widget w
, void *ptr
, void *ptr2
)
341 static void text_cr( w
, ptr
, ptr2
)
353 * when the user hits any other character, if we are doing incremental
354 * search, send the updated string to nvi
357 * I don't currently see any way to make this work -- incremental search
358 * is going to be really nasty. What makes it worse is that the dialog
359 * box almost certainly obscured a chunk of the text file, so there's no
360 * way to use it even if it works.
362 #if defined(__STDC__)
363 static void value_changed( Widget w
, void *ptr
, void *ptr2
)
365 static void value_changed( w
, ptr
, ptr2
)
371 /* get all the data from the root of the widget tree */
375 #if defined(SelfTest)
376 if ( incremental_search
) send_command( w
);
378 if ( __vi_incremental_search() ) send_command( w
);
384 /* Draw and display a dialog the describes nvi search capability */
386 #if defined(__STDC__)
387 static Widget
create_search_dialog( Widget parent
, String title
)
389 static Widget
create_search_dialog( parent
, title
)
394 Widget box
, form
, label
, text
, checks
, buttons
, form2
;
397 /* use an existing one? */
398 if ( dialogs
!= NULL
) {
399 box
= dialogs
->shell
;
406 box
= XtVaCreatePopupShell( title
,
407 xmDialogShellWidgetClass
,
410 XmNallowShellResize
, False
,
414 form
= XtVaCreateWidget( "form",
417 XmNverticalSpacing
, 4,
418 XmNhorizontalSpacing
, 4,
422 form2
= XtVaCreateManagedWidget( "form",
425 XmNtopAttachment
, XmATTACH_FORM
,
426 XmNleftAttachment
, XmATTACH_FORM
,
427 XmNrightAttachment
, XmATTACH_FORM
,
431 label
= XtVaCreateManagedWidget( "Pattern:",
434 XmNtopAttachment
, XmATTACH_FORM
,
435 XmNbottomAttachment
,XmATTACH_FORM
,
436 XmNleftAttachment
, XmATTACH_FORM
,
440 text
= XtVaCreateManagedWidget( PatternWidget
,
441 xmTextFieldWidgetClass
,
443 XmNtopAttachment
, XmATTACH_FORM
,
444 XmNbottomAttachment
,XmATTACH_FORM
,
445 XmNleftAttachment
, XmATTACH_WIDGET
,
446 XmNleftWidget
, label
,
447 XmNrightAttachment
, XmATTACH_FORM
,
451 XtAddCallback( text
, XmNvalueChangedCallback
, value_changed
, 0 );
453 XtAddCallback( text
, XmNactivateCallback
, text_cr
, 0 );
455 buttons
= create_push_buttons( form
, button_data
, XtNumber(button_data
) );
456 XtVaSetValues( buttons
,
457 XmNbottomAttachment
, XmATTACH_FORM
,
461 #if defined(SelfTest)
462 checks
= create_check_boxes( form
, toggle_data
, XtNumber(toggle_data
) );
464 checks
= (Widget
) __vi_create_search_toggles( form
, search_toggles
);
466 XtVaSetValues( checks
,
467 XmNtopAttachment
, XmATTACH_WIDGET
,
469 XmNbottomAttachment
, XmATTACH_WIDGET
,
470 XmNbottomWidget
, buttons
,
474 XtManageChild( form
);
479 /* Module interface to the outside world
481 * xip_show_search_dialog( parent, title )
482 * pops up a search dialog
485 * simulates a 'next' assuming that a search has been done
488 #if defined(__STDC__)
489 void __vi_show_search_dialog( Widget parent
, String title
)
491 void __vi_show_search_dialog( parent
, data
, cbs
)
496 Widget db
= create_search_dialog( parent
, title
);
499 /* we can handle getting taller and wider or narrower, but not shorter */
500 XtVaGetValues( db
, XmNheight
, &height
, 0 );
501 XtVaSetValues( db
, XmNmaxHeight
, height
, XmNminHeight
, height
, 0 );
503 /* post the dialog */
504 XtPopup( db
, XtGrabNone
);
506 /* request initial focus to the text widget */
507 XmProcessTraversal( get_child_widget( db
, PatternWidget
),
516 * PUBLIC: void __vi_search __P((Widget));
526 #if defined(SelfTest)
528 #if defined(__STDC__)
529 static void show_search( Widget w
, XtPointer data
, XtPointer cbs
)
531 static void show_search( w
, data
, cbs
)
537 __vi_show_search_dialog( data
, "Search" );
540 main( int argc
, char *argv
[] )
543 Widget top_level
, rc
, button
;
546 /* create a top-level shell for the window manager */
547 top_level
= XtVaAppInitialize( &ctx
,
549 NULL
, 0, /* options */
551 argv
, /* might get modified */
556 rc
= XtVaCreateManagedWidget( "rc",
557 xmRowColumnWidgetClass
,
562 button
= XtVaCreateManagedWidget( "Pop up search dialog",
563 xmPushButtonGadgetClass
,
567 XtAddCallback( button
, XmNactivateCallback
, show_search
, rc
);
569 button
= XtVaCreateManagedWidget( "Quit",
570 xmPushButtonGadgetClass
,
574 XtAddCallback( button
, XmNactivateCallback
, exit
, 0 );
576 XtRealizeWidget(top_level
);