dist/distrib: generate vi.0
[nvi.git] / motif_l / m_tags.c
blob149b4b2f97da2ce3532a0c120a1eefdecb74a8e2
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.9 2003/11/05 17:10:00 skimo Exp $ (Berkeley) $Date: 2003/11/05 17:10:00 $";
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 #undef LOCK_SUCCESS
65 #include "../common/common.h"
66 #include "../ipc/ip.h"
67 #include "m_motif.h"
68 #endif
70 extern int vi_ofd;
73 /* globals */
75 static Widget db_tabs = NULL,
76 db_text,
77 db_list;
79 static Boolean active = False;
81 typedef struct {
82 String name;
83 Boolean is_default;
84 void (*cb)();
85 } ButtonData;
87 static void go_to_tag(Widget w);
88 static void split_to_tag(Widget w);
89 static void pop_tag(Widget w);
91 static ButtonData button_data[] = {
92 { "Go To Tag", True, go_to_tag },
93 { "Split To Tag", False, split_to_tag },
94 { "Pop Tag", False, pop_tag },
98 /* manage the tags stack list */
100 void __vi_pop_tag(void)
102 if ( ! active ) return;
104 XmListDeletePos( db_list, 1 );
108 void __vi_clear_tag(void)
110 if ( ! active ) return;
112 XmListDeleteAllItems( db_list );
116 void __vi_push_tag(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(void)
190 #if defined(SelfTest)
191 puts( "cancelled" );
192 #endif
193 active = False;
197 static void set_text_field(Widget w, XtPointer ptr, XmListCallbackStruct *cbs)
199 String str;
201 XmStringGetLtoR( cbs->item, XmSTRING_DEFAULT_CHARSET, &str );
202 XmTextFieldSetString( db_text, str );
203 XtFree( str );
207 void __vi_set_tag_text(String text)
209 if ( active ) XmTextFieldSetString( db_text, text );
213 static void destroyed(void)
215 #if defined(SelfTest)
216 puts( "destroyed" );
217 #endif
219 /* some window managers destroy us upon popdown */
220 db_tabs = NULL;
221 active = False;
225 #if defined(__STDC__)
226 static void pop_tag( Widget w )
227 #else
228 static void pop_tag( w )
229 Widget w;
230 #endif
232 static String buffer = ":tagpop";
234 #if defined(SelfTest)
235 printf( "sending command <<%s>>\n", buffer );
236 __vi_pop_tag();
237 #else
238 __vi_send_command_string( buffer );
239 #endif
243 #if defined(__STDC__)
244 static void split_to_tag( Widget w )
245 #else
246 static void split_to_tag( w )
247 Widget w;
248 #endif
250 IP_BUF ipb;
251 String str;
253 str = XmTextFieldGetString( db_text );
255 #if defined(SelfTest)
256 printf( "sending command <<:Tag %s>>\n", str );
257 #else
259 * XXX
260 * This is REALLY sleazy. We pass the nul along with the
261 * string so that the core editor doesn't have to copy the
262 * string to get a nul termination. This should be fixed
263 * as part of making the editor fully 8-bit clean.
265 ipb.code = VI_TAGSPLIT;
266 ipb.str1 = str;
267 ipb.len1 = strlen(str) + 1;
268 vi_send(vi_ofd, "a", &ipb);
269 #endif
271 XtFree( str );
275 #if defined(__STDC__)
276 static void go_to_tag( Widget w )
277 #else
278 static void go_to_tag( w )
279 Widget w;
280 #endif
282 IP_BUF ipb;
283 String str;
285 str = XmTextFieldGetString( db_text );
287 #if defined(SelfTest)
288 printf( "sending command <<:tag %s>>\n", str );
289 #else
291 * XXX
292 * This is REALLY sleazy. We pass the nul along with the
293 * string so that the core editor doesn't have to copy the
294 * string to get a nul termination. This should be fixed
295 * as part of making the editor fully 8-bit clean.
297 ipb.code = VI_TAGAS;
298 ipb.str1 = str;
299 ipb.len1 = strlen(str) + 1;
300 vi_send(vi_ofd, "a", &ipb);
301 #endif
303 XtFree( str );
308 /* Draw and display a dialog the describes nvi options */
310 #if defined(__STDC__)
311 static Widget create_tags_dialog( Widget parent, String title )
312 #else
313 static Widget create_tags_dialog( parent, title )
314 Widget parent;
315 String title;
316 #endif
318 Widget box, form, form2, form3, buttons;
320 /* already built? */
321 if ( db_tabs != NULL ) return db_tabs;
323 box = XtVaCreatePopupShell( title,
324 xmDialogShellWidgetClass,
325 parent,
326 XmNtitle, title,
327 XmNallowShellResize, False,
330 XtAddCallback( box, XmNpopdownCallback, cancel_cb, 0 );
331 XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
333 form = XtVaCreateWidget( "Tags",
334 xmFormWidgetClass,
335 box,
339 buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
340 XtVaSetValues( buttons,
341 XmNbottomAttachment, XmATTACH_FORM,
345 form3 = XtVaCreateWidget( "form",
346 xmFormWidgetClass,
347 form,
348 XmNleftAttachment, XmATTACH_FORM,
349 XmNrightAttachment, XmATTACH_FORM,
350 XmNbottomAttachment, XmATTACH_WIDGET,
351 XmNbottomWidget, buttons,
355 form2 = XtVaCreateWidget( "form",
356 xmFormWidgetClass,
357 form,
358 XmNtopAttachment, XmATTACH_FORM,
359 XmNleftAttachment, XmATTACH_FORM,
360 XmNrightAttachment, XmATTACH_FORM,
361 XmNbottomAttachment, XmATTACH_WIDGET,
362 XmNbottomWidget, form3,
366 db_list = XtVaCreateManagedWidget( "list",
367 xmListWidgetClass,
368 form2,
369 XmNtopAttachment, XmATTACH_FORM,
370 XmNleftAttachment, XmATTACH_POSITION,
371 XmNleftPosition, 20,
372 XmNrightAttachment, XmATTACH_FORM,
373 XmNbottomAttachment, XmATTACH_FORM,
374 #if defined(SelfTest)
375 XmNvisibleItemCount, 5,
376 #endif
377 XmNselectionPolicy, XmSINGLE_SELECT,
380 XtAddCallback( db_list, XmNsingleSelectionCallback, set_text_field, 0 );
381 XtAddCallback( db_list, XmNdefaultActionCallback, go_to_tag, 0 );
383 XtVaCreateManagedWidget( "Tag Stack",
384 xmLabelGadgetClass,
385 form2,
386 XmNtopAttachment, XmATTACH_FORM,
387 XmNbottomAttachment, XmATTACH_FORM,
388 XmNleftAttachment, XmATTACH_FORM,
389 XmNrightAttachment, XmATTACH_POSITION,
390 XmNrightPosition, 20,
391 XmNalignment, XmALIGNMENT_END,
395 XtVaCreateManagedWidget( "Tag",
396 xmLabelGadgetClass,
397 form3,
398 XmNtopAttachment, XmATTACH_FORM,
399 XmNbottomAttachment, XmATTACH_FORM,
400 XmNleftAttachment, XmATTACH_FORM,
401 XmNrightAttachment, XmATTACH_POSITION,
402 XmNrightPosition, 20,
403 XmNalignment, XmALIGNMENT_END,
407 db_text = XtVaCreateManagedWidget( "text",
408 xmTextFieldWidgetClass,
409 form3,
410 XmNtopAttachment, XmATTACH_FORM,
411 XmNbottomAttachment, XmATTACH_FORM,
412 XmNrightAttachment, XmATTACH_FORM,
413 XmNleftAttachment, XmATTACH_POSITION,
414 XmNleftPosition, 20,
417 XtAddCallback( db_text, XmNactivateCallback, go_to_tag, 0 );
419 /* keep this global, we might destroy it later */
420 db_tabs = form;
422 /* done */
423 XtManageChild( form3 );
424 XtManageChild( form2 );
425 return form;
430 /* module entry point
431 * __vi_show_tags_dialog( parent, title )
434 #if defined(__STDC__)
435 void __vi_show_tags_dialog( Widget parent, String title )
436 #else
437 void __vi_show_tags_dialog( parent, title )
438 Widget parent;
439 String title;
440 #endif
442 Widget db = create_tags_dialog( parent, title ),
443 shell = XtParent(db);
445 XtManageChild( db );
447 /* get the current window's text */
448 __vi_set_tag_text( (String) __vi_get_word_at_caret( NULL ) );
450 /* TODO: ask vi core for the current tag stack now */
452 /* leave this guy up (or just raise it) */
453 XtPopup( shell, XtGrabNone );
454 XMapRaised( XtDisplay( shell ), XtWindow( shell ) );
456 active = True;
461 #if defined(SelfTest)
463 #if XtSpecificationRelease == 4
464 #define ArgcType Cardinal *
465 #else
466 #define ArgcType int *
467 #endif
469 static void add_a_tag( Widget w )
471 static String tags[] = { "first", "second", "this is the third" };
472 static int i = 0;
474 __vi_push_tag( tags[i] );
475 i = (i+1) % XtNumber(tags);
478 #if defined(__STDC__)
479 static void show_tags( Widget w, XtPointer data, XtPointer cbs )
480 #else
481 static void show_tags( w, data, cbs )
482 Widget w;
483 XtPointer data;
484 XtPointer cbs;
485 #endif
487 __vi_show_tags_dialog( data, "Tags" );
490 main( int argc, char *argv[] )
492 XtAppContext ctx;
493 Widget top_level, rc, button;
494 extern exit();
496 /* create a top-level shell for the window manager */
497 top_level = XtVaAppInitialize( &ctx,
498 argv[0],
499 NULL, 0, /* options */
500 (ArgcType) &argc,
501 argv, /* might get modified */
502 NULL,
503 NULL
506 rc = XtVaCreateManagedWidget( "rc",
507 xmRowColumnWidgetClass,
508 top_level,
512 button = XtVaCreateManagedWidget( "Pop up tags dialog",
513 xmPushButtonGadgetClass,
517 XtAddCallback( button, XmNactivateCallback, show_tags, rc );
519 button = XtVaCreateManagedWidget( "Add a tag",
520 xmPushButtonGadgetClass,
524 XtAddCallback( button, XmNactivateCallback, add_a_tag, rc );
526 button = XtVaCreateManagedWidget( "Quit",
527 xmPushButtonGadgetClass,
531 XtAddCallback( button, XmNactivateCallback, exit, 0 );
533 XtRealizeWidget(top_level);
534 XtAppMainLoop(ctx);
536 #endif