/* $NetBSD: m_search.c,v 1.1.1.2 2008/05/18 14:31:28 aymeric Exp $ */ /*- * Copyright (c) 1996 * Rob Zimmermann. All rights reserved. * Copyright (c) 1996 * Keith Bostic. All rights reserved. * * See the LICENSE file for redistribution information. */ #include "config.h" #ifndef lint 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"; #endif /* not lint */ #include /* context */ #include #include #include #include #include #include #include #include #include #include #include #include #undef LOCK_SUCCESS #include "../common/common.h" #include "../ipc/ip.h" #include "m_motif.h" extern int vi_ofd; /* types */ typedef struct sds { struct sds *next; Widget shell; } save_dialog; static save_dialog *dialogs = NULL; typedef struct { String name; void (*cb)(); } ButtonData; /* globals and constants */ static String PatternWidget = "text"; static String pattern = NULL; static optData search_toggles[] = { { optToggle, "extended", NULL, VI_SEARCH_EXT }, { optToggle, "iclower", NULL, VI_SEARCH_ICL }, { optToggle, "ignorecase", NULL, VI_SEARCH_IC }, { optToggle, "literal", NULL, VI_SEARCH_LIT }, { optToggle, "searchincr", NULL, VI_SEARCH_INCR }, { optToggle, "wrapscan", NULL, VI_SEARCH_WR }, { optTerminator, }, }; static void done_func __P((Widget)); static void next_func __P((Widget)); static void prev_func __P((Widget)); static void search __P((Widget, int)); static ButtonData button_data[] = { { "Next", next_func }, { "Previous", prev_func }, { "Cancel", done_func } /* always last */ }; /* Xt utilities */ #if defined(__STDC__) static Widget get_child_widget( Widget parent, String name ) #else static Widget get_child_widget( parent, name ) Widget parent; String name; #endif { char buffer[1024]; strcpy( buffer, "*" ); strcat( buffer, name ); return XtNameToWidget( parent, buffer ); } /* sync the global state */ #if defined(__STDC__) static void get_state( Widget w ) #else static void get_state( w ) Widget w; #endif { #if defined(SelfTest) int i; #endif Widget shell = w; /* get all the data from the root of the widget tree */ while ( ! XtIsShell(shell) ) shell = XtParent(shell); #if defined(SelfTest) /* which flags? */ for (i=0; ikind != optTerminator; ++opt) if (opt->value != NULL) ipb.val1 |= opt->flags; ipb.code = VI_C_SEARCH; vi_send(vi_ofd, "a1", &ipb); } #if defined(__STDC__) static void done_func( Widget w ) #else static void done_func( w ) Widget w; #endif { save_dialog *ptr; #if defined(SelfTest) puts( XtName(w) ); #endif while ( ! XtIsShell(w) ) w = XtParent(w); XtPopdown( w ); /* save it for later */ ptr = (save_dialog *) malloc( sizeof(save_dialog) ); ptr->next = dialogs; ptr->shell = w; dialogs = ptr; } /* create a set of push buttons */ #define SpacingRatio 4 /* 3:1 button to spaces */ #if defined(__STDC__) static Widget create_push_buttons( Widget parent, ButtonData *data, int count ) #else static Widget create_push_buttons( parent, data, count ) Widget parent; ButtonData *data; int count; #endif { Widget w, form; int pos = 1, base; base = SpacingRatio*count + 1; form = XtVaCreateManagedWidget( "buttons", xmFormWidgetClass, parent, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNfractionBase, base, XmNshadowType, XmSHADOW_ETCHED_IN, XmNshadowThickness, 2, XmNverticalSpacing, 4, 0 ); while ( count-- > 0 ) { w = XtVaCreateManagedWidget(data->name, xmPushButtonGadgetClass, form, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment,XmATTACH_FORM, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, pos, XmNshowAsDefault, False, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, pos+SpacingRatio-1, 0 ); XtAddCallback( w, XmNactivateCallback, data->cb, 0 ); pos += SpacingRatio; data++; } /* last button is 'cancel' */ XtVaSetValues( XtParent(form), XmNcancelButton, w, 0 ); return form; } /* create a set of check boxes */ #if defined(SelfTest) #if defined(__STDC__) static Widget create_check_boxes( Widget parent, ToggleData *toggles, int count ) #else static Widget create_check_boxes( parent, toggles, count ) Widget parent; ToggleData *toggles; int count; #endif { Widget form; int pos = 1, base; base = SpacingRatio*count +1; form = XtVaCreateManagedWidget( "toggles", xmFormWidgetClass, parent, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNfractionBase, base, XmNverticalSpacing, 4, 0 ); while ( count-- > 0 ) { XtVaCreateManagedWidget(toggles->name, xmToggleButtonWidgetClass, form, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, pos, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, pos+SpacingRatio-1, 0 ); pos += SpacingRatio; ++toggles; } return form; } #endif /* Routines to handle the text field widget */ /* when the user hits 'CR' in a text widget, fire the default pushbutton */ #if defined(__STDC__) static void text_cr( Widget w, void *ptr, void *ptr2 ) #else static void text_cr( w, ptr, ptr2 ) Widget w; void *ptr; void *ptr2; #endif { next_func( w ); } #ifdef notdef /* * when the user hits any other character, if we are doing incremental * search, send the updated string to nvi * * XXX * I don't currently see any way to make this work -- incremental search * is going to be really nasty. What makes it worse is that the dialog * box almost certainly obscured a chunk of the text file, so there's no * way to use it even if it works. */ #if defined(__STDC__) static void value_changed( Widget w, void *ptr, void *ptr2 ) #else static void value_changed( w, ptr, ptr2 ) Widget w; void *ptr; void *ptr2; #endif { /* get all the data from the root of the widget tree */ get_state( w ); /* send it along? */ #if defined(SelfTest) if ( incremental_search ) send_command( w ); #else if ( __vi_incremental_search() ) send_command( w ); #endif } #endif /* notdef */ /* Draw and display a dialog the describes nvi search capability */ #if defined(__STDC__) static Widget create_search_dialog( Widget parent, String title ) #else static Widget create_search_dialog( parent, title ) Widget parent; String title; #endif { Widget box, form, label, text, checks, buttons, form2; save_dialog *ptr; /* use an existing one? */ if ( dialogs != NULL ) { box = dialogs->shell; ptr = dialogs->next; free( dialogs ); dialogs = ptr; return box; } box = XtVaCreatePopupShell( title, xmDialogShellWidgetClass, parent, XmNtitle, title, XmNallowShellResize, False, 0 ); form = XtVaCreateWidget( "form", xmFormWidgetClass, box, XmNverticalSpacing, 4, XmNhorizontalSpacing, 4, 0 ); form2 = XtVaCreateManagedWidget( "form", xmFormWidgetClass, form, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, 0 ); label = XtVaCreateManagedWidget( "Pattern:", xmLabelWidgetClass, form2, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment,XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, 0 ); text = XtVaCreateManagedWidget( PatternWidget, xmTextFieldWidgetClass, form2, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment,XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, label, XmNrightAttachment, XmATTACH_FORM, 0 ); #ifdef notdef XtAddCallback( text, XmNvalueChangedCallback, value_changed, 0 ); #endif XtAddCallback( text, XmNactivateCallback, text_cr, 0 ); buttons = create_push_buttons( form, button_data, XtNumber(button_data) ); XtVaSetValues( buttons, XmNbottomAttachment, XmATTACH_FORM, 0 ); #if defined(SelfTest) checks = create_check_boxes( form, toggle_data, XtNumber(toggle_data) ); #else checks = (Widget) __vi_create_search_toggles( form, search_toggles ); #endif XtVaSetValues( checks, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, form2, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, buttons, 0 ); XtManageChild( form ); return box; } /* Module interface to the outside world * * xip_show_search_dialog( parent, title ) * pops up a search dialog * * xip_next_search() * simulates a 'next' assuming that a search has been done */ #if defined(__STDC__) void __vi_show_search_dialog( Widget parent, String title ) #else void __vi_show_search_dialog( parent, data, cbs ) Widget parent; String title; #endif { Widget db = create_search_dialog( parent, title ); Dimension height; /* we can handle getting taller and wider or narrower, but not shorter */ XtVaGetValues( db, XmNheight, &height, 0 ); XtVaSetValues( db, XmNmaxHeight, height, XmNminHeight, height, 0 ); /* post the dialog */ XtPopup( db, XtGrabNone ); /* request initial focus to the text widget */ XmProcessTraversal( get_child_widget( db, PatternWidget ), XmTRAVERSE_CURRENT ); } /* * __vi_search -- * * PUBLIC: void __vi_search __P((Widget)); */ void __vi_search(Widget w) { next_func( w ); } #if defined(SelfTest) #if defined(__STDC__) static void show_search( Widget w, XtPointer data, XtPointer cbs ) #else static void show_search( w, data, cbs ) Widget w; XtPointer data; XtPointer cbs; #endif { __vi_show_search_dialog( data, "Search" ); } main( int argc, char *argv[] ) { XtAppContext ctx; Widget top_level, rc, button; extern exit(); /* create a top-level shell for the window manager */ top_level = XtVaAppInitialize( &ctx, argv[0], NULL, 0, /* options */ (ArgcType) &argc, argv, /* might get modified */ NULL, NULL ); rc = XtVaCreateManagedWidget( "rc", xmRowColumnWidgetClass, top_level, 0 ); button = XtVaCreateManagedWidget( "Pop up search dialog", xmPushButtonGadgetClass, rc, 0 ); XtAddCallback( button, XmNactivateCallback, show_search, rc ); button = XtVaCreateManagedWidget( "Quit", xmPushButtonGadgetClass, rc, 0 ); XtAddCallback( button, XmNactivateCallback, exit, 0 ); XtRealizeWidget(top_level); XtAppMainLoop(ctx); } #endif