failed attempt to use slang curses; leave changes in in case someone wants to try...
[nvi.git] / motif_l / m_menu.c
blobf7dc522c91360ff00e98e6b6752a47e463639537
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.24 2000/06/28 20:20:39 skimo Exp $ (Berkeley) $Date: 2000/06/28 20:20:39 $";
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 "../ipc/ip.h"
32 #include "m_motif.h"
34 extern int vi_ofd;
36 /* save this for creation of children */
37 static Widget main_widget = NULL;
39 /* This module defines the menu structure for vi. Each menu
40 * item has an action routine associated with it. For the most
41 * part, those actions will simply call vi_send with vi commands.
42 * others will pop up file selection dialogs and use them for
43 * vi commands, and other will have to have special actions.
45 * Future:
46 * vi core will have to let us know when to be sensitive
47 * change VI_STRING to VI_COMMAND so that menu actions cannot
48 * be confusing when in insert mode
49 * need VI_CUT, VI_COPY, and VI_PASTE to perform the appropriate
50 * operations on the visible text of yank buffer. VI_COPY
51 * is likely a NOP, but it will make users happy
52 * add mnemonics
53 * add accelerators
54 * implement file selection dialog boxes
55 * implement string prompt dialog boxes (e.g. for 'find')
57 * Interface:
58 * Widget create_menubar( Widget parent ) creates and returns the
59 * X menu structure. The caller can place this
60 * anywhere in the widget heirarchy.
63 #define BufferSize 1024
66 * __vi_send_command_string --
67 * Utility: Send a menu command to vi
69 * Future:
70 * Change VI_STRING to VI_COMMAND so that menu actions cannot be confusing
71 * when in insert mode.
73 * XXX
74 * THIS SHOULD GO AWAY -- WE SHOULDN'T SEND UNINTERPRETED STRINGS TO THE
75 * CORE.
77 * PUBLIC: void __vi_send_command_string __P((String));
79 void
80 __vi_send_command_string(str)
81 String str;
83 IP_BUF ipb;
84 char buffer[BufferSize];
86 /* Future: Need VI_COMMAND so vi knows this is not text to insert
87 * At that point, appending a cr/lf will not be necessary. For now,
88 * append iff we are a colon or slash command. Of course, if we are in
89 * insert mode, all bets are off.
91 strcpy( buffer, str );
92 switch ( *str ) {
93 case ':':
94 case '/':
95 strcat( buffer, "\n" );
96 break;
99 ipb.code = VI_STRING;
100 ipb.str1 = buffer;
101 ipb.len1 = strlen(buffer);
102 vi_send(vi_ofd, "a", &ipb);
106 /* Utility: beep for unimplemented command */
108 #if defined(__STDC__)
109 static void send_beep( Widget w )
110 #else
111 static void send_beep( w )
112 Widget w;
113 #endif
115 XBell( XtDisplay(w), 0 );
120 * __vi_cancel_cb --
121 * Utility: make a dialog box go Modal
123 * PUBLIC: void __vi_cancel_cb __P((Widget, XtPointer, XtPointer));
125 static Bool have_answer;
126 void
127 __vi_cancel_cb(w, client_data, call_data)
128 Widget w;
129 XtPointer client_data, call_data;
131 have_answer = True;
135 * PUBLIC: void __vi_modal_dialog __P((Widget));
137 void
138 __vi_modal_dialog( db )
139 Widget db;
141 XtAppContext ctx;
143 /* post the dialog */
144 XtManageChild( db );
145 XtPopup( XtParent(db), XtGrabExclusive );
147 /* wait for a response */
148 ctx = XtWidgetToApplicationContext(db);
149 XtAddGrab( XtParent(db), TRUE, FALSE );
150 for ( have_answer = False; ! have_answer; )
151 XtAppProcessEvent( ctx, XtIMAll );
153 /* done with db */
154 XtPopdown( XtParent(db) );
155 XtRemoveGrab( XtParent(db) );
159 /* Utility: Get a file (using standard File Selection Dialog Box) */
161 static String file_name;
164 #if defined(__STDC__)
165 static void ok_file_name( Widget w,
166 XtPointer client_data,
167 XtPointer call_data
169 #else
170 static void ok_file_name( w, client_data, call_data )
171 Widget w;
172 XtPointer client_data;
173 XtPointer call_data;
174 #endif
176 XmFileSelectionBoxCallbackStruct *cbs;
178 cbs = (XmFileSelectionBoxCallbackStruct *) call_data;
179 XmStringGetLtoR( cbs->value, XmSTRING_DEFAULT_CHARSET, &file_name );
181 have_answer = True;
185 #if defined(__STDC__)
186 static String get_file( Widget w, String prompt )
187 #else
188 static String get_file( w, prompt )
189 Widget w;
190 String prompt;
191 #endif
193 /* make it static so we can reuse it */
194 static Widget db;
196 /* our return parameter */
197 if ( file_name != NULL ) {
198 XtFree( file_name );
199 file_name = NULL;
202 /* create one? */
203 if ( db == NULL ){
204 db = XmCreateFileSelectionDialog( main_widget, "file", NULL, 0 );
205 XtAddCallback( db, XmNokCallback, ok_file_name, NULL );
206 XtAddCallback( db, XmNcancelCallback, __vi_cancel_cb, NULL );
209 /* use the title as a prompt */
210 XtVaSetValues( XtParent(db), XmNtitle, prompt, 0 );
212 /* wait for a response */
213 __vi_modal_dialog( db );
215 /* done */
216 return file_name;
221 * file_command --
222 * Get a file name and send it with the command to the core.
224 static void
225 file_command(w, code, prompt)
226 Widget w;
227 int code;
228 String prompt;
230 IP_BUF ipb;
231 char *file;
233 if ((file = get_file(w, prompt)) != NULL) {
234 ipb.code = code;
235 ipb.str1 = file;
236 ipb.len1 = strlen(file);
237 vi_send(vi_ofd, "a", &ipb);
243 * Menu action routines (one per menu entry)
245 * These are in the order in which they appear in the menu structure.
247 static void
248 ma_edit_file(w, call_data, client_data)
249 Widget w;
250 XtPointer call_data, client_data;
252 file_command(w, VI_EDIT, "Edit");
255 static void
256 ma_split(w, call_data, client_data)
257 Widget w;
258 XtPointer call_data, client_data;
260 file_command(w, VI_EDITSPLIT, "Edit");
263 static void
264 ma_save(w, call_data, client_data)
265 Widget w;
266 XtPointer call_data, client_data;
268 IP_BUF ipb;
270 ipb.code = VI_WRITE;
271 (void)vi_send(vi_ofd, NULL, &ipb);
274 static void
275 ma_save_as(w, call_data, client_data)
276 Widget w;
277 XtPointer call_data, client_data;
279 file_command(w, VI_WRITEAS, "Save As");
282 static void
283 ma_wq(w, call_data, client_data)
284 Widget w;
285 XtPointer call_data, client_data;
287 IP_BUF ipb;
289 ipb.code = VI_WQ;
290 (void)vi_send(vi_ofd, NULL, &ipb);
293 static void
294 ma_quit(w, call_data, client_data)
295 Widget w;
296 XtPointer call_data, client_data;
298 IP_BUF ipb;
300 ipb.code = VI_QUIT;
301 (void)vi_send(vi_ofd, NULL, &ipb);
304 static void
305 ma_undo(w, call_data, client_data)
306 Widget w;
307 XtPointer call_data, client_data;
309 IP_BUF ipb;
311 ipb.code = VI_UNDO;
312 (void)vi_send(vi_ofd, NULL, &ipb);
315 #if defined(__STDC__)
316 static void ma_cut( Widget w,
317 XtPointer call_data,
318 XtPointer client_data
320 #else
321 static void ma_cut( w, call_data, client_data )
322 Widget w;
323 XtPointer call_data;
324 XtPointer client_data;
325 #endif
327 /* future */
328 send_beep( w );
332 #if defined(__STDC__)
333 static void ma_copy( Widget w,
334 XtPointer call_data,
335 XtPointer client_data
337 #else
338 static void ma_copy( w, call_data, client_data )
339 Widget w;
340 XtPointer call_data;
341 XtPointer client_data;
342 #endif
344 /* future */
345 send_beep( w );
349 #if defined(__STDC__)
350 static void ma_paste( Widget w,
351 XtPointer call_data,
352 XtPointer client_data
354 #else
355 static void ma_paste( w, call_data, client_data )
356 Widget w;
357 XtPointer call_data;
358 XtPointer client_data;
359 #endif
361 /* future */
362 send_beep( w );
365 static void
366 ma_find(w, call_data, client_data)
367 Widget w;
368 XtPointer call_data, client_data;
370 __vi_show_search_dialog( main_widget, "Find" );
373 static void
374 ma_find_next(w, call_data, client_data)
375 Widget w;
376 XtPointer call_data, client_data;
378 __vi_search( w );
381 static void
382 ma_tags(w, call_data, client_data)
383 Widget w;
384 XtPointer call_data, client_data;
386 __vi_show_tags_dialog( main_widget, "Tag Stack" );
389 static void
390 ma_tagpop(w, call_data, client_data)
391 Widget w;
392 XtPointer call_data, client_data;
394 __vi_send_command_string( "\024" );
397 static void
398 ma_tagtop(w, call_data, client_data)
399 Widget w;
400 XtPointer call_data, client_data;
402 __vi_send_command_string( ":tagtop" );
405 #if defined(__STDC__)
406 static void ma_preferences( Widget w,
407 XtPointer call_data,
408 XtPointer client_data
410 #else
411 static void ma_preferences( w, call_data, client_data )
412 Widget w;
413 XtPointer call_data;
414 XtPointer client_data;
415 #endif
417 __vi_show_options_dialog( main_widget, "Preferences" );
421 /* Menu construction routines */
423 typedef struct {
424 String title;
425 void (*action)();
426 String accel; /* for Motif */
427 String accel_text; /* for the user */
428 } pull_down;
430 typedef struct {
431 char mnemonic;
432 String title;
433 pull_down *actions;
434 } menu_bar;
436 static pull_down file_menu[] = {
437 { "Edit File...", ma_edit_file, "Alt<Key>e", "Alt+E" },
438 { "", NULL, NULL, NULL },
439 { "Split Window...", ma_split, NULL, NULL },
440 { "", NULL, NULL, NULL },
441 { "Save ", ma_save, "Alt<Key>s", "Alt+S" },
442 { "Save As...", ma_save_as, "Shift Alt<Key>s", "Shift+Alt+S" },
443 { "", NULL, NULL, NULL },
444 { "Write and Quit", ma_wq, "Shift Alt<Key>q", "Shift+Alt+Q" },
445 { "Quit", ma_quit, "Alt<Key>q", "Alt+Q" },
446 { NULL, NULL, NULL, NULL },
449 static pull_down edit_menu[] = {
450 { "Undo", ma_undo, NULL, NULL },
451 { "", NULL, NULL, NULL },
452 { "Cut", ma_cut, "Alt<Key>x", "Alt+X" },
453 { "Copy", ma_copy, "Alt<Key>c", "Alt+C" },
454 { "Paste", ma_paste, "Alt<Key>v", "Alt+V" },
455 { "", NULL, NULL, NULL },
456 { "Find", ma_find, "Alt<Key>f", "Alt+F" },
457 { "Find Next", ma_find_next, "Alt<Key>g", "Alt+G" },
458 { NULL, NULL, NULL, NULL },
461 static pull_down options_menu[] = {
462 { "Preferences", ma_preferences, NULL, NULL },
463 { "Command Mode Maps", NULL, NULL, NULL },
464 { "Insert Mode Maps", NULL, NULL, NULL },
465 { NULL, NULL, NULL, NULL },
468 static pull_down tag_menu[] = {
469 { "Show Tag Stack", ma_tags, "Alt<Key>t", "Alt+T" },
470 { "", NULL, NULL, NULL },
471 { "Pop Tag", ma_tagpop, NULL, NULL },
472 { "Clear Stack", ma_tagtop, NULL, NULL },
473 { NULL, NULL, NULL, NULL },
476 static pull_down help_menu[] = {
477 { NULL, NULL, NULL, NULL },
480 static menu_bar main_menu[] = {
481 { 'F', "File", file_menu },
482 { 'E', "Edit", edit_menu },
483 { 'O', "Options", options_menu },
484 { 'T', "Tag", tag_menu },
485 { 'H', "Help", help_menu },
486 { 0, NULL, NULL },
490 #if defined(__STDC__)
491 static void add_entries( Widget parent, pull_down *actions )
492 #else
493 static void add_entries( parent, actions )
494 Widget parent;
495 pull_down *actions;
496 #endif
498 Widget w;
499 XmString str;
501 for ( ; actions->title != NULL; actions++ ) {
503 /* a separator? */
504 if ( *actions->title != '\0' ) {
505 w = XmCreatePushButton( parent, actions->title, NULL, 0 );
506 if ( actions->action == NULL )
507 XtSetSensitive( w, False );
508 else
509 XtAddCallback( w,
510 XmNactivateCallback,
511 (XtCallbackProc) actions->action,
512 actions
514 if ( actions->accel != NULL ) {
515 str = XmStringCreateSimple( actions->accel_text );
516 XtVaSetValues( w,
517 XmNaccelerator, actions->accel,
518 XmNacceleratorText, str,
521 XmStringFree( str );
524 else {
525 w = XmCreateSeparator( parent, "separator", NULL, 0 );
528 XtManageChild( w );
534 * vi_create_menubar --
536 * PUBLIC: Widget vi_create_menubar __P((Widget));
538 Widget
539 vi_create_menubar(parent)
540 Widget parent;
542 Widget menu, pull, button;
543 menu_bar *ptr;
545 /* save this for creation of children */
546 main_widget = parent;
548 menu = XmCreateMenuBar( parent, "Menu", NULL, 0 );
550 for ( ptr=main_menu; ptr->title != NULL; ptr++ ) {
552 pull = XmCreatePulldownMenu( menu, "pull", NULL, 0 );
553 add_entries( pull, ptr->actions );
554 button = XmCreateCascadeButton( menu, ptr->title, NULL, 0 );
555 XtVaSetValues( button, XmNsubMenuId, pull, 0 );
557 if ( strcmp( ptr->title, "Help" ) == 0 )
558 XtVaSetValues( menu, XmNmenuHelpWidget, button, 0 );
560 #if 0
561 /* These screw up accelerator processing. Punt for now */
562 if ( ptr->mnemonic )
563 XtVaSetValues( button, XmNmnemonic, ptr->mnemonic, 0 );
564 #endif
566 XtManageChild( button );
569 return menu;