Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / motif_l / m_menu.c
blobec7f56905a21b334f9e3d14b67bbb3ac2aa8aa4f
1 /* $NetBSD$ */
3 /*-
4 * Copyright (c) 1996
5 * Rob Zimmermann. All rights reserved.
6 * Copyright (c) 1996
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
12 #include "config.h"
14 #ifndef lint
15 static const char sccsid[] = "Id: m_menu.c,v 8.26 2003/11/05 17:09:59 skimo Exp (Berkeley) Date: 2003/11/05 17:09:59";
16 #endif /* not lint */
18 #include <sys/queue.h>
20 #include <X11/Intrinsic.h>
21 #include <X11/StringDefs.h>
22 #include <Xm/PushB.h>
23 #include <Xm/CascadeB.h>
24 #include <Xm/RowColumn.h>
25 #include <Xm/Separator.h>
26 #include <Xm/FileSB.h>
27 #include <Xm/SelectioB.h>
29 #include <bitstring.h>
30 #include <stdio.h>
32 #undef LOCK_SUCCESS
33 #include "../common/common.h"
34 #include "../ipc/ip.h"
35 #include "m_motif.h"
37 extern int vi_ofd;
39 /* save this for creation of children */
40 static Widget main_widget = NULL;
42 /* This module defines the menu structure for vi. Each menu
43 * item has an action routine associated with it. For the most
44 * part, those actions will simply call vi_send with vi commands.
45 * others will pop up file selection dialogs and use them for
46 * vi commands, and other will have to have special actions.
48 * Future:
49 * vi core will have to let us know when to be sensitive
50 * change VI_STRING to VI_COMMAND so that menu actions cannot
51 * be confusing when in insert mode
52 * need VI_CUT, VI_COPY, and VI_PASTE to perform the appropriate
53 * operations on the visible text of yank buffer. VI_COPY
54 * is likely a NOP, but it will make users happy
55 * add mnemonics
56 * add accelerators
57 * implement file selection dialog boxes
58 * implement string prompt dialog boxes (e.g. for 'find')
60 * Interface:
61 * Widget create_menubar( Widget parent ) creates and returns the
62 * X menu structure. The caller can place this
63 * anywhere in the widget heirarchy.
66 #define BufferSize 1024
69 * __vi_send_command_string --
70 * Utility: Send a menu command to vi
72 * Future:
73 * Change VI_STRING to VI_COMMAND so that menu actions cannot be confusing
74 * when in insert mode.
76 * XXX
77 * THIS SHOULD GO AWAY -- WE SHOULDN'T SEND UNINTERPRETED STRINGS TO THE
78 * CORE.
80 * PUBLIC: void __vi_send_command_string __P((String));
82 void
83 __vi_send_command_string(String str)
85 IP_BUF ipb;
86 char buffer[BufferSize];
88 /* Future: Need VI_COMMAND so vi knows this is not text to insert
89 * At that point, appending a cr/lf will not be necessary. For now,
90 * append iff we are a colon or slash command. Of course, if we are in
91 * insert mode, all bets are off.
93 strcpy( buffer, str );
94 switch ( *str ) {
95 case ':':
96 case '/':
97 strcat( buffer, "\n" );
98 break;
101 ipb.code = VI_STRING;
102 ipb.str1 = buffer;
103 ipb.len1 = strlen(buffer);
104 vi_send(vi_ofd, "a", &ipb);
108 /* Utility: beep for unimplemented command */
110 #if defined(__STDC__)
111 static void send_beep( Widget w )
112 #else
113 static void send_beep( w )
114 Widget w;
115 #endif
117 XBell( XtDisplay(w), 0 );
122 * __vi_cancel_cb --
123 * Utility: make a dialog box go Modal
125 * PUBLIC: void __vi_cancel_cb __P((Widget, XtPointer, XtPointer));
127 static Bool have_answer;
128 void
129 __vi_cancel_cb(Widget w, XtPointer client_data, XtPointer call_data)
131 have_answer = True;
135 * PUBLIC: void __vi_modal_dialog __P((Widget));
137 void
138 __vi_modal_dialog(Widget db)
140 XtAppContext ctx;
142 /* post the dialog */
143 XtManageChild( db );
144 XtPopup( XtParent(db), XtGrabExclusive );
146 /* wait for a response */
147 ctx = XtWidgetToApplicationContext(db);
148 XtAddGrab( XtParent(db), TRUE, FALSE );
149 for ( have_answer = False; ! have_answer; )
150 XtAppProcessEvent( ctx, XtIMAll );
152 /* done with db */
153 XtPopdown( XtParent(db) );
154 XtRemoveGrab( XtParent(db) );
158 /* Utility: Get a file (using standard File Selection Dialog Box) */
160 static String file_name;
163 #if defined(__STDC__)
164 static void ok_file_name( Widget w,
165 XtPointer client_data,
166 XtPointer call_data
168 #else
169 static void ok_file_name( w, client_data, call_data )
170 Widget w;
171 XtPointer client_data;
172 XtPointer call_data;
173 #endif
175 XmFileSelectionBoxCallbackStruct *cbs;
177 cbs = (XmFileSelectionBoxCallbackStruct *) call_data;
178 XmStringGetLtoR( cbs->value, XmSTRING_DEFAULT_CHARSET, &file_name );
180 have_answer = True;
184 #if defined(__STDC__)
185 static String get_file( Widget w, String prompt )
186 #else
187 static String get_file( w, prompt )
188 Widget w;
189 String prompt;
190 #endif
192 /* make it static so we can reuse it */
193 static Widget db;
195 /* our return parameter */
196 if ( file_name != NULL ) {
197 XtFree( file_name );
198 file_name = NULL;
201 /* create one? */
202 if ( db == NULL ){
203 db = XmCreateFileSelectionDialog( main_widget, "file", NULL, 0 );
204 XtAddCallback( db, XmNokCallback, ok_file_name, NULL );
205 XtAddCallback( db, XmNcancelCallback, __vi_cancel_cb, NULL );
208 /* use the title as a prompt */
209 XtVaSetValues( XtParent(db), XmNtitle, prompt, 0 );
211 /* wait for a response */
212 __vi_modal_dialog( db );
214 /* done */
215 return file_name;
220 * file_command --
221 * Get a file name and send it with the command to the core.
223 static void
224 file_command(Widget w, int code, String prompt)
226 IP_BUF ipb;
227 char *file;
229 if ((file = get_file(w, prompt)) != NULL) {
230 ipb.code = code;
231 ipb.str1 = file;
232 ipb.len1 = strlen(file);
233 vi_send(vi_ofd, "a", &ipb);
239 * Menu action routines (one per menu entry)
241 * These are in the order in which they appear in the menu structure.
243 static void
244 ma_edit_file(Widget w, XtPointer call_data, XtPointer client_data)
246 file_command(w, VI_EDIT, "Edit");
249 static void
250 ma_split(Widget w, XtPointer call_data, XtPointer client_data)
252 file_command(w, VI_EDITSPLIT, "Edit");
255 static void
256 ma_save(Widget w, XtPointer call_data, XtPointer client_data)
258 IP_BUF ipb;
260 ipb.code = VI_WRITE;
261 (void)vi_send(vi_ofd, NULL, &ipb);
264 static void
265 ma_save_as(Widget w, XtPointer call_data, XtPointer client_data)
267 file_command(w, VI_WRITEAS, "Save As");
270 static void
271 ma_wq(Widget w, XtPointer call_data, XtPointer client_data)
273 IP_BUF ipb;
275 ipb.code = VI_WQ;
276 (void)vi_send(vi_ofd, NULL, &ipb);
279 static void
280 ma_quit(Widget w, XtPointer call_data, XtPointer client_data)
282 IP_BUF ipb;
284 ipb.code = VI_QUIT;
285 (void)vi_send(vi_ofd, NULL, &ipb);
288 static void
289 ma_undo(Widget w, XtPointer call_data, XtPointer client_data)
291 IP_BUF ipb;
293 ipb.code = VI_UNDO;
294 (void)vi_send(vi_ofd, NULL, &ipb);
297 #if defined(__STDC__)
298 static void ma_cut( Widget w,
299 XtPointer call_data,
300 XtPointer client_data
302 #else
303 static void ma_cut( w, call_data, client_data )
304 Widget w;
305 XtPointer call_data;
306 XtPointer client_data;
307 #endif
309 /* future */
310 send_beep( w );
314 #if defined(__STDC__)
315 static void ma_copy( Widget w,
316 XtPointer call_data,
317 XtPointer client_data
319 #else
320 static void ma_copy( w, call_data, client_data )
321 Widget w;
322 XtPointer call_data;
323 XtPointer client_data;
324 #endif
326 /* future */
327 send_beep( w );
331 #if defined(__STDC__)
332 static void ma_paste( Widget w,
333 XtPointer call_data,
334 XtPointer client_data
336 #else
337 static void ma_paste( w, call_data, client_data )
338 Widget w;
339 XtPointer call_data;
340 XtPointer client_data;
341 #endif
343 /* future */
344 send_beep( w );
347 static void
348 ma_find(Widget w, XtPointer call_data, XtPointer client_data)
350 __vi_show_search_dialog( main_widget, "Find" );
353 static void
354 ma_find_next(Widget w, XtPointer call_data, XtPointer client_data)
356 __vi_search( w );
359 static void
360 ma_tags(Widget w, XtPointer call_data, XtPointer client_data)
362 __vi_show_tags_dialog( main_widget, "Tag Stack" );
365 static void
366 ma_tagpop(Widget w, XtPointer call_data, XtPointer client_data)
368 __vi_send_command_string( "\024" );
371 static void
372 ma_tagtop(Widget w, XtPointer call_data, XtPointer client_data)
374 __vi_send_command_string( ":tagtop" );
377 #if defined(__STDC__)
378 static void ma_preferences( Widget w,
379 XtPointer call_data,
380 XtPointer client_data
382 #else
383 static void ma_preferences( w, call_data, client_data )
384 Widget w;
385 XtPointer call_data;
386 XtPointer client_data;
387 #endif
389 __vi_show_options_dialog( main_widget, "Preferences" );
393 /* Menu construction routines */
395 typedef struct {
396 String title;
397 void (*action)();
398 String accel; /* for Motif */
399 String accel_text; /* for the user */
400 } pull_down;
402 typedef struct {
403 char mnemonic;
404 String title;
405 pull_down *actions;
406 } menu_bar;
408 static pull_down file_menu[] = {
409 { "Edit File...", ma_edit_file, "Alt<Key>e", "Alt+E" },
410 { "", NULL, NULL, NULL },
411 { "Split Window...", ma_split, NULL, NULL },
412 { "", NULL, NULL, NULL },
413 { "Save ", ma_save, "Alt<Key>s", "Alt+S" },
414 { "Save As...", ma_save_as, "Shift Alt<Key>s", "Shift+Alt+S" },
415 { "", NULL, NULL, NULL },
416 { "Write and Quit", ma_wq, "Shift Alt<Key>q", "Shift+Alt+Q" },
417 { "Quit", ma_quit, "Alt<Key>q", "Alt+Q" },
418 { NULL, NULL, NULL, NULL },
421 static pull_down edit_menu[] = {
422 { "Undo", ma_undo, NULL, NULL },
423 { "", NULL, NULL, NULL },
424 { "Cut", ma_cut, "Alt<Key>x", "Alt+X" },
425 { "Copy", ma_copy, "Alt<Key>c", "Alt+C" },
426 { "Paste", ma_paste, "Alt<Key>v", "Alt+V" },
427 { "", NULL, NULL, NULL },
428 { "Find", ma_find, "Alt<Key>f", "Alt+F" },
429 { "Find Next", ma_find_next, "Alt<Key>g", "Alt+G" },
430 { NULL, NULL, NULL, NULL },
433 static pull_down options_menu[] = {
434 { "Preferences", ma_preferences, NULL, NULL },
435 { "Command Mode Maps", NULL, NULL, NULL },
436 { "Insert Mode Maps", NULL, NULL, NULL },
437 { NULL, NULL, NULL, NULL },
440 static pull_down tag_menu[] = {
441 { "Show Tag Stack", ma_tags, "Alt<Key>t", "Alt+T" },
442 { "", NULL, NULL, NULL },
443 { "Pop Tag", ma_tagpop, NULL, NULL },
444 { "Clear Stack", ma_tagtop, NULL, NULL },
445 { NULL, NULL, NULL, NULL },
448 static pull_down help_menu[] = {
449 { NULL, NULL, NULL, NULL },
452 static menu_bar main_menu[] = {
453 { 'F', "File", file_menu },
454 { 'E', "Edit", edit_menu },
455 { 'O', "Options", options_menu },
456 { 'T', "Tag", tag_menu },
457 { 'H', "Help", help_menu },
458 { 0, NULL, NULL },
462 #if defined(__STDC__)
463 static void add_entries( Widget parent, pull_down *actions )
464 #else
465 static void add_entries( parent, actions )
466 Widget parent;
467 pull_down *actions;
468 #endif
470 Widget w;
471 XmString str;
473 for ( ; actions->title != NULL; actions++ ) {
475 /* a separator? */
476 if ( *actions->title != '\0' ) {
477 w = XmCreatePushButton( parent, actions->title, NULL, 0 );
478 if ( actions->action == NULL )
479 XtSetSensitive( w, False );
480 else
481 XtAddCallback( w,
482 XmNactivateCallback,
483 (XtCallbackProc) actions->action,
484 actions
486 if ( actions->accel != NULL ) {
487 str = XmStringCreateSimple( actions->accel_text );
488 XtVaSetValues( w,
489 XmNaccelerator, actions->accel,
490 XmNacceleratorText, str,
493 XmStringFree( str );
496 else {
497 w = XmCreateSeparator( parent, "separator", NULL, 0 );
500 XtManageChild( w );
506 * vi_create_menubar --
508 * PUBLIC: Widget vi_create_menubar __P((Widget));
510 Widget
511 vi_create_menubar(Widget parent)
513 Widget menu, pull, button;
514 menu_bar *ptr;
516 /* save this for creation of children */
517 main_widget = parent;
519 menu = XmCreateMenuBar( parent, "Menu", NULL, 0 );
521 for ( ptr=main_menu; ptr->title != NULL; ptr++ ) {
523 pull = XmCreatePulldownMenu( menu, "pull", NULL, 0 );
524 add_entries( pull, ptr->actions );
525 button = XmCreateCascadeButton( menu, ptr->title, NULL, 0 );
526 XtVaSetValues( button, XmNsubMenuId, pull, 0 );
528 if ( strcmp( ptr->title, "Help" ) == 0 )
529 XtVaSetValues( menu, XmNmenuHelpWidget, button, 0 );
531 #if 0
532 /* These screw up accelerator processing. Punt for now */
533 if ( ptr->mnemonic )
534 XtVaSetValues( button, XmNmnemonic, ptr->mnemonic, 0 );
535 #endif
537 XtManageChild( button );
540 return menu;