xref: /minix/external/bsd/nvi/dist/motif_l/m_tags.c (revision 0a6a1f1d)
1 /*-
2  * Copyright (c) 1996
3  *	Rob Zimmermann.  All rights reserved.
4  * Copyright (c) 1996
5  *	Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9 
10 #include "config.h"
11 
12 #include <sys/cdefs.h>
13 #if 0
14 #ifndef lint
15 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 ";
16 #endif /* not lint */
17 #else
18 __RCSID("$NetBSD: m_tags.c,v 1.2 2014/01/26 21:43:45 christos Exp $");
19 #endif
20 
21 /*
22  * This module implements a dialog for navigating the tag stack
23  *
24  * Interface:
25  * void	__vi_show_tags_dialog( Widget parent, String title )
26  *	Pops up a Tags dialog.  We allow one per session.  It is not modal.
27  *
28  * void __vi_push_tag( String text )
29  * void __vi_pop_tag()
30  * void __vi_clear_tag()
31  *	When core changes the tag stack we will change our representation
32  *	of it.  When this dialog appears, we need core to send a slew of
33  *	messages so we can display the current tag stack.
34  *
35  * void __vi_set_tag_text( String text )
36  *	the text field in the dialog is set to the string.  ideally,
37  *	this should be kept in sync with the word following the caret
38  *	in the current editor window
39  *
40  * To Do:
41  *	The push-buttons should activate and deactivate according to
42  *	the state of the tag stack and the text field.
43  *
44  *	Need to send VI commands rather than strings
45  *
46  *	Need IPO command to start/stop asking for the current tag stack
47  */
48 
49 
50 /* context */
51 #include <X11/X.h>
52 #include <X11/Intrinsic.h>
53 #include <Xm/DialogS.h>
54 #include <Xm/Form.h>
55 #include <Xm/LabelG.h>
56 #include <Xm/TextF.h>
57 #include <Xm/List.h>
58 #include <Xm/RowColumn.h>
59 #include <Xm/PushBG.h>
60 
61 #if ! defined(SelfTest)
62 #include <sys/types.h>
63 #include <sys/queue.h>
64 
65 #include <bitstring.h>
66 #include <stdio.h>
67 #include <string.h>
68 
69 #undef LOCK_SUCCESS
70 #include "../common/common.h"
71 #include "../ipc/ip.h"
72 #include "m_motif.h"
73 #endif
74 
75 extern int vi_ofd;
76 
77 
78 /* globals */
79 
80 static	Widget	db_tabs = NULL,
81 		db_text,
82 		db_list;
83 
84 static	Boolean	active = False;
85 
86 typedef struct	{
87     String	name;
88     Boolean	is_default;
89     void	(*cb)();
90 } ButtonData;
91 
92 static	void go_to_tag(Widget w);
93 static	void split_to_tag(Widget w);
94 static	void pop_tag(Widget w);
95 
96 static	ButtonData button_data[] = {
97     { "Go To Tag",	True,	go_to_tag	},
98     { "Split To Tag", 	False,	split_to_tag	},
99     { "Pop Tag", 	False,	pop_tag		},
100 };
101 
102 
103 /* manage the tags stack list */
104 
__vi_pop_tag(void)105 void	__vi_pop_tag(void)
106 {
107     if ( ! active ) return;
108 
109     XmListDeletePos( db_list, 1 );
110 }
111 
112 
__vi_clear_tag(void)113 void	__vi_clear_tag(void)
114 {
115     if ( ! active ) return;
116 
117     XmListDeleteAllItems( db_list );
118 }
119 
120 
__vi_push_tag(String text)121 void	__vi_push_tag(String text)
122 {
123     XmString	str;
124 
125     if ( ! active ) return;
126 
127     str = XmStringCreateSimple( text );
128     XmListAddItem( db_list, str, 1 );
129     XmStringFree( str );
130 }
131 
132 
133 /* create a set of push buttons */
134 
135 #define	SpacingRatio	4	/* 3:1 button to spaces */
136 
137 #if defined(__STDC__)
create_push_buttons(Widget parent,ButtonData * data,int count)138 static	Widget	create_push_buttons( Widget parent,
139 				     ButtonData *data,
140 				     int count
141 				    )
142 #else
143 static	Widget	create_push_buttons( parent, data, count )
144     Widget	parent;
145     ButtonData	*data;
146     int		count;
147 #endif
148 {
149     Widget	w, form;
150     int		pos = 1, base;
151 
152     base = SpacingRatio*count + 1;
153     form = XtVaCreateManagedWidget( "buttons",
154 				    xmFormWidgetClass,
155 				    parent,
156 				    XmNleftAttachment,	XmATTACH_FORM,
157 				    XmNrightAttachment,	XmATTACH_FORM,
158 				    XmNfractionBase,	base,
159 				    XmNshadowType,	XmSHADOW_ETCHED_IN,
160 				    XmNshadowThickness,	2,
161 				    XmNverticalSpacing,	4,
162 				    0
163 				    );
164 
165     while ( count-- > 0 ) {
166 	w = XtVaCreateManagedWidget(data->name,
167 				    xmPushButtonGadgetClass,
168 				    form,
169 				    XmNtopAttachment,	XmATTACH_FORM,
170 				    XmNbottomAttachment,XmATTACH_FORM,
171 				    XmNleftAttachment,	XmATTACH_POSITION,
172 				    XmNleftPosition,	pos,
173 				    XmNshowAsDefault,	data->is_default,
174 				    XmNdefaultButtonShadowThickness,	data->is_default,
175 				    XmNrightAttachment,	XmATTACH_POSITION,
176 				    XmNrightPosition,	pos+SpacingRatio-1,
177 				    0
178 				    );
179 	if ( data->is_default )
180 	    XtVaSetValues( form, XmNdefaultButton, w, 0 );
181 	XtAddCallback( w, XmNactivateCallback, data->cb, 0 );
182 	pos += SpacingRatio;
183 	data++;
184     }
185 
186     return form;
187 }
188 
189 
190 /* callbacks */
191 
192 static void
cancel_cb(void)193 cancel_cb(void)
194 {
195 #if defined(SelfTest)
196     puts( "cancelled" );
197 #endif
198     active = False;
199 }
200 
201 
set_text_field(Widget w,XtPointer ptr,XmListCallbackStruct * cbs)202 static	void 		set_text_field(Widget w, XtPointer ptr, XmListCallbackStruct *cbs)
203 {
204     String str;
205 
206     XmStringGetLtoR( cbs->item, XmSTRING_DEFAULT_CHARSET, &str );
207     XmTextFieldSetString( db_text, str );
208     XtFree( str );
209 }
210 
211 
__vi_set_tag_text(String text)212 void	__vi_set_tag_text(String text)
213 {
214     if ( active ) XmTextFieldSetString( db_text, text );
215 }
216 
217 
destroyed(void)218 static	void destroyed(void)
219 {
220 #if defined(SelfTest)
221     puts( "destroyed" );
222 #endif
223 
224     /* some window managers destroy us upon popdown */
225     db_tabs = NULL;
226     active  = False;
227 }
228 
229 
230 #if defined(__STDC__)
pop_tag(Widget w)231 static	void	pop_tag( Widget w )
232 #else
233 static	void	pop_tag( w )
234 	Widget	w;
235 #endif
236 {
237     static String buffer = ":tagpop";
238 
239 #if defined(SelfTest)
240     printf( "sending command <<%s>>\n", buffer );
241     __vi_pop_tag();
242 #else
243     __vi_send_command_string( buffer );
244 #endif
245 }
246 
247 
248 #if defined(__STDC__)
split_to_tag(Widget w)249 static	void	split_to_tag( Widget w )
250 #else
251 static	void	split_to_tag( w )
252 	Widget	w;
253 #endif
254 {
255     IP_BUF	ipb;
256     String	str;
257 
258     str = XmTextFieldGetString( db_text );
259 
260 #if defined(SelfTest)
261     printf( "sending command <<:Tag %s>>\n", str );
262 #else
263     /*
264      * XXX
265      * This is REALLY sleazy.  We pass the nul along with the
266      * string so that the core editor doesn't have to copy the
267      * string to get a nul termination.  This should be fixed
268      * as part of making the editor fully 8-bit clean.
269      */
270     ipb.code = VI_TAGSPLIT;
271     ipb.str1 = str;
272     ipb.len1 = strlen(str) + 1;
273     vi_send(vi_ofd, "a", &ipb);
274 #endif
275 
276     XtFree( str );
277 }
278 
279 
280 #if defined(__STDC__)
go_to_tag(Widget w)281 static	void	go_to_tag( Widget w )
282 #else
283 static	void	go_to_tag( w )
284 	Widget	w;
285 #endif
286 {
287     IP_BUF	ipb;
288     String	str;
289 
290     str = XmTextFieldGetString( db_text );
291 
292 #if defined(SelfTest)
293     printf( "sending command <<:tag %s>>\n", str );
294 #else
295     /*
296      * XXX
297      * This is REALLY sleazy.  We pass the nul along with the
298      * string so that the core editor doesn't have to copy the
299      * string to get a nul termination.  This should be fixed
300      * as part of making the editor fully 8-bit clean.
301      */
302     ipb.code = VI_TAGAS;
303     ipb.str1 = str;
304     ipb.len1 = strlen(str) + 1;
305     vi_send(vi_ofd, "a", &ipb);
306 #endif
307 
308     XtFree( str );
309 }
310 
311 
312 
313 /* Draw and display a dialog the describes nvi options */
314 
315 #if defined(__STDC__)
create_tags_dialog(Widget parent,String title)316 static	Widget	create_tags_dialog( Widget parent, String title )
317 #else
318 static	Widget	create_tags_dialog( parent, title )
319 	Widget	parent;
320 	String	title;
321 #endif
322 {
323     Widget	box, form, form2, form3, buttons;
324 
325     /* already built? */
326     if ( db_tabs != NULL ) return db_tabs;
327 
328     box = XtVaCreatePopupShell( title,
329 				xmDialogShellWidgetClass,
330 				parent,
331 				XmNtitle,		title,
332 				XmNallowShellResize,	False,
333 				0
334 				);
335     XtAddCallback( box, XmNpopdownCallback, cancel_cb, 0 );
336     XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
337 
338     form = XtVaCreateWidget( "Tags",
339 			     xmFormWidgetClass,
340 			     box,
341 			     0
342 			     );
343 
344     buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
345     XtVaSetValues( buttons,
346 		   XmNbottomAttachment,	XmATTACH_FORM,
347 		   0
348 		   );
349 
350     form3 = XtVaCreateWidget( "form",
351 			      xmFormWidgetClass,
352 			      form,
353 			      XmNleftAttachment,	XmATTACH_FORM,
354 			      XmNrightAttachment,	XmATTACH_FORM,
355 			      XmNbottomAttachment,	XmATTACH_WIDGET,
356 			      XmNbottomWidget,		buttons,
357 			      0
358 			      );
359 
360     form2 = XtVaCreateWidget( "form",
361 			      xmFormWidgetClass,
362 			      form,
363 			      XmNtopAttachment,		XmATTACH_FORM,
364 			      XmNleftAttachment,	XmATTACH_FORM,
365 			      XmNrightAttachment,	XmATTACH_FORM,
366 			      XmNbottomAttachment,	XmATTACH_WIDGET,
367 			      XmNbottomWidget,		form3,
368 			      0
369 			      );
370 
371     db_list = XtVaCreateManagedWidget( "list",
372 				xmListWidgetClass,
373 				form2,
374 				XmNtopAttachment,	XmATTACH_FORM,
375 				XmNleftAttachment,	XmATTACH_POSITION,
376 				XmNleftPosition,	20,
377 				XmNrightAttachment,	XmATTACH_FORM,
378 				XmNbottomAttachment,	XmATTACH_FORM,
379 #if defined(SelfTest)
380 				XmNvisibleItemCount,	5,
381 #endif
382 				XmNselectionPolicy,	XmSINGLE_SELECT,
383 				0
384 				);
385     XtAddCallback( db_list, XmNsingleSelectionCallback, set_text_field, 0 );
386     XtAddCallback( db_list, XmNdefaultActionCallback, go_to_tag, 0 );
387 
388     XtVaCreateManagedWidget( "Tag Stack",
389 			     xmLabelGadgetClass,
390 			     form2,
391 			     XmNtopAttachment,		XmATTACH_FORM,
392 			     XmNbottomAttachment,	XmATTACH_FORM,
393 			     XmNleftAttachment,		XmATTACH_FORM,
394 			     XmNrightAttachment,	XmATTACH_POSITION,
395 			     XmNrightPosition,		20,
396 			     XmNalignment,		XmALIGNMENT_END,
397 			     0
398 			     );
399 
400     XtVaCreateManagedWidget( "Tag",
401 			     xmLabelGadgetClass,
402 			     form3,
403 			     XmNtopAttachment,		XmATTACH_FORM,
404 			     XmNbottomAttachment,	XmATTACH_FORM,
405 			     XmNleftAttachment,		XmATTACH_FORM,
406 			     XmNrightAttachment,	XmATTACH_POSITION,
407 			     XmNrightPosition,		20,
408 			     XmNalignment,		XmALIGNMENT_END,
409 			     0
410 			     );
411 
412     db_text = XtVaCreateManagedWidget( "text",
413 			    xmTextFieldWidgetClass,
414 			    form3,
415 			    XmNtopAttachment,		XmATTACH_FORM,
416 			    XmNbottomAttachment,	XmATTACH_FORM,
417 			    XmNrightAttachment,		XmATTACH_FORM,
418 			    XmNleftAttachment,		XmATTACH_POSITION,
419 			    XmNleftPosition,		20,
420 			    0
421 			    );
422     XtAddCallback( db_text, XmNactivateCallback, go_to_tag, 0 );
423 
424     /* keep this global, we might destroy it later */
425     db_tabs = form;
426 
427     /* done */
428     XtManageChild( form3 );
429     XtManageChild( form2 );
430     return form;
431 }
432 
433 
434 
435 /* module entry point
436  *	__vi_show_tags_dialog( parent, title )
437  */
438 
439 #if defined(__STDC__)
__vi_show_tags_dialog(Widget parent,String title)440 void	__vi_show_tags_dialog( Widget parent, String title )
441 #else
442 void	__vi_show_tags_dialog( parent, title )
443 Widget	parent;
444 String	title;
445 #endif
446 {
447     Widget 	db = create_tags_dialog( parent, title ),
448 		shell = XtParent(db);
449 
450     XtManageChild( db );
451 
452     /* get the current window's text */
453     __vi_set_tag_text( (String) __vi_get_word_at_caret( NULL ) );
454 
455     /* TODO:  ask vi core for the current tag stack now */
456 
457     /* leave this guy up (or just raise it) */
458     XtPopup( shell, XtGrabNone );
459     XMapRaised( XtDisplay( shell ), XtWindow( shell ) );
460 
461     active = True;
462 }
463 
464 
465 
466 #if defined(SelfTest)
467 
468 #if XtSpecificationRelease == 4
469 #define	ArgcType	Cardinal *
470 #else
471 #define	ArgcType	int *
472 #endif
473 
add_a_tag(Widget w)474 static	void	add_a_tag( Widget w )
475 {
476     static	String	tags[] = { "first", "second", "this is the third" };
477     static	int	i = 0;
478 
479     __vi_push_tag( tags[i] );
480     i = (i+1) % XtNumber(tags);
481 }
482 
483 #if defined(__STDC__)
show_tags(Widget w,XtPointer data,XtPointer cbs)484 static void show_tags( Widget w, XtPointer data, XtPointer cbs )
485 #else
486 static void show_tags( w, data, cbs )
487 Widget w;
488 XtPointer	data;
489 XtPointer	cbs;
490 #endif
491 {
492     __vi_show_tags_dialog( data, "Tags" );
493 }
494 
main(int argc,char * argv[])495 main( int argc, char *argv[] )
496 {
497     XtAppContext	ctx;
498     Widget		top_level, rc, button;
499     extern		exit();
500 
501     /* create a top-level shell for the window manager */
502     top_level = XtVaAppInitialize( &ctx,
503 				   argv[0],
504 				   NULL, 0,	/* options */
505 				   (ArgcType) &argc,
506 				   argv,	/* might get modified */
507 				   NULL,
508 				   NULL
509 				   );
510 
511     rc = XtVaCreateManagedWidget( "rc",
512 				  xmRowColumnWidgetClass,
513 				  top_level,
514 				  0
515 				  );
516 
517     button = XtVaCreateManagedWidget( "Pop up tags dialog",
518 				      xmPushButtonGadgetClass,
519 				      rc,
520 				      0
521 				      );
522     XtAddCallback( button, XmNactivateCallback, show_tags, rc );
523 
524     button = XtVaCreateManagedWidget( "Add a tag",
525 				      xmPushButtonGadgetClass,
526 				      rc,
527 				      0
528 				      );
529     XtAddCallback( button, XmNactivateCallback, add_a_tag, rc );
530 
531     button = XtVaCreateManagedWidget( "Quit",
532 				      xmPushButtonGadgetClass,
533 				      rc,
534 				      0
535 				      );
536     XtAddCallback( button, XmNactivateCallback, exit, 0 );
537 
538     XtRealizeWidget(top_level);
539     XtAppMainLoop(ctx);
540 }
541 #endif
542