only clean out gs when last window goes
[nvi.git] / motif_l / m_tags.c
bloba8516681c416b8a38f322f51262875fe78b9a649
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_tags.c,v 8.7 2000/06/28 20:20:40 skimo Exp $ (Berkeley) $Date: 2000/06/28 20:20:40 $";
14 #endif /* not lint */
17 * This module implements a dialog for navigating the tag stack
19 * Interface:
20 * void __vi_show_tags_dialog( Widget parent, String title )
21 * Pops up a Tags dialog. We allow one per session. It is not modal.
23 * void __vi_push_tag( String text )
24 * void __vi_pop_tag()
25 * void __vi_clear_tag()
26 * When core changes the tag stack we will change our representation
27 * of it. When this dialog appears, we need core to send a slew of
28 * messages so we can display the current tag stack.
30 * void __vi_set_tag_text( String text )
31 * the text field in the dialog is set to the string. ideally,
32 * this should be kept in sync with the word following the caret
33 * in the current editor window
35 * To Do:
36 * The push-buttons should activate and deactivate according to
37 * the state of the tag stack and the text field.
39 * Need to send VI commands rather than strings
41 * Need IPO command to start/stop asking for the current tag stack
45 /* context */
46 #include <X11/X.h>
47 #include <X11/Intrinsic.h>
48 #include <Xm/DialogS.h>
49 #include <Xm/Form.h>
50 #include <Xm/LabelG.h>
51 #include <Xm/TextF.h>
52 #include <Xm/List.h>
53 #include <Xm/RowColumn.h>
54 #include <Xm/PushBG.h>
56 #if ! defined(SelfTest)
57 #include <sys/types.h>
58 #include <sys/queue.h>
60 #include <bitstring.h>
61 #include <stdio.h>
62 #include <string.h>
64 #include "../common/common.h"
65 #include "../ipc/ip.h"
66 #include "m_motif.h"
67 #endif
69 extern int vi_ofd;
72 /* globals */
74 static Widget db_tabs = NULL,
75 db_text,
76 db_list;
78 static Boolean active = False;
80 typedef struct {
81 String name;
82 Boolean is_default;
83 void (*cb)();
84 } ButtonData;
86 static void go_to_tag();
87 static void split_to_tag();
88 static void pop_tag();
90 static ButtonData button_data[] = {
91 { "Go To Tag", True, go_to_tag },
92 { "Split To Tag", False, split_to_tag },
93 { "Pop Tag", False, pop_tag },
97 /* manage the tags stack list */
99 void __vi_pop_tag()
101 if ( ! active ) return;
103 XmListDeletePos( db_list, 1 );
107 void __vi_clear_tag()
109 if ( ! active ) return;
111 XmListDeleteAllItems( db_list );
115 void __vi_push_tag( text )
116 String text;
118 XmString str;
120 if ( ! active ) return;
122 str = XmStringCreateSimple( text );
123 XmListAddItem( db_list, str, 1 );
124 XmStringFree( str );
128 /* create a set of push buttons */
130 #define SpacingRatio 4 /* 3:1 button to spaces */
132 #if defined(__STDC__)
133 static Widget create_push_buttons( Widget parent,
134 ButtonData *data,
135 int count
137 #else
138 static Widget create_push_buttons( parent, data, count )
139 Widget parent;
140 ButtonData *data;
141 int count;
142 #endif
144 Widget w, form;
145 int pos = 1, base;
147 base = SpacingRatio*count + 1;
148 form = XtVaCreateManagedWidget( "buttons",
149 xmFormWidgetClass,
150 parent,
151 XmNleftAttachment, XmATTACH_FORM,
152 XmNrightAttachment, XmATTACH_FORM,
153 XmNfractionBase, base,
154 XmNshadowType, XmSHADOW_ETCHED_IN,
155 XmNshadowThickness, 2,
156 XmNverticalSpacing, 4,
160 while ( count-- > 0 ) {
161 w = XtVaCreateManagedWidget(data->name,
162 xmPushButtonGadgetClass,
163 form,
164 XmNtopAttachment, XmATTACH_FORM,
165 XmNbottomAttachment,XmATTACH_FORM,
166 XmNleftAttachment, XmATTACH_POSITION,
167 XmNleftPosition, pos,
168 XmNshowAsDefault, data->is_default,
169 XmNdefaultButtonShadowThickness, data->is_default,
170 XmNrightAttachment, XmATTACH_POSITION,
171 XmNrightPosition, pos+SpacingRatio-1,
174 if ( data->is_default )
175 XtVaSetValues( form, XmNdefaultButton, w, 0 );
176 XtAddCallback( w, XmNactivateCallback, data->cb, 0 );
177 pos += SpacingRatio;
178 data++;
181 return form;
185 /* callbacks */
187 static void
188 cancel_cb()
190 #if defined(SelfTest)
191 puts( "cancelled" );
192 #endif
193 active = False;
197 static void set_text_field( w, ptr, cbs )
198 Widget w;
199 XtPointer ptr;
200 XmListCallbackStruct *cbs;
202 String str;
204 XmStringGetLtoR( cbs->item, XmSTRING_DEFAULT_CHARSET, &str );
205 XmTextFieldSetString( db_text, str );
206 XtFree( str );
210 void __vi_set_tag_text( text )
211 String text;
213 if ( active ) XmTextFieldSetString( db_text, text );
217 static void destroyed()
219 #if defined(SelfTest)
220 puts( "destroyed" );
221 #endif
223 /* some window managers destroy us upon popdown */
224 db_tabs = NULL;
225 active = False;
229 #if defined(__STDC__)
230 static void pop_tag( Widget w )
231 #else
232 static void pop_tag( w )
233 Widget w;
234 #endif
236 static String buffer = ":tagpop";
238 #if defined(SelfTest)
239 printf( "sending command <<%s>>\n", buffer );
240 __vi_pop_tag();
241 #else
242 __vi_send_command_string( buffer );
243 #endif
247 #if defined(__STDC__)
248 static void split_to_tag( Widget w )
249 #else
250 static void split_to_tag( w )
251 Widget w;
252 #endif
254 IP_BUF ipb;
255 String str;
257 str = XmTextFieldGetString( db_text );
259 #if defined(SelfTest)
260 printf( "sending command <<:Tag %s>>\n", str );
261 #else
263 * XXX
264 * This is REALLY sleazy. We pass the nul along with the
265 * string so that the core editor doesn't have to copy the
266 * string to get a nul termination. This should be fixed
267 * as part of making the editor fully 8-bit clean.
269 ipb.code = VI_TAGSPLIT;
270 ipb.str1 = str;
271 ipb.len1 = strlen(str) + 1;
272 vi_send(vi_ofd, "a", &ipb);
273 #endif
275 XtFree( str );
279 #if defined(__STDC__)
280 static void go_to_tag( Widget w )
281 #else
282 static void go_to_tag( w )
283 Widget w;
284 #endif
286 IP_BUF ipb;
287 String str;
289 str = XmTextFieldGetString( db_text );
291 #if defined(SelfTest)
292 printf( "sending command <<:tag %s>>\n", str );
293 #else
295 * XXX
296 * This is REALLY sleazy. We pass the nul along with the
297 * string so that the core editor doesn't have to copy the
298 * string to get a nul termination. This should be fixed
299 * as part of making the editor fully 8-bit clean.
301 ipb.code = VI_TAGAS;
302 ipb.str1 = str;
303 ipb.len1 = strlen(str) + 1;
304 vi_send(vi_ofd, "a", &ipb);
305 #endif
307 XtFree( str );
312 /* Draw and display a dialog the describes nvi options */
314 #if defined(__STDC__)
315 static Widget create_tags_dialog( Widget parent, String title )
316 #else
317 static Widget create_tags_dialog( parent, title )
318 Widget parent;
319 String title;
320 #endif
322 Widget box, form, form2, form3, buttons;
324 /* already built? */
325 if ( db_tabs != NULL ) return db_tabs;
327 box = XtVaCreatePopupShell( title,
328 xmDialogShellWidgetClass,
329 parent,
330 XmNtitle, title,
331 XmNallowShellResize, False,
334 XtAddCallback( box, XmNpopdownCallback, cancel_cb, 0 );
335 XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
337 form = XtVaCreateWidget( "Tags",
338 xmFormWidgetClass,
339 box,
343 buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
344 XtVaSetValues( buttons,
345 XmNbottomAttachment, XmATTACH_FORM,
349 form3 = XtVaCreateWidget( "form",
350 xmFormWidgetClass,
351 form,
352 XmNleftAttachment, XmATTACH_FORM,
353 XmNrightAttachment, XmATTACH_FORM,
354 XmNbottomAttachment, XmATTACH_WIDGET,
355 XmNbottomWidget, buttons,
359 form2 = XtVaCreateWidget( "form",
360 xmFormWidgetClass,
361 form,
362 XmNtopAttachment, XmATTACH_FORM,
363 XmNleftAttachment, XmATTACH_FORM,
364 XmNrightAttachment, XmATTACH_FORM,
365 XmNbottomAttachment, XmATTACH_WIDGET,
366 XmNbottomWidget, form3,
370 db_list = XtVaCreateManagedWidget( "list",
371 xmListWidgetClass,
372 form2,
373 XmNtopAttachment, XmATTACH_FORM,
374 XmNleftAttachment, XmATTACH_POSITION,
375 XmNleftPosition, 20,
376 XmNrightAttachment, XmATTACH_FORM,
377 XmNbottomAttachment, XmATTACH_FORM,
378 #if defined(SelfTest)
379 XmNvisibleItemCount, 5,
380 #endif
381 XmNselectionPolicy, XmSINGLE_SELECT,
384 XtAddCallback( db_list, XmNsingleSelectionCallback, set_text_field, 0 );
385 XtAddCallback( db_list, XmNdefaultActionCallback, go_to_tag, 0 );
387 XtVaCreateManagedWidget( "Tag Stack",
388 xmLabelGadgetClass,
389 form2,
390 XmNtopAttachment, XmATTACH_FORM,
391 XmNbottomAttachment, XmATTACH_FORM,
392 XmNleftAttachment, XmATTACH_FORM,
393 XmNrightAttachment, XmATTACH_POSITION,
394 XmNrightPosition, 20,
395 XmNalignment, XmALIGNMENT_END,
399 XtVaCreateManagedWidget( "Tag",
400 xmLabelGadgetClass,
401 form3,
402 XmNtopAttachment, XmATTACH_FORM,
403 XmNbottomAttachment, XmATTACH_FORM,
404 XmNleftAttachment, XmATTACH_FORM,
405 XmNrightAttachment, XmATTACH_POSITION,
406 XmNrightPosition, 20,
407 XmNalignment, XmALIGNMENT_END,
411 db_text = XtVaCreateManagedWidget( "text",
412 xmTextFieldWidgetClass,
413 form3,
414 XmNtopAttachment, XmATTACH_FORM,
415 XmNbottomAttachment, XmATTACH_FORM,
416 XmNrightAttachment, XmATTACH_FORM,
417 XmNleftAttachment, XmATTACH_POSITION,
418 XmNleftPosition, 20,
421 XtAddCallback( db_text, XmNactivateCallback, go_to_tag, 0 );
423 /* keep this global, we might destroy it later */
424 db_tabs = form;
426 /* done */
427 XtManageChild( form3 );
428 XtManageChild( form2 );
429 return form;
434 /* module entry point
435 * __vi_show_tags_dialog( parent, title )
438 #if defined(__STDC__)
439 void __vi_show_tags_dialog( Widget parent, String title )
440 #else
441 void __vi_show_tags_dialog( parent, title )
442 Widget parent;
443 String title;
444 #endif
446 Widget db = create_tags_dialog( parent, title ),
447 shell = XtParent(db);
449 XtManageChild( db );
451 /* get the current window's text */
452 __vi_set_tag_text( (String) __vi_get_word_at_caret( NULL ) );
454 /* TODO: ask vi core for the current tag stack now */
456 /* leave this guy up (or just raise it) */
457 XtPopup( shell, XtGrabNone );
458 XMapRaised( XtDisplay( shell ), XtWindow( shell ) );
460 active = True;
465 #if defined(SelfTest)
467 #if XtSpecificationRelease == 4
468 #define ArgcType Cardinal *
469 #else
470 #define ArgcType int *
471 #endif
473 static void add_a_tag( Widget w )
475 static String tags[] = { "first", "second", "this is the third" };
476 static int i = 0;
478 __vi_push_tag( tags[i] );
479 i = (i+1) % XtNumber(tags);
482 #if defined(__STDC__)
483 static void show_tags( Widget w, XtPointer data, XtPointer cbs )
484 #else
485 static void show_tags( w, data, cbs )
486 Widget w;
487 XtPointer data;
488 XtPointer cbs;
489 #endif
491 __vi_show_tags_dialog( data, "Tags" );
494 main( int argc, char *argv[] )
496 XtAppContext ctx;
497 Widget top_level, rc, button;
498 extern exit();
500 /* create a top-level shell for the window manager */
501 top_level = XtVaAppInitialize( &ctx,
502 argv[0],
503 NULL, 0, /* options */
504 (ArgcType) &argc,
505 argv, /* might get modified */
506 NULL,
507 NULL
510 rc = XtVaCreateManagedWidget( "rc",
511 xmRowColumnWidgetClass,
512 top_level,
516 button = XtVaCreateManagedWidget( "Pop up tags dialog",
517 xmPushButtonGadgetClass,
521 XtAddCallback( button, XmNactivateCallback, show_tags, rc );
523 button = XtVaCreateManagedWidget( "Add a tag",
524 xmPushButtonGadgetClass,
528 XtAddCallback( button, XmNactivateCallback, add_a_tag, rc );
530 button = XtVaCreateManagedWidget( "Quit",
531 xmPushButtonGadgetClass,
535 XtAddCallback( button, XmNactivateCallback, exit, 0 );
537 XtRealizeWidget(top_level);
538 XtAppMainLoop(ctx);
540 #endif