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.14 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00 ";
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>
34 #include "../common/common.h"
35 #include "../ipc/ip.h"
48 static save_dialog
*dialogs
= NULL
;
56 /* globals and constants */
58 static String PatternWidget
= "text";
59 static String pattern
= NULL
;
61 static optData search_toggles
[] = {
62 { optToggle
, "extended", NULL
, VI_SEARCH_EXT
},
63 { optToggle
, "iclower", NULL
, VI_SEARCH_ICL
},
64 { optToggle
, "ignorecase", NULL
, VI_SEARCH_IC
},
65 { optToggle
, "literal", NULL
, VI_SEARCH_LIT
},
66 { optToggle
, "searchincr", NULL
, VI_SEARCH_INCR
},
67 { optToggle
, "wrapscan", NULL
, VI_SEARCH_WR
},
71 static void done_func
__P((Widget
));
72 static void next_func
__P((Widget
));
73 static void prev_func
__P((Widget
));
74 static void search
__P((Widget
, int));
76 static ButtonData button_data
[] = {
77 { "Next", next_func
},
78 { "Previous", prev_func
},
79 { "Cancel", done_func
} /* always last */
86 static Widget
get_child_widget( Widget parent
, String name
)
88 static Widget
get_child_widget( parent
, name
)
95 strcpy( buffer
, "*" );
96 strcat( buffer
, name
);
97 return XtNameToWidget( parent
, buffer
);
101 /* sync the global state */
103 #if defined(__STDC__)
104 static void get_state( Widget w
)
106 static void get_state( w
)
110 #if defined(SelfTest)
115 /* get all the data from the root of the widget tree */
116 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
118 #if defined(SelfTest)
120 for (i
=0; i
<XtNumber(toggle_data
); i
++) {
121 if (( w
= get_child_widget( shell
, toggle_data
[i
].name
)) != NULL
) {
122 XtVaGetValues( w
, XmNset
, &toggle_data
[i
].value
, 0 );
127 /* what's the pattern? */
128 if (( w
= get_child_widget( shell
, PatternWidget
)) != NULL
) {
129 if ( pattern
!= NULL
) XtFree( pattern
);
130 pattern
= XmTextFieldGetString( w
);
135 /* Translate the user's actions into nvi commands */
138 * Action for next button.
148 * Action for previous button.
153 search(w
, VI_SEARCH_REV
);
158 * Perform the search.
161 search(Widget w
, int flags
)
168 while ( ! XtIsShell(shell
) ) shell
= XtParent(shell
);
170 /* Get current data from the root of the widget tree?
171 * Do it if we are a child of a dialog shell (assume we
172 * are a 'Find' dialog). Otherwise don't (we are the child
173 * of a menu and being invoked via accelerator)
175 if (XmIsDialogShell(shell
))
178 /* no pattern? probably, we haven't posted a search dialog yet.
179 * there ought to be a better thing to do here.
181 if ( pattern
== NULL
) {
182 vi_info_message( w
, "No previous string specified" );
187 ipb
.len1
= strlen(pattern
);
189 /* Initialize the search flags based on the buttons. */
191 for (opt
= search_toggles
; opt
->kind
!= optTerminator
; ++opt
)
192 if (opt
->value
!= NULL
)
193 ipb
.val1
|= opt
->flags
;
195 ipb
.code
= VI_C_SEARCH
;
196 vi_send(vi_ofd
, "a1", &ipb
);
199 #if defined(__STDC__)
200 static void done_func( Widget w
)
202 static void done_func( w
)
208 #if defined(SelfTest)
212 while ( ! XtIsShell(w
) ) w
= XtParent(w
);
215 /* save it for later */
216 ptr
= (save_dialog
*) malloc( sizeof(save_dialog
) );
223 /* create a set of push buttons */
225 #define SpacingRatio 4 /* 3:1 button to spaces */
227 #if defined(__STDC__)
228 static Widget
create_push_buttons( Widget parent
,
233 static Widget
create_push_buttons( parent
, data
, count
)
242 base
= SpacingRatio
*count
+ 1;
243 form
= XtVaCreateManagedWidget( "buttons",
246 XmNleftAttachment
, XmATTACH_FORM
,
247 XmNrightAttachment
, XmATTACH_FORM
,
248 XmNfractionBase
, base
,
249 XmNshadowType
, XmSHADOW_ETCHED_IN
,
250 XmNshadowThickness
, 2,
251 XmNverticalSpacing
, 4,
255 while ( count
-- > 0 ) {
256 w
= XtVaCreateManagedWidget(data
->name
,
257 xmPushButtonGadgetClass
,
259 XmNtopAttachment
, XmATTACH_FORM
,
260 XmNbottomAttachment
,XmATTACH_FORM
,
261 XmNleftAttachment
, XmATTACH_POSITION
,
262 XmNleftPosition
, pos
,
263 XmNshowAsDefault
, False
,
264 XmNrightAttachment
, XmATTACH_POSITION
,
265 XmNrightPosition
, pos
+SpacingRatio
-1,
268 XtAddCallback( w
, XmNactivateCallback
, data
->cb
, 0 );
273 /* last button is 'cancel' */
274 XtVaSetValues( XtParent(form
), XmNcancelButton
, w
, 0 );
280 /* create a set of check boxes */
282 #if defined(SelfTest)
284 #if defined(__STDC__)
285 static Widget
create_check_boxes( Widget parent
,
290 static Widget
create_check_boxes( parent
, toggles
, count
)
299 base
= SpacingRatio
*count
+1;
300 form
= XtVaCreateManagedWidget( "toggles",
303 XmNleftAttachment
, XmATTACH_FORM
,
304 XmNrightAttachment
, XmATTACH_FORM
,
305 XmNfractionBase
, base
,
306 XmNverticalSpacing
, 4,
310 while ( count
-- > 0 ) {
311 XtVaCreateManagedWidget(toggles
->name
,
312 xmToggleButtonWidgetClass
,
314 XmNtopAttachment
, XmATTACH_FORM
,
315 XmNbottomAttachment
, XmATTACH_FORM
,
316 XmNleftAttachment
, XmATTACH_POSITION
,
317 XmNleftPosition
, pos
,
318 XmNrightAttachment
, XmATTACH_POSITION
,
319 XmNrightPosition
, pos
+SpacingRatio
-1,
332 /* Routines to handle the text field widget */
334 /* when the user hits 'CR' in a text widget, fire the default pushbutton */
335 #if defined(__STDC__)
336 static void text_cr( Widget w
, void *ptr
, void *ptr2
)
338 static void text_cr( w
, ptr
, ptr2
)
350 * when the user hits any other character, if we are doing incremental
351 * search, send the updated string to nvi
354 * I don't currently see any way to make this work -- incremental search
355 * is going to be really nasty. What makes it worse is that the dialog
356 * box almost certainly obscured a chunk of the text file, so there's no
357 * way to use it even if it works.
359 #if defined(__STDC__)
360 static void value_changed( Widget w
, void *ptr
, void *ptr2
)
362 static void value_changed( w
, ptr
, ptr2
)
368 /* get all the data from the root of the widget tree */
372 #if defined(SelfTest)
373 if ( incremental_search
) send_command( w
);
375 if ( __vi_incremental_search() ) send_command( w
);
381 /* Draw and display a dialog the describes nvi search capability */
383 #if defined(__STDC__)
384 static Widget
create_search_dialog( Widget parent
, String title
)
386 static Widget
create_search_dialog( parent
, title
)
391 Widget box
, form
, label
, text
, checks
, buttons
, form2
;
394 /* use an existing one? */
395 if ( dialogs
!= NULL
) {
396 box
= dialogs
->shell
;
403 box
= XtVaCreatePopupShell( title
,
404 xmDialogShellWidgetClass
,
407 XmNallowShellResize
, False
,
411 form
= XtVaCreateWidget( "form",
414 XmNverticalSpacing
, 4,
415 XmNhorizontalSpacing
, 4,
419 form2
= XtVaCreateManagedWidget( "form",
422 XmNtopAttachment
, XmATTACH_FORM
,
423 XmNleftAttachment
, XmATTACH_FORM
,
424 XmNrightAttachment
, XmATTACH_FORM
,
428 label
= XtVaCreateManagedWidget( "Pattern:",
431 XmNtopAttachment
, XmATTACH_FORM
,
432 XmNbottomAttachment
,XmATTACH_FORM
,
433 XmNleftAttachment
, XmATTACH_FORM
,
437 text
= XtVaCreateManagedWidget( PatternWidget
,
438 xmTextFieldWidgetClass
,
440 XmNtopAttachment
, XmATTACH_FORM
,
441 XmNbottomAttachment
,XmATTACH_FORM
,
442 XmNleftAttachment
, XmATTACH_WIDGET
,
443 XmNleftWidget
, label
,
444 XmNrightAttachment
, XmATTACH_FORM
,
448 XtAddCallback( text
, XmNvalueChangedCallback
, value_changed
, 0 );
450 XtAddCallback( text
, XmNactivateCallback
, text_cr
, 0 );
452 buttons
= create_push_buttons( form
, button_data
, XtNumber(button_data
) );
453 XtVaSetValues( buttons
,
454 XmNbottomAttachment
, XmATTACH_FORM
,
458 #if defined(SelfTest)
459 checks
= create_check_boxes( form
, toggle_data
, XtNumber(toggle_data
) );
461 checks
= (Widget
) __vi_create_search_toggles( form
, search_toggles
);
463 XtVaSetValues( checks
,
464 XmNtopAttachment
, XmATTACH_WIDGET
,
466 XmNbottomAttachment
, XmATTACH_WIDGET
,
467 XmNbottomWidget
, buttons
,
471 XtManageChild( form
);
476 /* Module interface to the outside world
478 * xip_show_search_dialog( parent, title )
479 * pops up a search dialog
482 * simulates a 'next' assuming that a search has been done
485 #if defined(__STDC__)
486 void __vi_show_search_dialog( Widget parent
, String title
)
488 void __vi_show_search_dialog( parent
, data
, cbs
)
493 Widget db
= create_search_dialog( parent
, title
);
496 /* we can handle getting taller and wider or narrower, but not shorter */
497 XtVaGetValues( db
, XmNheight
, &height
, 0 );
498 XtVaSetValues( db
, XmNmaxHeight
, height
, XmNminHeight
, height
, 0 );
500 /* post the dialog */
501 XtPopup( db
, XtGrabNone
);
503 /* request initial focus to the text widget */
504 XmProcessTraversal( get_child_widget( db
, PatternWidget
),
513 * PUBLIC: void __vi_search __P((Widget));
516 __vi_search(Widget w
)
522 #if defined(SelfTest)
524 #if defined(__STDC__)
525 static void show_search( Widget w
, XtPointer data
, XtPointer cbs
)
527 static void show_search( w
, data
, cbs
)
533 __vi_show_search_dialog( data
, "Search" );
536 main( int argc
, char *argv
[] )
539 Widget top_level
, rc
, button
;
542 /* create a top-level shell for the window manager */
543 top_level
= XtVaAppInitialize( &ctx
,
545 NULL
, 0, /* options */
547 argv
, /* might get modified */
552 rc
= XtVaCreateManagedWidget( "rc",
553 xmRowColumnWidgetClass
,
558 button
= XtVaCreateManagedWidget( "Pop up search dialog",
559 xmPushButtonGadgetClass
,
563 XtAddCallback( button
, XmNactivateCallback
, show_search
, rc
);
565 button
= XtVaCreateManagedWidget( "Quit",
566 xmPushButtonGadgetClass
,
570 XtAddCallback( button
, XmNactivateCallback
, exit
, 0 );
572 XtRealizeWidget(top_level
);