from RAZ: ruler dialog box
[nvi.git] / motif_l / m_menu.c
blob3f89d773257d9057d59eabd2850d30320840e0a3
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_menu.c,v 8.19 1996/12/11 20:58:23 bostic Exp $ (Berkeley) $Date: 1996/12/11 20:58:23 $";
14 #endif /* not lint */
16 #include <sys/queue.h>
18 #include <X11/Intrinsic.h>
19 #include <X11/StringDefs.h>
20 #include <Xm/PushB.h>
21 #include <Xm/CascadeB.h>
22 #include <Xm/RowColumn.h>
23 #include <Xm/Separator.h>
24 #include <Xm/FileSB.h>
25 #include <Xm/SelectioB.h>
27 #include <bitstring.h>
28 #include <stdio.h>
30 #include "../common/common.h"
31 #include "../ip/ip.h"
32 #include "ipc_extern.h"
34 /* save this for creation of children */
35 static Widget main_widget = NULL;
37 /* This module defines the menu structure for vi. Each menu
38 * item has an action routine associated with it. For the most
39 * part, those actions will simply call __vi_send with vi commands.
40 * others will pop up file selection dialogs and use them for
41 * vi commands, and other will have to have special actions.
43 * Future:
44 * vi core will have to let us know when to be sensitive
45 * change VI_STRING to VI_COMMAND so that menu actions cannot
46 * be confusing when in insert mode
47 * need VI_CUT, VI_COPY, and VI_PASTE to perform the appropriate
48 * operations on the visible text of yank buffer. VI_COPY
49 * is likely a NOP, but it will make users happy
50 * add mnemonics
51 * add accelerators
52 * implement file selection dialog boxes
53 * implement string prompt dialog boxes (e.g. for 'find')
55 * Interface:
56 * Widget create_menubar( Widget parent ) creates and returns the
57 * X menu structure. The caller can place this
58 * anywhere in the widget heirarchy.
61 #define BufferSize 1024
64 * __vi_send_command_string --
65 * Utility: Send a menu command to vi
67 * Future:
68 * Change VI_STRING to VI_COMMAND so that menu actions cannot be confusing
69 * when in insert mode.
71 * XXX
72 * THIS SHOULD GO AWAY -- WE SHOULDN'T SEND UNINTERPRETED STRINGS TO THE
73 * CORE.
75 * PUBLIC: void __vi_send_command_string __P((String));
77 void
78 __vi_send_command_string(str)
79 String str;
81 IP_BUF ipb;
82 char buffer[BufferSize];
84 /* Future: Need VI_COMMAND so vi knows this is not text to insert
85 * At that point, appending a cr/lf will not be necessary. For now,
86 * append iff we are a colon or slash command. Of course, if we are in
87 * insert mode, all bets are off.
89 strcpy( buffer, str );
90 switch ( *str ) {
91 case ':':
92 case '/':
93 strcat( buffer, "\n" );
94 break;
97 ipb.code = VI_STRING;
98 ipb.str = buffer;
99 ipb.len = strlen(buffer);
100 __vi_send("s", &ipb);
104 /* Utility: beep for unimplemented command */
106 #if defined(__STDC__)
107 static void send_beep( Widget w )
108 #else
109 static void send_beep( w )
110 Widget w;
111 #endif
113 XBell( XtDisplay(w), 0 );
118 * __vi_cancel_cb --
119 * Utility: make a dialog box go Modal
121 * PUBLIC: void __vi_cancel_cb __P((Widget, XtPointer, XtPointer));
123 static Bool have_answer;
124 void
125 __vi_cancel_cb(w, client_data, call_data)
126 Widget w;
127 XtPointer client_data, call_data;
129 have_answer = True;
132 void __vi_modal_dialog( db )
133 Widget db;
135 XtAppContext ctx;
137 /* post the dialog */
138 XtManageChild( db );
139 XtPopup( XtParent(db), XtGrabExclusive );
141 /* wait for a response */
142 ctx = XtWidgetToApplicationContext(db);
143 XtAddGrab( XtParent(db), TRUE, FALSE );
144 for ( have_answer = False; ! have_answer; )
145 XtAppProcessEvent( ctx, XtIMAll );
147 /* done with db */
148 XtPopdown( XtParent(db) );
149 XtRemoveGrab( XtParent(db) );
153 /* Utility: Get a file (using standard File Selection Dialog Box) */
155 static String file_name;
158 #if defined(__STDC__)
159 static void ok_file_name( Widget w,
160 XtPointer client_data,
161 XtPointer call_data
163 #else
164 static void ok_file_name( w, client_data, call_data )
165 Widget w;
166 XtPointer client_data;
167 XtPointer call_data;
168 #endif
170 XmFileSelectionBoxCallbackStruct *cbs;
172 cbs = (XmFileSelectionBoxCallbackStruct *) call_data;
173 XmStringGetLtoR( cbs->value, XmSTRING_DEFAULT_CHARSET, &file_name );
175 have_answer = True;
179 #if defined(__STDC__)
180 static String get_file( Widget w, String prompt )
181 #else
182 static String get_file( w, prompt )
183 Widget w;
184 String prompt;
185 #endif
187 /* make it static so we can reuse it */
188 static Widget db;
190 /* our return parameter */
191 if ( file_name != NULL ) {
192 XtFree( file_name );
193 file_name = NULL;
196 /* create one? */
197 if ( db == NULL ){
198 db = XmCreateFileSelectionDialog( main_widget, "file", NULL, 0 );
199 XtAddCallback( db, XmNokCallback, ok_file_name, NULL );
200 XtAddCallback( db, XmNcancelCallback, __vi_cancel_cb, NULL );
203 /* use the title as a prompt */
204 XtVaSetValues( XtParent(db), XmNtitle, prompt, 0 );
206 /* wait for a response */
207 __vi_modal_dialog( db );
209 /* done */
210 return file_name;
215 * file_command --
216 * Get a file name and send it with the command to the core.
218 static void
219 file_command(w, code, prompt)
220 Widget w;
221 int code;
222 String prompt;
224 IP_BUF ipb;
225 char *file;
227 if ((file = get_file(w, prompt)) != NULL) {
228 ipb.code = code;
229 ipb.str = file;
230 ipb.len = strlen(file);
231 __vi_send("s", &ipb);
237 * Menu action routines (one per menu entry)
239 * These are in the order in which they appear in the menu structure.
241 static void
242 ma_edit_file(w, call_data, client_data)
243 Widget w;
244 XtPointer call_data, client_data;
246 file_command(w, VI_EDIT, "Edit");
249 static void
250 ma_split(w, call_data, client_data)
251 Widget w;
252 XtPointer call_data, client_data;
254 file_command(w, VI_EDITSPLIT, "Edit");
257 static void
258 ma_save(w, call_data, client_data)
259 Widget w;
260 XtPointer call_data, client_data;
262 IP_BUF ipb;
264 ipb.code = VI_WRITE;
265 (void)__vi_send(NULL, &ipb);
268 static void
269 ma_save_as(w, call_data, client_data)
270 Widget w;
271 XtPointer call_data, client_data;
273 file_command(w, VI_WRITEAS, "Save As");
276 static void
277 ma_wq(w, call_data, client_data)
278 Widget w;
279 XtPointer call_data, client_data;
281 IP_BUF ipb;
283 ipb.code = VI_WQ;
284 (void)__vi_send(NULL, &ipb);
287 static void
288 ma_quit(w, call_data, client_data)
289 Widget w;
290 XtPointer call_data, client_data;
292 IP_BUF ipb;
294 ipb.code = VI_QUIT;
295 (void)__vi_send(NULL, &ipb);
298 static void
299 ma_undo(w, call_data, client_data)
300 Widget w;
301 XtPointer call_data, client_data;
303 IP_BUF ipb;
305 ipb.code = VI_UNDO;
306 (void)__vi_send(NULL, &ipb);
309 #if defined(__STDC__)
310 static void ma_cut( Widget w,
311 XtPointer call_data,
312 XtPointer client_data
314 #else
315 static void ma_cut( w, call_data, client_data )
316 Widget w;
317 XtPointer call_data;
318 XtPointer client_data;
319 #endif
321 /* future */
322 send_beep( w );
326 #if defined(__STDC__)
327 static void ma_copy( Widget w,
328 XtPointer call_data,
329 XtPointer client_data
331 #else
332 static void ma_copy( w, call_data, client_data )
333 Widget w;
334 XtPointer call_data;
335 XtPointer client_data;
336 #endif
338 /* future */
339 send_beep( w );
343 #if defined(__STDC__)
344 static void ma_paste( Widget w,
345 XtPointer call_data,
346 XtPointer client_data
348 #else
349 static void ma_paste( w, call_data, client_data )
350 Widget w;
351 XtPointer call_data;
352 XtPointer client_data;
353 #endif
355 /* future */
356 send_beep( w );
359 static void
360 ma_find(w, call_data, client_data)
361 Widget w;
362 XtPointer call_data, client_data;
364 __vi_show_search_dialog( main_widget, "Find" );
367 static void
368 ma_find_next(w, call_data, client_data)
369 Widget w;
370 XtPointer call_data, client_data;
372 __vi_search();
375 static void
376 ma_tags(w, call_data, client_data)
377 Widget w;
378 XtPointer call_data, client_data;
380 __vi_show_tags_dialog( main_widget, "Tag Stack" );
383 static void
384 ma_tagpop(w, call_data, client_data)
385 Widget w;
386 XtPointer call_data, client_data;
388 __vi_send_command_string( "\024" );
391 static void
392 ma_tagtop(w, call_data, client_data)
393 Widget w;
394 XtPointer call_data, client_data;
396 __vi_send_command_string( ":tagtop" );
399 #if defined(__STDC__)
400 static void ma_preferences( Widget w,
401 XtPointer call_data,
402 XtPointer client_data
404 #else
405 static void ma_preferences( w, call_data, client_data )
406 Widget w;
407 XtPointer call_data;
408 XtPointer client_data;
409 #endif
411 __vi_show_options_dialog( main_widget, "Preferences" );
415 /* Menu construction routines */
417 typedef struct {
418 String title;
419 void (*action)();
420 String accel; /* for Motif */
421 String accel_text; /* for the user */
422 } pull_down;
424 typedef struct {
425 char mnemonic;
426 String title;
427 pull_down *actions;
428 } menu_bar;
430 static pull_down file_menu[] = {
431 { "Edit File...", ma_edit_file, "Alt<Key>e", "Alt+E" },
432 { "", NULL, NULL, NULL },
433 { "Split Window...", ma_split, NULL, NULL },
434 { "", NULL, NULL, NULL },
435 { "Save ", ma_save, "Alt<Key>s", "Alt+S" },
436 { "Save As...", ma_save_as, "Shift Alt<Key>s", "Shift+Alt+S" },
437 { "", NULL, NULL, NULL },
438 { "Write and Quit", ma_wq, "Shift Alt<Key>q", "Shift+Alt+Q" },
439 { "Quit", ma_quit, "Alt<Key>q", "Alt+Q" },
440 { NULL, NULL, NULL, NULL },
443 static pull_down edit_menu[] = {
444 { "Undo", ma_undo, NULL, NULL },
445 { "", NULL, NULL, NULL },
446 { "Cut", ma_cut, "Alt<Key>x", "Alt+X" },
447 { "Copy", ma_copy, "Alt<Key>c", "Alt+C" },
448 { "Paste", ma_paste, "Alt<Key>v", "Alt+V" },
449 { "", NULL, NULL, NULL },
450 { "Find", ma_find, "Alt<Key>f", "Alt+F" },
451 { "Find Next", ma_find_next, "Alt<Key>g", "Alt+G" },
452 { NULL, NULL, NULL, NULL },
455 static pull_down options_menu[] = {
456 { "Preferences", ma_preferences, NULL, NULL },
457 { "Command Mode Maps", NULL, NULL, NULL },
458 { "Insert Mode Maps", NULL, NULL, NULL },
459 { NULL, NULL, NULL, NULL },
462 static pull_down tag_menu[] = {
463 { "Show Tag Stack", ma_tags, "Alt<Key>t", "Alt+T" },
464 { "", NULL, NULL, NULL },
465 { "Pop Tag", ma_tagpop, NULL, NULL },
466 { "Clear Stack", ma_tagtop, NULL, NULL },
467 { NULL, NULL, NULL, NULL },
470 static pull_down help_menu[] = {
471 { NULL, NULL, NULL, NULL },
474 static menu_bar main_menu[] = {
475 { 'F', "File", file_menu },
476 { 'E', "Edit", edit_menu },
477 { 'O', "Options", options_menu },
478 { 'T', "Tag", tag_menu },
479 { 'H', "Help", help_menu },
480 { 0, NULL, NULL },
484 #if defined(__STDC__)
485 static void add_entries( Widget parent, pull_down *actions )
486 #else
487 static void add_entries( parent, actions )
488 Widget parent;
489 pull_down *actions;
490 #endif
492 Widget w;
493 XmString str;
495 for ( ; actions->title != NULL; actions++ ) {
497 /* a separator? */
498 if ( *actions->title != '\0' ) {
499 w = XmCreatePushButton( parent, actions->title, NULL, 0 );
500 if ( actions->action == NULL )
501 XtSetSensitive( w, False );
502 else
503 XtAddCallback( w,
504 XmNactivateCallback,
505 (XtCallbackProc) actions->action,
506 actions
508 if ( actions->accel != NULL ) {
509 str = XmStringCreateSimple( actions->accel_text );
510 XtVaSetValues( w,
511 XmNaccelerator, actions->accel,
512 XmNacceleratorText, str,
515 XmStringFree( str );
518 else {
519 w = XmCreateSeparator( parent, "separator", NULL, 0 );
522 XtManageChild( w );
528 * vi_create_menubar --
530 * PUBLIC: Widget vi_create_menubar __P((Widget));
532 Widget
533 vi_create_menubar(parent)
534 Widget parent;
536 Widget menu, pull, button;
537 menu_bar *ptr;
539 /* save this for creation of children */
540 main_widget = parent;
542 menu = XmCreateMenuBar( parent, "Menu", NULL, 0 );
544 for ( ptr=main_menu; ptr->title != NULL; ptr++ ) {
546 pull = XmCreatePulldownMenu( menu, "pull", NULL, 0 );
547 add_entries( pull, ptr->actions );
548 button = XmCreateCascadeButton( menu, ptr->title, NULL, 0 );
549 XtVaSetValues( button, XmNsubMenuId, pull, 0 );
551 if ( strcmp( ptr->title, "Help" ) == 0 )
552 XtVaSetValues( menu, XmNmenuHelpWidget, button, 0 );
554 #if 0
555 /* These screw up accelerator processing. Punt for now */
556 if ( ptr->mnemonic )
557 XtVaSetValues( button, XmNmnemonic, ptr->mnemonic, 0 );
558 #endif
560 XtManageChild( button );
563 return menu;