add VI_C_SETTOP for scrollbar setting
[nvi.git] / motif_l / m_search.c
blobb0af0882b0418c4eb9c10b9132d0f430a3a05213
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.6 1996/12/11 20:58:25 bostic Exp $ (Berkeley) $Date: 1996/12/11 20:58:25 $";
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 "../ip/ip.h"
35 #include "ipc_extern.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 Boolean is_default;
50 void (*cb)();
51 } ButtonData;
54 #if defined(SelfTest)
56 typedef struct {
57 String name;
58 Boolean *value;
59 int flag;
60 } ToggleData;
62 static ToggleData toggle_data[] = {
63 { "Ignore Case", 0, VI_SEARCH_IC },
64 { "Incremental", 0, VI_SEARCH_INCR }
65 { "Literal", 0, VI_SEARCH_LIT },
66 { "Wrap End Of File", 0, VI_SEARCH_WR },
69 #endif
72 /* globals and constants */
74 static String PatternWidget = "text";
76 static void done_func __P((Widget));
77 static void next_func __P((Widget));
78 static void prev_func __P((Widget));
79 static void search __P((Widget, int));
81 static ButtonData button_data[] = {
82 { "Next", True, next_func },
83 { "Previous", False, prev_func },
84 { "Cancel", False, done_func }
87 static String pattern = NULL;
90 /* Xt utilities */
92 #if defined(__STDC__)
93 static Widget get_child_widget( Widget parent, String name )
94 #else
95 static Widget get_child_widget( parent, name )
96 Widget parent;
97 String name;
98 #endif
100 char buffer[1024];
102 strcpy( buffer, "*" );
103 strcat( buffer, name );
104 return XtNameToWidget( parent, buffer );
108 #if defined(__STDC__)
109 static String get_widget_string( Widget w, String resource )
110 #else
111 static String get_widget_string( w, resource )
112 Widget w;
113 String resource;
114 #endif
116 XmString xmstr;
117 String str;
119 XtVaGetValues( w, resource, &xmstr, 0 );
120 XmStringGetLtoR( xmstr, XmSTRING_DEFAULT_CHARSET, &str );
121 XmStringFree( xmstr );
123 return str;
127 /* sync the global state */
129 #if defined(__STDC__)
130 static void get_state( Widget w )
131 #else
132 static void get_state( w )
133 Widget w;
134 #endif
136 int i;
137 String str;
138 Widget shell = w;
140 /* get all the data from the root of the widget tree */
141 while ( ! XtIsShell(shell) ) shell = XtParent(shell);
143 #if defined(SelfTest)
144 /* which flags? */
145 for (i=0; i<XtNumber(toggle_data); i++) {
146 if (( w = get_child_widget( shell, toggle_data[i].name )) != NULL ) {
147 XtVaGetValues( w, XmNset, &toggle_data[i].value, 0 );
150 #endif
152 /* what's the pattern? */
153 if (( w = get_child_widget( shell, PatternWidget )) != NULL ) {
154 if ( pattern != NULL ) XtFree( pattern );
155 pattern = XmTextFieldGetString( w );
160 /* Translate the user's actions into nvi commands */
162 * next_func --
163 * Action for next button.
165 static void
166 next_func(w)
167 Widget w;
169 search(w, 0);
173 * prev_func --
174 * Action for previous button.
176 static void
177 prev_func(w)
178 Widget w;
180 search(w, VI_SEARCH_REV);
184 * search --
185 * Perform the search.
187 static void
188 search(w, flags)
189 Widget w;
190 int flags;
192 IP_BUF ipb;
193 int i;
195 /* get current data from the root of the widget tree? */
196 if ( w != NULL ) get_state( w );
198 ipb.str = pattern;
199 ipb.len = strlen(pattern);
201 #if defined(SelfTest)
202 /* initialize the search flags based on the buttons. */
203 ipb.val1 = flags;
204 for (i=0; i<XtNumber(toggle_data); i++) {
205 if (toggle_data[i].value)
206 ipb.val1 |= toggle_data[i].flag;
208 #endif
210 ipb.code = VI_C_SEARCH;
211 __vi_send("1s", &ipb);
214 #if defined(__STDC__)
215 static void done_func( Widget w )
216 #else
217 static void done_func( w )
218 Widget w;
219 #endif
221 save_dialog *ptr;
223 #if defined(SelfTest)
224 puts( XtName(w) );
225 #endif
227 while ( ! XtIsShell(w) ) w = XtParent(w);
228 XtPopdown( w );
230 /* save it for later */
231 ptr = (save_dialog *) malloc( sizeof(save_dialog) );
232 ptr->next = dialogs;
233 ptr->shell = w;
234 dialogs = ptr;
238 /* create a set of push buttons */
240 #define SpacingRatio 4 /* 3:1 button to spaces */
242 #if defined(__STDC__)
243 static Widget create_push_buttons( Widget parent,
244 ButtonData *data,
245 int count
247 #else
248 static Widget create_push_buttons( parent, data, count )
249 Widget parent;
250 ButtonData *data;
251 int count;
252 #endif
254 Widget w, form;
255 int pos = 1, base;
257 base = SpacingRatio*count + 1;
258 form = XtVaCreateManagedWidget( "buttons",
259 xmFormWidgetClass,
260 parent,
261 XmNleftAttachment, XmATTACH_FORM,
262 XmNrightAttachment, XmATTACH_FORM,
263 XmNfractionBase, base,
264 XmNshadowType, XmSHADOW_ETCHED_IN,
265 XmNshadowThickness, 2,
266 XmNverticalSpacing, 4,
270 while ( count-- > 0 ) {
271 w = XtVaCreateManagedWidget(data->name,
272 xmPushButtonGadgetClass,
273 form,
274 XmNtopAttachment, XmATTACH_FORM,
275 XmNbottomAttachment,XmATTACH_FORM,
276 XmNleftAttachment, XmATTACH_POSITION,
277 XmNleftPosition, pos,
278 XmNshowAsDefault, data->is_default,
279 XmNdefaultButtonShadowThickness, data->is_default,
280 XmNrightAttachment, XmATTACH_POSITION,
281 XmNrightPosition, pos+SpacingRatio-1,
284 if ( data->is_default )
285 XtVaSetValues( form, XmNdefaultButton, w, 0 );
286 XtAddCallback( w, XmNactivateCallback, data->cb, 0 );
287 pos += SpacingRatio;
288 data++;
291 return form;
295 /* create a set of check boxes */
297 #if defined(SelfTest)
299 #if defined(__STDC__)
300 static Widget create_check_boxes( Widget parent,
301 ToggleData *toggles,
302 int count
304 #else
305 static Widget create_check_boxes( parent, toggles, count )
306 Widget parent;
307 ToggleData *toggles;
308 int count;
309 #endif
311 Widget form;
312 int pos = 1, base;
314 base = SpacingRatio*count +1;
315 form = XtVaCreateManagedWidget( "toggles",
316 xmFormWidgetClass,
317 parent,
318 XmNleftAttachment, XmATTACH_FORM,
319 XmNrightAttachment, XmATTACH_FORM,
320 XmNfractionBase, base,
321 XmNverticalSpacing, 4,
325 while ( count-- > 0 ) {
326 XtVaCreateManagedWidget(toggles->name,
327 xmToggleButtonWidgetClass,
328 form,
329 XmNtopAttachment, XmATTACH_FORM,
330 XmNbottomAttachment, XmATTACH_FORM,
331 XmNleftAttachment, XmATTACH_POSITION,
332 XmNleftPosition, pos,
333 XmNrightAttachment, XmATTACH_POSITION,
334 XmNrightPosition, pos+SpacingRatio-1,
337 pos += SpacingRatio;
338 ++toggles;
341 return form;
344 #endif
347 /* Routines to handle the text field widget */
349 /* when the user hits 'CR' in a text widget, fire the default pushbutton */
350 #if defined(__STDC__)
351 static void text_cr( Widget w, void *ptr, void *ptr2 )
352 #else
353 static void text_cr( w, ptr, ptr2 )
354 Widget w;
355 void *ptr;
356 void *ptr2;
357 #endif
359 next_func( w );
363 #ifdef notdef
365 * when the user hits any other character, if we are doing incremental
366 * search, send the updated string to nvi
368 * XXX
369 * I don't currently see any way to make this work -- incremental search
370 * is going to be really nasty. What makes it worse is that the dialog
371 * box almost certainly obscured a chunk of the text file, so there's no
372 * way to use it even if it works.
374 #if defined(__STDC__)
375 static void value_changed( Widget w, void *ptr, void *ptr2 )
376 #else
377 static void value_changed( w, ptr, ptr2 )
378 Widget w;
379 void *ptr;
380 void *ptr2;
381 #endif
383 /* get all the data from the root of the widget tree */
384 get_state( w );
386 /* send it along? */
387 #if defined(SelfTest)
388 if ( incremental_search ) send_command( w );
389 #else
390 if ( __vi_incremental_search() ) send_command( w );
391 #endif
393 #endif /* notdef */
396 /* Draw and display a dialog the describes nvi search capability */
398 #if defined(__STDC__)
399 static Widget create_search_dialog( Widget parent, String title )
400 #else
401 static Widget create_search_dialog( parent, title )
402 Widget parent;
403 String title;
404 #endif
406 Widget box, form, label, text, checks, buttons, form2;
407 save_dialog *ptr;
409 /* use an existing one? */
410 if ( dialogs != NULL ) {
411 box = dialogs->shell;
412 ptr = dialogs->next;
413 free( dialogs );
414 dialogs = ptr;
415 return box;
418 box = XtVaCreatePopupShell( title,
419 xmDialogShellWidgetClass,
420 parent,
421 XmNtitle, title,
422 XmNallowShellResize, False,
426 form = XtVaCreateWidget( "form",
427 xmFormWidgetClass,
428 box,
429 XmNverticalSpacing, 4,
430 XmNhorizontalSpacing, 4,
434 form2 = XtVaCreateManagedWidget( "form",
435 xmFormWidgetClass,
436 form,
437 XmNtopAttachment, XmATTACH_FORM,
438 XmNleftAttachment, XmATTACH_FORM,
439 XmNrightAttachment, XmATTACH_FORM,
443 label = XtVaCreateManagedWidget( "Pattern:",
444 xmLabelWidgetClass,
445 form2,
446 XmNtopAttachment, XmATTACH_FORM,
447 XmNbottomAttachment,XmATTACH_FORM,
448 XmNleftAttachment, XmATTACH_FORM,
452 text = XtVaCreateManagedWidget( PatternWidget,
453 xmTextFieldWidgetClass,
454 form2,
455 XmNtopAttachment, XmATTACH_FORM,
456 XmNbottomAttachment,XmATTACH_FORM,
457 XmNleftAttachment, XmATTACH_WIDGET,
458 XmNleftWidget, label,
459 XmNrightAttachment, XmATTACH_FORM,
462 #ifdef notdef
463 XtAddCallback( text, XmNvalueChangedCallback, value_changed, 0 );
464 #endif
465 XtAddCallback( text, XmNactivateCallback, text_cr, 0 );
467 buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
468 XtVaSetValues( buttons,
469 XmNbottomAttachment, XmATTACH_FORM,
473 #if defined(SelfTest)
474 checks = create_check_boxes( form, toggle_data, XtNumber(toggle_data) );
475 #else
476 checks = (Widget) __vi_create_search_toggles( form );
477 #endif
478 XtVaSetValues( checks,
479 XmNtopAttachment, XmATTACH_WIDGET,
480 XmNtopWidget, form2,
481 XmNbottomAttachment, XmATTACH_WIDGET,
482 XmNbottomWidget, buttons,
486 XtManageChild( form );
487 return box;
491 /* Module interface to the outside world
493 * xip_show_search_dialog( parent, title )
494 * pops up a search dialog
496 * xip_next_search()
497 * simulates a 'next' assuming that a search has been done
500 #if defined(__STDC__)
501 void __vi_show_search_dialog( Widget parent, String title )
502 #else
503 void __vi_show_search_dialog( parent, data, cbs )
504 Widget parent;
505 String title;
506 #endif
508 Widget db = create_search_dialog( parent, title );
509 Dimension height;
511 /* we can handle getting taller and wider or narrower, but not shorter */
512 XtVaGetValues( db, XmNheight, &height, 0 );
513 XtVaSetValues( db, XmNmaxHeight, height, XmNminHeight, height, 0 );
515 /* post the dialog */
516 XtPopup( db, XtGrabNone );
518 /* request initial focus to the text widget */
519 XmProcessTraversal( get_child_widget( db, PatternWidget ),
520 XmTRAVERSE_CURRENT
526 * __vi_search --
528 * PUBLIC: void __vi_search __P((void));
530 void
531 __vi_search()
533 next_func( NULL );
537 #if defined(SelfTest)
539 #if defined(__STDC__)
540 static void show_search( Widget w, XtPointer data, XtPointer cbs )
541 #else
542 static void show_search( w, data, cbs )
543 Widget w;
544 XtPointer data;
545 XtPointer cbs;
546 #endif
548 __vi_show_search_dialog( data, "Search" );
551 main( int argc, char *argv[] )
553 XtAppContext ctx;
554 Widget top_level, rc, button;
555 extern exit();
557 /* create a top-level shell for the window manager */
558 top_level = XtVaAppInitialize( &ctx,
559 argv[0],
560 NULL, 0, /* options */
561 (ArgcType) &argc,
562 argv, /* might get modified */
563 NULL,
564 NULL
567 rc = XtVaCreateManagedWidget( "rc",
568 xmRowColumnWidgetClass,
569 top_level,
573 button = XtVaCreateManagedWidget( "Pop up search dialog",
574 xmPushButtonGadgetClass,
578 XtAddCallback( button, XmNactivateCallback, show_search, rc );
580 button = XtVaCreateManagedWidget( "Quit",
581 xmPushButtonGadgetClass,
585 XtAddCallback( button, XmNactivateCallback, exit, 0 );
587 XtRealizeWidget(top_level);
588 XtAppMainLoop(ctx);
591 #endif