ex: convert line input buffer from file encoding to internal encoding
[nvi.git] / motif_l / m_search.c
blobac3c7e36784eb9d137acc3770b6ff7ea7d8b2634
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.14 2003/11/05 17:10:00 skimo Exp $ (Berkeley) $Date: 2003/11/05 17:10:00 $";
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 #undef LOCK_SUCCESS
34 #include "../common/common.h"
35 #include "../ipc/ip.h"
36 #include "m_motif.h"
38 extern int vi_ofd;
41 /* types */
43 typedef struct sds {
44 struct sds *next;
45 Widget shell;
46 } save_dialog;
48 static save_dialog *dialogs = NULL;
50 typedef struct {
51 String name;
52 void (*cb)();
53 } ButtonData;
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 },
68 { optTerminator, },
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 */
83 /* Xt utilities */
85 #if defined(__STDC__)
86 static Widget get_child_widget( Widget parent, String name )
87 #else
88 static Widget get_child_widget( parent, name )
89 Widget parent;
90 String name;
91 #endif
93 char buffer[1024];
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 )
105 #else
106 static void get_state( w )
107 Widget w;
108 #endif
110 #if defined(SelfTest)
111 int i;
112 #endif
113 Widget shell = w;
115 /* get all the data from the root of the widget tree */
116 while ( ! XtIsShell(shell) ) shell = XtParent(shell);
118 #if defined(SelfTest)
119 /* which flags? */
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 );
125 #endif
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 */
137 * next_func --
138 * Action for next button.
140 static void
141 next_func(Widget w)
143 search(w, 0);
147 * prev_func --
148 * Action for previous button.
150 static void
151 prev_func(Widget w)
153 search(w, VI_SEARCH_REV);
157 * search --
158 * Perform the search.
160 static void
161 search(Widget w, int flags)
163 IP_BUF ipb;
164 optData *opt;
165 Widget shell;
167 shell = w;
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))
176 get_state(w);
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" );
183 return;
186 ipb.str1 = pattern;
187 ipb.len1 = strlen(pattern);
189 /* Initialize the search flags based on the buttons. */
190 ipb.val1 = flags;
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 )
201 #else
202 static void done_func( w )
203 Widget w;
204 #endif
206 save_dialog *ptr;
208 #if defined(SelfTest)
209 puts( XtName(w) );
210 #endif
212 while ( ! XtIsShell(w) ) w = XtParent(w);
213 XtPopdown( w );
215 /* save it for later */
216 ptr = (save_dialog *) malloc( sizeof(save_dialog) );
217 ptr->next = dialogs;
218 ptr->shell = w;
219 dialogs = ptr;
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,
229 ButtonData *data,
230 int count
232 #else
233 static Widget create_push_buttons( parent, data, count )
234 Widget parent;
235 ButtonData *data;
236 int count;
237 #endif
239 Widget w, form;
240 int pos = 1, base;
242 base = SpacingRatio*count + 1;
243 form = XtVaCreateManagedWidget( "buttons",
244 xmFormWidgetClass,
245 parent,
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,
258 form,
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 );
269 pos += SpacingRatio;
270 data++;
273 /* last button is 'cancel' */
274 XtVaSetValues( XtParent(form), XmNcancelButton, w, 0 );
276 return form;
280 /* create a set of check boxes */
282 #if defined(SelfTest)
284 #if defined(__STDC__)
285 static Widget create_check_boxes( Widget parent,
286 ToggleData *toggles,
287 int count
289 #else
290 static Widget create_check_boxes( parent, toggles, count )
291 Widget parent;
292 ToggleData *toggles;
293 int count;
294 #endif
296 Widget form;
297 int pos = 1, base;
299 base = SpacingRatio*count +1;
300 form = XtVaCreateManagedWidget( "toggles",
301 xmFormWidgetClass,
302 parent,
303 XmNleftAttachment, XmATTACH_FORM,
304 XmNrightAttachment, XmATTACH_FORM,
305 XmNfractionBase, base,
306 XmNverticalSpacing, 4,
310 while ( count-- > 0 ) {
311 XtVaCreateManagedWidget(toggles->name,
312 xmToggleButtonWidgetClass,
313 form,
314 XmNtopAttachment, XmATTACH_FORM,
315 XmNbottomAttachment, XmATTACH_FORM,
316 XmNleftAttachment, XmATTACH_POSITION,
317 XmNleftPosition, pos,
318 XmNrightAttachment, XmATTACH_POSITION,
319 XmNrightPosition, pos+SpacingRatio-1,
322 pos += SpacingRatio;
323 ++toggles;
326 return form;
329 #endif
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 )
337 #else
338 static void text_cr( w, ptr, ptr2 )
339 Widget w;
340 void *ptr;
341 void *ptr2;
342 #endif
344 next_func( w );
348 #ifdef notdef
350 * when the user hits any other character, if we are doing incremental
351 * search, send the updated string to nvi
353 * XXX
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 )
361 #else
362 static void value_changed( w, ptr, ptr2 )
363 Widget w;
364 void *ptr;
365 void *ptr2;
366 #endif
368 /* get all the data from the root of the widget tree */
369 get_state( w );
371 /* send it along? */
372 #if defined(SelfTest)
373 if ( incremental_search ) send_command( w );
374 #else
375 if ( __vi_incremental_search() ) send_command( w );
376 #endif
378 #endif /* notdef */
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 )
385 #else
386 static Widget create_search_dialog( parent, title )
387 Widget parent;
388 String title;
389 #endif
391 Widget box, form, label, text, checks, buttons, form2;
392 save_dialog *ptr;
394 /* use an existing one? */
395 if ( dialogs != NULL ) {
396 box = dialogs->shell;
397 ptr = dialogs->next;
398 free( dialogs );
399 dialogs = ptr;
400 return box;
403 box = XtVaCreatePopupShell( title,
404 xmDialogShellWidgetClass,
405 parent,
406 XmNtitle, title,
407 XmNallowShellResize, False,
411 form = XtVaCreateWidget( "form",
412 xmFormWidgetClass,
413 box,
414 XmNverticalSpacing, 4,
415 XmNhorizontalSpacing, 4,
419 form2 = XtVaCreateManagedWidget( "form",
420 xmFormWidgetClass,
421 form,
422 XmNtopAttachment, XmATTACH_FORM,
423 XmNleftAttachment, XmATTACH_FORM,
424 XmNrightAttachment, XmATTACH_FORM,
428 label = XtVaCreateManagedWidget( "Pattern:",
429 xmLabelWidgetClass,
430 form2,
431 XmNtopAttachment, XmATTACH_FORM,
432 XmNbottomAttachment,XmATTACH_FORM,
433 XmNleftAttachment, XmATTACH_FORM,
437 text = XtVaCreateManagedWidget( PatternWidget,
438 xmTextFieldWidgetClass,
439 form2,
440 XmNtopAttachment, XmATTACH_FORM,
441 XmNbottomAttachment,XmATTACH_FORM,
442 XmNleftAttachment, XmATTACH_WIDGET,
443 XmNleftWidget, label,
444 XmNrightAttachment, XmATTACH_FORM,
447 #ifdef notdef
448 XtAddCallback( text, XmNvalueChangedCallback, value_changed, 0 );
449 #endif
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) );
460 #else
461 checks = (Widget) __vi_create_search_toggles( form, search_toggles );
462 #endif
463 XtVaSetValues( checks,
464 XmNtopAttachment, XmATTACH_WIDGET,
465 XmNtopWidget, form2,
466 XmNbottomAttachment, XmATTACH_WIDGET,
467 XmNbottomWidget, buttons,
471 XtManageChild( form );
472 return box;
476 /* Module interface to the outside world
478 * xip_show_search_dialog( parent, title )
479 * pops up a search dialog
481 * xip_next_search()
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 )
487 #else
488 void __vi_show_search_dialog( parent, data, cbs )
489 Widget parent;
490 String title;
491 #endif
493 Widget db = create_search_dialog( parent, title );
494 Dimension height;
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 ),
505 XmTRAVERSE_CURRENT
511 * __vi_search --
513 * PUBLIC: void __vi_search __P((Widget));
515 void
516 __vi_search(Widget w)
518 next_func( w );
522 #if defined(SelfTest)
524 #if defined(__STDC__)
525 static void show_search( Widget w, XtPointer data, XtPointer cbs )
526 #else
527 static void show_search( w, data, cbs )
528 Widget w;
529 XtPointer data;
530 XtPointer cbs;
531 #endif
533 __vi_show_search_dialog( data, "Search" );
536 main( int argc, char *argv[] )
538 XtAppContext ctx;
539 Widget top_level, rc, button;
540 extern exit();
542 /* create a top-level shell for the window manager */
543 top_level = XtVaAppInitialize( &ctx,
544 argv[0],
545 NULL, 0, /* options */
546 (ArgcType) &argc,
547 argv, /* might get modified */
548 NULL,
549 NULL
552 rc = XtVaCreateManagedWidget( "rc",
553 xmRowColumnWidgetClass,
554 top_level,
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);
573 XtAppMainLoop(ctx);
575 #endif