*** empty log message ***
[nvi.git] / motif_l / m_search.c
blob7687abcd0be9d919a5fc97c7ea97dc23f48286c0
1 /*-
2 * Copyright (c) 1996
3 * Rob Zimmermann. All rights reserved.
4 * Copyright (c) 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
8 */
10 #include "config.h"
12 #ifndef lint
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 $";
14 #endif /* not lint */
16 #include <sys/queue.h>
18 /* context */
19 #include <X11/X.h>
20 #include <X11/Intrinsic.h>
21 #include <Xm/DialogS.h>
22 #include <Xm/Form.h>
23 #include <Xm/Label.h>
24 #include <Xm/PushBG.h>
25 #include <Xm/TextF.h>
26 #include <Xm/ToggleB.h>
27 #include <Xm/RowColumn.h>
29 #include <bitstring.h>
30 #include <stdio.h>
31 #include <stdlib.h>
33 #include "../common/common.h"
34 #include "../ipc/ip.h"
35 #include "m_motif.h"
38 /* types */
40 typedef struct sds {
41 struct sds *next;
42 Widget shell;
43 } save_dialog;
45 static save_dialog *dialogs = NULL;
47 typedef struct {
48 String name;
49 void (*cb)();
50 } ButtonData;
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 },
65 { optTerminator, },
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 */
80 /* Xt utilities */
82 #if defined(__STDC__)
83 static Widget get_child_widget( Widget parent, String name )
84 #else
85 static Widget get_child_widget( parent, name )
86 Widget parent;
87 String name;
88 #endif
90 char buffer[1024];
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 )
102 #else
103 static void get_state( w )
104 Widget w;
105 #endif
107 #if defined(SelfTest)
108 int i;
109 #endif
110 Widget shell = w;
112 /* get all the data from the root of the widget tree */
113 while ( ! XtIsShell(shell) ) shell = XtParent(shell);
115 #if defined(SelfTest)
116 /* which flags? */
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 );
122 #endif
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 */
134 * next_func --
135 * Action for next button.
137 static void
138 next_func(w)
139 Widget w;
141 search(w, 0);
145 * prev_func --
146 * Action for previous button.
148 static void
149 prev_func(w)
150 Widget w;
152 search(w, VI_SEARCH_REV);
156 * search --
157 * Perform the search.
159 static void
160 search(w, flags)
161 Widget w;
162 int flags;
164 IP_BUF ipb;
165 optData *opt;
166 Widget shell;
168 shell = w;
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))
177 get_state(w);
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" );
184 return;
187 ipb.str1 = pattern;
188 ipb.len1 = strlen(pattern);
190 /* Initialize the search flags based on the buttons. */
191 ipb.val1 = flags;
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;
197 vi_send("a1", &ipb);
200 #if defined(__STDC__)
201 static void done_func( Widget w )
202 #else
203 static void done_func( w )
204 Widget w;
205 #endif
207 save_dialog *ptr;
209 #if defined(SelfTest)
210 puts( XtName(w) );
211 #endif
213 while ( ! XtIsShell(w) ) w = XtParent(w);
214 XtPopdown( w );
216 /* save it for later */
217 ptr = (save_dialog *) malloc( sizeof(save_dialog) );
218 ptr->next = dialogs;
219 ptr->shell = w;
220 dialogs = ptr;
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,
230 ButtonData *data,
231 int count
233 #else
234 static Widget create_push_buttons( parent, data, count )
235 Widget parent;
236 ButtonData *data;
237 int count;
238 #endif
240 Widget w, form;
241 int pos = 1, base;
243 base = SpacingRatio*count + 1;
244 form = XtVaCreateManagedWidget( "buttons",
245 xmFormWidgetClass,
246 parent,
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,
259 form,
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 );
270 pos += SpacingRatio;
271 data++;
274 /* last button is 'cancel' */
275 XtVaSetValues( XtParent(form), XmNcancelButton, w, 0 );
277 return form;
281 /* create a set of check boxes */
283 #if defined(SelfTest)
285 #if defined(__STDC__)
286 static Widget create_check_boxes( Widget parent,
287 ToggleData *toggles,
288 int count
290 #else
291 static Widget create_check_boxes( parent, toggles, count )
292 Widget parent;
293 ToggleData *toggles;
294 int count;
295 #endif
297 Widget form;
298 int pos = 1, base;
300 base = SpacingRatio*count +1;
301 form = XtVaCreateManagedWidget( "toggles",
302 xmFormWidgetClass,
303 parent,
304 XmNleftAttachment, XmATTACH_FORM,
305 XmNrightAttachment, XmATTACH_FORM,
306 XmNfractionBase, base,
307 XmNverticalSpacing, 4,
311 while ( count-- > 0 ) {
312 XtVaCreateManagedWidget(toggles->name,
313 xmToggleButtonWidgetClass,
314 form,
315 XmNtopAttachment, XmATTACH_FORM,
316 XmNbottomAttachment, XmATTACH_FORM,
317 XmNleftAttachment, XmATTACH_POSITION,
318 XmNleftPosition, pos,
319 XmNrightAttachment, XmATTACH_POSITION,
320 XmNrightPosition, pos+SpacingRatio-1,
323 pos += SpacingRatio;
324 ++toggles;
327 return form;
330 #endif
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 )
338 #else
339 static void text_cr( w, ptr, ptr2 )
340 Widget w;
341 void *ptr;
342 void *ptr2;
343 #endif
345 next_func( w );
349 #ifdef notdef
351 * when the user hits any other character, if we are doing incremental
352 * search, send the updated string to nvi
354 * XXX
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 )
362 #else
363 static void value_changed( w, ptr, ptr2 )
364 Widget w;
365 void *ptr;
366 void *ptr2;
367 #endif
369 /* get all the data from the root of the widget tree */
370 get_state( w );
372 /* send it along? */
373 #if defined(SelfTest)
374 if ( incremental_search ) send_command( w );
375 #else
376 if ( __vi_incremental_search() ) send_command( w );
377 #endif
379 #endif /* notdef */
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 )
386 #else
387 static Widget create_search_dialog( parent, title )
388 Widget parent;
389 String title;
390 #endif
392 Widget box, form, label, text, checks, buttons, form2;
393 save_dialog *ptr;
395 /* use an existing one? */
396 if ( dialogs != NULL ) {
397 box = dialogs->shell;
398 ptr = dialogs->next;
399 free( dialogs );
400 dialogs = ptr;
401 return box;
404 box = XtVaCreatePopupShell( title,
405 xmDialogShellWidgetClass,
406 parent,
407 XmNtitle, title,
408 XmNallowShellResize, False,
412 form = XtVaCreateWidget( "form",
413 xmFormWidgetClass,
414 box,
415 XmNverticalSpacing, 4,
416 XmNhorizontalSpacing, 4,
420 form2 = XtVaCreateManagedWidget( "form",
421 xmFormWidgetClass,
422 form,
423 XmNtopAttachment, XmATTACH_FORM,
424 XmNleftAttachment, XmATTACH_FORM,
425 XmNrightAttachment, XmATTACH_FORM,
429 label = XtVaCreateManagedWidget( "Pattern:",
430 xmLabelWidgetClass,
431 form2,
432 XmNtopAttachment, XmATTACH_FORM,
433 XmNbottomAttachment,XmATTACH_FORM,
434 XmNleftAttachment, XmATTACH_FORM,
438 text = XtVaCreateManagedWidget( PatternWidget,
439 xmTextFieldWidgetClass,
440 form2,
441 XmNtopAttachment, XmATTACH_FORM,
442 XmNbottomAttachment,XmATTACH_FORM,
443 XmNleftAttachment, XmATTACH_WIDGET,
444 XmNleftWidget, label,
445 XmNrightAttachment, XmATTACH_FORM,
448 #ifdef notdef
449 XtAddCallback( text, XmNvalueChangedCallback, value_changed, 0 );
450 #endif
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) );
461 #else
462 checks = (Widget) __vi_create_search_toggles( form, search_toggles );
463 #endif
464 XtVaSetValues( checks,
465 XmNtopAttachment, XmATTACH_WIDGET,
466 XmNtopWidget, form2,
467 XmNbottomAttachment, XmATTACH_WIDGET,
468 XmNbottomWidget, buttons,
472 XtManageChild( form );
473 return box;
477 /* Module interface to the outside world
479 * xip_show_search_dialog( parent, title )
480 * pops up a search dialog
482 * xip_next_search()
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 )
488 #else
489 void __vi_show_search_dialog( parent, data, cbs )
490 Widget parent;
491 String title;
492 #endif
494 Widget db = create_search_dialog( parent, title );
495 Dimension height;
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 ),
506 XmTRAVERSE_CURRENT
512 * __vi_search --
514 * PUBLIC: void __vi_search __P((Widget));
516 void
517 __vi_search( w )
518 Widget w;
520 next_func( w );
524 #if defined(SelfTest)
526 #if defined(__STDC__)
527 static void show_search( Widget w, XtPointer data, XtPointer cbs )
528 #else
529 static void show_search( w, data, cbs )
530 Widget w;
531 XtPointer data;
532 XtPointer cbs;
533 #endif
535 __vi_show_search_dialog( data, "Search" );
538 main( int argc, char *argv[] )
540 XtAppContext ctx;
541 Widget top_level, rc, button;
542 extern exit();
544 /* create a top-level shell for the window manager */
545 top_level = XtVaAppInitialize( &ctx,
546 argv[0],
547 NULL, 0, /* options */
548 (ArgcType) &argc,
549 argv, /* might get modified */
550 NULL,
551 NULL
554 rc = XtVaCreateManagedWidget( "rc",
555 xmRowColumnWidgetClass,
556 top_level,
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);
575 XtAppMainLoop(ctx);
577 #endif