Initial revision
[nvi.git] / motif_l / m_tags.c
blob899377d8a06b1e063cd5d25ebbe438d054c29f8b
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.1 1996/12/11 19:34:33 bostic Exp $ (Berkeley) $Date: 1996/12/11 19:34:33 $";
14 #endif /* not lint */
16 /* This module implements a dialog for navigating the tag stack
18 * Interface:
19 * void __vi_show_tags_dialog( Widget parent, String title )
20 * Pops up a Tags dialog. We allow one per session. It is not modal.
22 * void __vi_push_tag( String text )
23 * void __vi_pop_tag()
24 * void __vi_clear_tag()
25 * When core changes the tag stack we will change our representation
26 * of it. When this dialog appears, we need core to send a slew of
27 * messages so we can display the current tag stack.
29 * void __vi_set_tag_text( String text )
30 * the text field in the dialog is set to the string. ideally,
31 * this should be kept in sync with the word following the caret
32 * in the current editor window
34 * To Do:
35 * The push-buttons should activate and deactivate according to
36 * the state of the tag stack and the text field.
38 * Need to send VI commands rather than strings
40 * Need IPO command to start/stop asking for the current tag stack
44 /* context */
45 #include <X11/X.h>
46 #include <X11/Intrinsic.h>
47 #include <Xm/DialogS.h>
48 #include <Xm/Form.h>
49 #include <Xm/LabelG.h>
50 #include <Xm/TextF.h>
51 #include <Xm/List.h>
52 #include <Xm/RowColumn.h>
53 #include <Xm/PushBG.h>
55 #if ! defined(SelfTest)
56 #include <stdio.h>
57 #include <bitstring.h>
58 #include <sys/types.h>
59 #include <sys/queue.h>
60 #include <string.h>
61 #include "../common/common.h"
62 #include "../ip_vi/ip.h"
63 #endif
66 /* globals */
68 static Widget db_tabs = NULL,
69 db_text,
70 db_list;
72 static Boolean active = False;
74 typedef struct {
75 String name;
76 Boolean is_default;
77 void (*cb)();
78 } ButtonData;
80 static void go_to_tag();
81 static void split_to_tag();
82 static void pop_tag();
84 static ButtonData button_data[] = {
85 { "Go To Tag", True, go_to_tag },
86 { "Split To Tag", False, split_to_tag },
87 { "Pop Tag", False, pop_tag },
91 /* manage the tags stack list */
93 void __vi_pop_tag()
95 if ( ! active ) return;
97 XmListDeletePos( db_list, 1 );
101 void __vi_clear_tag()
103 if ( ! active ) return;
105 XmListDeleteAllItems( db_list );
109 void __vi_push_tag( text )
110 String text;
112 XmString str;
114 if ( ! active ) return;
116 str = XmStringCreateSimple( text );
117 XmListAddItem( db_list, str, 1 );
118 XmStringFree( str );
122 /* create a set of push buttons */
124 #define SpacingRatio 4 /* 3:1 button to spaces */
126 #if defined(__STDC__)
127 static Widget create_push_buttons( Widget parent,
128 ButtonData *data,
129 int count
131 #else
132 static Widget create_push_buttons( parent, data, count )
133 Widget parent;
134 ButtonData *data;
135 int count;
136 #endif
138 Widget w, form;
139 int pos = 1, base;
141 base = SpacingRatio*count + 1;
142 form = XtVaCreateManagedWidget( "buttons",
143 xmFormWidgetClass,
144 parent,
145 XmNleftAttachment, XmATTACH_FORM,
146 XmNrightAttachment, XmATTACH_FORM,
147 XmNfractionBase, base,
148 XmNshadowType, XmSHADOW_ETCHED_IN,
149 XmNshadowThickness, 2,
150 XmNverticalSpacing, 4,
154 while ( count-- > 0 ) {
155 w = XtVaCreateManagedWidget(data->name,
156 xmPushButtonGadgetClass,
157 form,
158 XmNtopAttachment, XmATTACH_FORM,
159 XmNbottomAttachment,XmATTACH_FORM,
160 XmNleftAttachment, XmATTACH_POSITION,
161 XmNleftPosition, pos,
162 XmNshowAsDefault, data->is_default,
163 XmNdefaultButtonShadowThickness, data->is_default,
164 XmNrightAttachment, XmATTACH_POSITION,
165 XmNrightPosition, pos+SpacingRatio-1,
168 if ( data->is_default )
169 XtVaSetValues( form, XmNdefaultButton, w, 0 );
170 XtAddCallback( w, XmNactivateCallback, data->cb, 0 );
171 pos += SpacingRatio;
172 data++;
175 return form;
179 /* callbacks */
181 void cancel_cb()
183 #if defined(SelfTest)
184 puts( "cancelled" );
185 #endif
186 active = False;
190 static void set_text_field( w, ptr, cbs )
191 Widget w;
192 XtPointer ptr;
193 XmListCallbackStruct *cbs;
195 String str;
197 XmStringGetLtoR( cbs->item, XmSTRING_DEFAULT_CHARSET, &str );
198 XmTextFieldSetString( db_text, str );
199 XtFree( str );
203 void __vi_set_tag_text( text )
204 String text;
206 if ( active ) XmTextFieldSetString( db_text, text );
210 static void destroyed()
212 #if defined(SelfTest)
213 puts( "destroyed" );
214 #endif
216 /* some window managers destroy us upon popdown */
217 db_tabs = NULL;
218 active = False;
222 #if defined(__STDC__)
223 static void pop_tag( Widget w )
224 #else
225 static void pop_tag( w )
226 Widget w;
227 #endif
229 static String buffer = ":tagpop";
231 #if defined(SelfTest)
232 printf( "sending command <<%s>>\n", buffer );
233 __vi_pop_tag();
234 #else
235 __vi_send_command_string( buffer );
236 #endif
240 #if defined(__STDC__)
241 static void split_to_tag( Widget w )
242 #else
243 static void split_to_tag( w )
244 Widget w;
245 #endif
247 IP_BUF ipb;
248 String str;
250 str = XmTextFieldGetString( db_text );
252 #if defined(SelfTest)
253 printf( "sending command <<:Tag %s>>\n", str );
254 #else
256 * XXX
257 * This is REALLY sleazy. We pass the nul along with the
258 * string so that the core editor doesn't have to copy the
259 * string to get a nul termination. This should be fixed
260 * as part of making the editor fully 8-bit clean.
262 ipb.code = VI_TAGSPLIT;
263 ipb.str = str;
264 ipb.len = strlen(str) + 1;
265 __vi_send("s", &ipb);
266 #endif
268 XtFree( str );
272 #if defined(__STDC__)
273 static void go_to_tag( Widget w )
274 #else
275 static void go_to_tag( w )
276 Widget w;
277 #endif
279 IP_BUF ipb;
280 String str;
282 str = XmTextFieldGetString( db_text );
284 #if defined(SelfTest)
285 printf( "sending command <<:tag %s>>\n", str );
286 #else
288 * XXX
289 * This is REALLY sleazy. We pass the nul along with the
290 * string so that the core editor doesn't have to copy the
291 * string to get a nul termination. This should be fixed
292 * as part of making the editor fully 8-bit clean.
294 ipb.code = VI_TAGAS;
295 ipb.str = str;
296 ipb.len = strlen(str) + 1;
297 __vi_send("s", &ipb);
298 #endif
300 XtFree( str );
305 /* Draw and display a dialog the describes nvi options */
307 #if defined(__STDC__)
308 static Widget create_tags_dialog( Widget parent, String title )
309 #else
310 static Widget create_tags_dialog( parent, title )
311 Widget parent;
312 String title;
313 #endif
315 Widget box, form, form2, form3, buttons;
317 /* already built? */
318 if ( db_tabs != NULL ) return db_tabs;
320 box = XtVaCreatePopupShell( title,
321 xmDialogShellWidgetClass,
322 parent,
323 XmNtitle, title,
324 XmNallowShellResize, False,
327 XtAddCallback( box, XmNpopdownCallback, cancel_cb, 0 );
328 XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
330 form = XtVaCreateWidget( "Tags",
331 xmFormWidgetClass,
332 box,
336 buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
337 XtVaSetValues( buttons,
338 XmNbottomAttachment, XmATTACH_FORM,
342 form3 = XtVaCreateWidget( "form",
343 xmFormWidgetClass,
344 form,
345 XmNleftAttachment, XmATTACH_FORM,
346 XmNrightAttachment, XmATTACH_FORM,
347 XmNbottomAttachment, XmATTACH_WIDGET,
348 XmNbottomWidget, buttons,
352 form2 = XtVaCreateWidget( "form",
353 xmFormWidgetClass,
354 form,
355 XmNtopAttachment, XmATTACH_FORM,
356 XmNleftAttachment, XmATTACH_FORM,
357 XmNrightAttachment, XmATTACH_FORM,
358 XmNbottomAttachment, XmATTACH_WIDGET,
359 XmNbottomWidget, form3,
363 db_list = XtVaCreateManagedWidget( "list",
364 xmListWidgetClass,
365 form2,
366 XmNtopAttachment, XmATTACH_FORM,
367 XmNleftAttachment, XmATTACH_POSITION,
368 XmNleftPosition, 20,
369 XmNrightAttachment, XmATTACH_FORM,
370 XmNbottomAttachment, XmATTACH_FORM,
371 #if defined(SelfTest)
372 XmNvisibleItemCount, 5,
373 #endif
374 XmNselectionPolicy, XmSINGLE_SELECT,
377 XtAddCallback( db_list, XmNsingleSelectionCallback, set_text_field, 0 );
378 XtAddCallback( db_list, XmNdefaultActionCallback, go_to_tag, 0 );
380 XtVaCreateManagedWidget( "Tag Stack",
381 xmLabelGadgetClass,
382 form2,
383 XmNtopAttachment, XmATTACH_FORM,
384 XmNbottomAttachment, XmATTACH_FORM,
385 XmNleftAttachment, XmATTACH_FORM,
386 XmNrightAttachment, XmATTACH_POSITION,
387 XmNrightPosition, 20,
388 XmNalignment, XmALIGNMENT_END,
392 XtVaCreateManagedWidget( "Tag",
393 xmLabelGadgetClass,
394 form3,
395 XmNtopAttachment, XmATTACH_FORM,
396 XmNbottomAttachment, XmATTACH_FORM,
397 XmNleftAttachment, XmATTACH_FORM,
398 XmNrightAttachment, XmATTACH_POSITION,
399 XmNrightPosition, 20,
400 XmNalignment, XmALIGNMENT_END,
404 db_text = XtVaCreateManagedWidget( "text",
405 xmTextFieldWidgetClass,
406 form3,
407 XmNtopAttachment, XmATTACH_FORM,
408 XmNbottomAttachment, XmATTACH_FORM,
409 XmNrightAttachment, XmATTACH_FORM,
410 XmNleftAttachment, XmATTACH_POSITION,
411 XmNleftPosition, 20,
414 XtAddCallback( db_text, XmNactivateCallback, go_to_tag, 0 );
416 /* keep this global, we might destroy it later */
417 db_tabs = form;
419 /* done */
420 XtManageChild( form3 );
421 XtManageChild( form2 );
422 return form;
427 /* module entry point
428 * __vi_show_tags_dialog( parent, title )
431 #if defined(__STDC__)
432 void __vi_show_tags_dialog( Widget parent, String title )
433 #else
434 void __vi_show_tags_dialog( parent, title )
435 Widget parent;
436 String title;
437 #endif
439 Widget db = create_tags_dialog( parent, title ),
440 shell = XtParent(db);
442 XtManageChild( db );
444 /* get the current window's text */
445 __vi_set_tag_text( (String) __vi_get_word_at_caret( NULL ) );
447 /* TODO: ask vi core for the current tag stack now */
449 /* leave this guy up (or just raise it) */
450 XtPopup( shell, XtGrabNone );
451 XMapRaised( XtDisplay( shell ), XtWindow( shell ) );
453 active = True;
458 #if defined(SelfTest)
460 #if XtSpecificationRelease == 4
461 #define ArgcType Cardinal *
462 #else
463 #define ArgcType int *
464 #endif
466 static void add_a_tag( Widget w )
468 static String tags[] = { "first", "second", "this is the third" };
469 static int i = 0;
471 __vi_push_tag( tags[i] );
472 i = (i+1) % XtNumber(tags);
475 #if defined(__STDC__)
476 static void show_tags( Widget w, XtPointer data, XtPointer cbs )
477 #else
478 static void show_tags( w, data, cbs )
479 Widget w;
480 XtPointer data;
481 XtPointer cbs;
482 #endif
484 __vi_show_tags_dialog( data, "Tags" );
487 main( int argc, char *argv[] )
489 XtAppContext ctx;
490 Widget top_level, rc, button;
491 extern exit();
493 /* create a top-level shell for the window manager */
494 top_level = XtVaAppInitialize( &ctx,
495 argv[0],
496 NULL, 0, /* options */
497 (ArgcType) &argc,
498 argv, /* might get modified */
499 NULL,
500 NULL
503 rc = XtVaCreateManagedWidget( "rc",
504 xmRowColumnWidgetClass,
505 top_level,
509 button = XtVaCreateManagedWidget( "Pop up tags dialog",
510 xmPushButtonGadgetClass,
514 XtAddCallback( button, XmNactivateCallback, show_tags, rc );
516 button = XtVaCreateManagedWidget( "Add a tag",
517 xmPushButtonGadgetClass,
521 XtAddCallback( button, XmNactivateCallback, add_a_tag, rc );
523 button = XtVaCreateManagedWidget( "Quit",
524 xmPushButtonGadgetClass,
528 XtAddCallback( button, XmNactivateCallback, exit, 0 );
530 XtRealizeWidget(top_level);
531 XtAppMainLoop(ctx);
533 #endif