dist/distrib: generate vi.0
[nvi.git] / motif_l / m_options.c
blobc42a38d4bfbf85413a607e2754b7faaddbbad54d
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_options.c,v 8.22 2003/11/05 17:09:59 skimo Exp $ (Berkeley) $Date: 2003/11/05 17:09:59 $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
19 #include <X11/X.h>
20 #include <X11/Intrinsic.h>
21 #include <Xm/DialogS.h>
22 #include <Xm/Form.h>
23 #include <Xm/Frame.h>
24 #include <Xm/LabelG.h>
25 #include <Xm/PushBG.h>
26 #include <Xm/TextF.h>
27 #include <Xm/ToggleBG.h>
28 #include <Xm/RowColumn.h>
30 #include <bitstring.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #undef LOCK_SUCCESS
36 #include "../common/common.h"
37 #include "../ipc/ip.h"
38 #include "m_motif.h"
40 extern int vi_ofd;
42 static void set_opt __P((Widget, XtPointer, XtPointer));
45 /* constants */
47 #if defined(SelfTest)
49 /* in production, get these from the resource list */
51 #define toggleColumns 6
53 #endif
57 * global data
60 static Widget preferences = NULL;
62 static optData display[] = {
63 { optToggle, "comment", },
64 { optToggle, "flash", },
65 { optToggle, "leftright", },
66 { optToggle, "list", },
67 { optToggle, "number", },
68 { optToggle, "octal", },
69 { optToggle, "ruler", },
70 { optToggle, "showmode", },
71 { optToggle, "slowopen", },
72 { optToggle, "verbose", },
73 { optToggle, "windowname", },
74 { optTerminator, },
75 }, display_int[] = {
76 { optInteger, "report", },
77 { optInteger, "scroll", },
78 { optInteger, "shiftwidth", },
79 { optInteger, "sidescroll", },
80 { optInteger, "tabstop", },
81 { optInteger, "window", },
82 { optTerminator, },
83 }, display_str[] = {
84 { optString, "noprint", },
85 { optString, "print", },
86 { optTerminator, },
87 }, files[] = {
88 { optToggle, "autowrite", },
89 { optToggle, "lock", },
90 { optToggle, "readonly", },
91 { optToggle, "writeany", },
92 { optTerminator, },
93 }, files_str[] = {
94 { optString, "backup", },
95 { optString, "path", },
96 { optTerminator, },
97 }, general[] = {
98 { optToggle, "exrc", },
99 { optToggle, "lisp", },
100 { optToggle, "modeline", },
101 { optToggle, "sourceany", },
102 { optToggle, "tildeop", },
103 { optTerminator, },
104 }, general_int[] = {
105 { optInteger, "taglength", },
106 { optTerminator, },
107 }, general_str[] = {
108 { optString, "cdpath", },
109 { optString, "directory", },
110 { optString, "msgcat", },
111 { optString, "recdir", },
112 { optString, "shell", },
113 { optString, "shellmeta", },
114 { optString, "tags", },
115 { optTerminator, },
116 }, input[] = {
117 { optToggle, "altwerase", },
118 { optToggle, "autoindent", },
119 { optToggle, "remap", },
120 { optToggle, "showmatch", },
121 { optToggle, "ttywerase", },
122 { optTerminator, },
123 }, input_int[] = {
124 { optInteger, "escapetime", },
125 { optInteger, "keytime", },
126 { optInteger, "matchtime", },
127 { optInteger, "timeout", },
128 { optInteger, "wraplen", },
129 { optInteger, "wrapmargin", },
130 { optTerminator, },
131 }, input_str[] = {
132 { optString, "cedit", },
133 { optString, "filec", },
134 { optTerminator, },
135 }, search[] = {
136 { optToggle, "extended", },
137 { optToggle, "iclower", },
138 { optToggle, "ignorecase", },
139 { optToggle, "magic", },
140 { optToggle, "searchincr", },
141 { optToggle, "wrapscan", },
142 { optTerminator, },
143 }, search_str[] = {
144 { optString, "paragraphs", },
145 { optString, "sections", },
146 { optTerminator, },
149 /* ********* NOTE ***********
150 * Sheet 0 will always be shown first. It does not matter to the Xt code
151 * which sheet that is, so it ought to be the one users interact with most.
152 * Best guess is that's general editor options, but it might be Search/re.
153 * ********* NOTE ***********
155 static optSheet sheets[] = {
156 { "Display",
157 "These options control how text is displayed on the screen",
158 NULL,
159 display,
160 display_int,
161 display_str,
163 { "Files",
164 "These options control how the editor handles files",
165 NULL,
166 files,
167 NULL,
168 files_str,
170 { "Input",
171 "These options control text input behavior",
172 NULL,
173 input,
174 input_int,
175 input_str,
177 { "Search/RE",
178 "These options control searching and Regular Expression behavior",
179 NULL,
180 search,
181 NULL,
182 search_str,
184 { "Editor",
185 "These options control general editor configuration",
186 NULL,
187 general,
188 general_int,
189 general_str,
194 /* callbacks */
196 #if defined(SelfTest)
197 void __vi_cancel_cb()
199 puts( "cancelled" );
201 #endif
204 static void destroyed(void)
206 int i;
208 puts( "destroyed" );
210 /* some window managers destroy us upon popdown */
211 for (i=0; i<XtNumber(sheets); i++) {
212 sheets[i].holder = NULL;
214 preferences = NULL;
218 static void window_unmapped(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
220 if ( ev->type == UnmapNotify ) {
221 #if defined(SelfTest)
222 puts( "unmapped" );
223 #endif
224 XtPopdown( XtParent( preferences ) );
229 * __vi_editopt --
230 * Set an edit option based on a core message.
232 * PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
235 __vi_editopt(IPVI *ipvi, const char *str1, u_int32_t len1, const char *str2, u_int32_t len2, u_int32_t val1)
237 optData *opt;
239 #undef NSEARCH
240 #define NSEARCH(list) { \
241 for (opt = list; opt->kind != optTerminator; ++opt) \
242 if (!strcmp(opt->name, str1)) \
243 goto found; \
246 NSEARCH(display);
247 NSEARCH(display_int);
248 NSEARCH(display_str);
249 NSEARCH(files);
250 NSEARCH(files_str);
251 NSEARCH(general);
252 NSEARCH(general_int);
253 NSEARCH(general_str);
254 NSEARCH(input);
255 NSEARCH(input_int);
256 NSEARCH(input_str);
257 NSEARCH(search);
258 NSEARCH(search_str);
260 return (0);
262 found: switch (opt->kind) {
263 case optToggle:
264 opt->value = (void *)val1;
265 break;
266 case optInteger:
267 if (opt->value != NULL)
268 free(opt->value);
269 if ((opt->value = malloc(8)) != NULL)
270 (void)snprintf(opt->value,
271 8, "%lu", (u_long)val1);
272 break;
273 case optString:
274 case optFile:
275 if (opt->value != NULL)
276 free(opt->value);
277 if ((opt->value = malloc(len2)) != NULL)
278 memcpy(opt->value, str2, len2);
279 break;
280 case optTerminator:
281 abort();
283 return (0);
287 * set_opt --
288 * Send a set-edit-option message to core.
290 static void
291 set_opt(Widget w, XtPointer closure, XtPointer call_data)
293 optData *opt;
294 Boolean set;
295 IP_BUF ipb;
296 String str;
297 extern IPVI ipvi_motif;
299 opt = closure;
301 ipb.code = VI_EDITOPT;
302 ipb.str1 = opt->name;
303 ipb.len1 = strlen(opt->name);
305 switch (opt->kind) {
306 case optToggle:
307 XtVaGetValues(w, XmNset, &set, 0);
308 ipb.val1 = set;
309 ipb.len2 = 0;
311 vi_wsend(&ipvi_motif, "ab1", &ipb);
312 if (ipb.val1) {
313 opt->value = (void *)!set;
315 * RAZ:
316 * How do we turn off the button? We don't want to
317 * go recursive where we set it and it calls set_opt
318 * to tell the core. Is that possible?
320 XtVaSetValues(w, XmNset, &set, 0);
321 break;
324 if (strcmp(opt->name, "ruler") == 0)
325 if (set)
326 __vi_show_text_ruler_dialog(
327 __vi_screen->area, "Ruler");
328 else
329 __vi_clear_text_ruler_dialog();
330 break;
331 case optInteger:
332 str = XmTextFieldGetString(w);
333 ipb.val1 = atoi(str);
334 ipb.len2 = 0;
335 vi_send(vi_ofd, "ab1", &ipb);
336 break;
337 case optFile:
338 case optString:
339 ipb.str2 = XmTextFieldGetString(w);
340 ipb.len2 = strlen(ipb.str2);
341 vi_send(vi_ofd, "ab1", &ipb);
342 break;
343 case optTerminator:
344 abort();
349 /* add toggles to the property sheet */
351 #if defined(__STDC__)
352 static void add_toggle( Widget parent, optData *option )
353 #else
354 static void add_toggle( parent, option )
355 Widget parent;
356 optData *option;
357 #endif
359 Widget w;
361 w = XtVaCreateManagedWidget( option->name,
362 xmToggleButtonGadgetClass,
363 parent,
364 XmNset, (Boolean) option->value,
367 XtAddCallback( w, XmNvalueChangedCallback, set_opt, option );
371 static Widget create_toggles(Widget outer, optData *toggles)
373 Widget inner;
374 int i;
376 inner = XtVaCreateWidget( "toggleOptions",
377 xmRowColumnWidgetClass,
378 outer,
379 XmNpacking, XmPACK_COLUMN,
380 XmNnumColumns, 4,
381 XmNtopAttachment, XmATTACH_FORM,
382 XmNrightAttachment, XmATTACH_FORM,
383 XmNleftAttachment, XmATTACH_FORM,
387 /* first the booleans */
388 for (i=0; toggles[i].kind != optTerminator; i++) {
389 add_toggle( inner, &toggles[i] );
391 XtManageChild( inner );
393 return inner;
397 /* draw text fields and their labels */
399 #if defined(__STDC__)
400 static void add_string_options( Widget parent,
401 optData *options
403 #else
404 static void add_string_options( parent, options )
405 Widget parent;
406 optData *options;
407 #endif
409 int i;
410 Widget f, w;
412 for ( i=0; options[i].kind != optTerminator; i++ ) {
414 f = XtVaCreateWidget( "form",
415 xmFormWidgetClass,
416 parent,
420 XtVaCreateManagedWidget( options[i].name,
421 xmLabelGadgetClass,
423 XmNtopAttachment, XmATTACH_FORM,
424 XmNbottomAttachment, XmATTACH_FORM,
425 XmNleftAttachment, XmATTACH_FORM,
426 XmNrightAttachment, XmATTACH_POSITION,
427 XmNrightPosition, 20,
428 XmNalignment, XmALIGNMENT_END,
432 w = XtVaCreateManagedWidget( "text",
433 xmTextFieldWidgetClass,
435 XmNtopAttachment, XmATTACH_FORM,
436 XmNbottomAttachment, XmATTACH_FORM,
437 XmNrightAttachment, XmATTACH_FORM,
438 XmNleftAttachment, XmATTACH_POSITION,
439 XmNleftPosition, 20,
443 XmTextFieldSetString( w, (char *) options[i].value );
444 XtAddCallback( w, XmNactivateCallback, set_opt, &options[i] );
445 XtManageChild( f );
450 /* draw and display a single page of properties */
452 #if defined(__STDC__)
453 static Widget create_sheet( Widget parent, optSheet *sheet )
454 #else
455 static Widget create_sheet( parent, sheet )
456 Widget parent;
457 optSheet *sheet;
458 #endif
460 Widget outer, inner, frame;
461 Dimension height;
462 XmString str;
464 outer = XtVaCreateWidget( sheet->name,
465 xmFormWidgetClass,
466 parent,
467 XmNtopAttachment, XmATTACH_FORM,
468 XmNrightAttachment, XmATTACH_FORM,
469 XmNbottomAttachment, XmATTACH_FORM,
470 XmNleftAttachment, XmATTACH_FORM,
471 XmNshadowType, XmSHADOW_ETCHED_IN,
472 XmNshadowThickness, 2,
473 XmNverticalSpacing, 4,
474 XmNhorizontalSpacing, 4,
478 /* add descriptive text */
479 frame = XtVaCreateManagedWidget( "frame",
480 xmFrameWidgetClass,
481 outer,
482 XmNtopAttachment, XmATTACH_FORM,
483 XmNrightAttachment, XmATTACH_FORM,
484 XmNleftAttachment, XmATTACH_FORM,
487 str = XmStringCreateLtoR( sheet->description, XmSTRING_DEFAULT_CHARSET );
488 XtVaCreateManagedWidget( "description",
489 xmLabelGadgetClass,
490 frame,
491 XmNlabelString, str,
494 XmStringFree( str );
496 /* Add the toggles. */
497 inner = create_toggles( outer, sheet->toggles );
498 XtVaSetValues( inner,
499 XmNtopAttachment, XmATTACH_WIDGET,
500 XmNtopWidget, frame,
504 /* the string options go here */
505 inner = XtVaCreateWidget( "otherOptions",
506 xmRowColumnWidgetClass,
507 outer,
508 XmNpacking, XmPACK_COLUMN,
509 XmNtopAttachment, XmATTACH_WIDGET,
510 XmNtopWidget, inner,
511 XmNrightAttachment, XmATTACH_FORM,
512 XmNbottomAttachment, XmATTACH_FORM,
513 XmNleftAttachment, XmATTACH_FORM,
517 /* Optionally, the ints. */
518 if ( sheet->ints != NULL )
519 add_string_options( inner, sheet->ints );
521 /* Optionally, the rest. */
522 if ( sheet->others != NULL )
523 add_string_options( inner, sheet->others );
525 XtManageChild( inner );
527 /* finally, force resize of the parent */
528 XtVaGetValues( outer, XmNheight, &height, 0 );
529 XtVaSetValues( parent, XmNheight, height, 0 );
531 return outer;
535 /* change preferences to another sheet */
537 static void change_sheet(Widget parent, int current)
539 static int current_sheet = -1;
541 /* create a new one? */
542 if ( sheets[current].holder == NULL )
543 sheets[current].holder = create_sheet( parent, &sheets[current] );
545 /* done with the old one? */
546 if ( current_sheet != -1 && sheets[current_sheet].holder != NULL )
547 XtUnmanageChild( sheets[current_sheet].holder );
549 current_sheet = current;
550 XtManageChild( sheets[current].holder );
551 XtManageChild( parent );
555 /* Draw and display a dialog the describes vi options */
557 #if defined(__STDC__)
558 static Widget create_options_dialog( Widget parent, String title )
559 #else
560 static Widget create_options_dialog( parent, title )
561 Widget parent;
562 String title;
563 #endif
565 Widget box, form, inner;
566 int i;
567 char buffer[1024];
569 /* already built? */
570 if ( preferences != NULL ) return preferences;
572 box = XtVaCreatePopupShell( title,
573 xmDialogShellWidgetClass,
574 parent,
575 XmNtitle, title,
576 XmNallowShellResize, False,
579 XtAddCallback( box, XmNpopdownCallback, __vi_cancel_cb, 0 );
580 XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
581 XtAddEventHandler( box,
582 SubstructureNotifyMask,
583 False,
584 window_unmapped,
585 NULL
588 form = XtVaCreateWidget( "options",
589 xmFormWidgetClass,
590 box,
594 /* copy the pointers to the sheet names */
595 *buffer = '\0';
596 for (i=0; i<XtNumber(sheets); i++) {
597 strcat( buffer, "|" );
598 strcat( buffer, sheets[i].name );
601 inner = __vi_CreateTabbedFolder( "tabs",
602 form,
603 buffer,
604 XtNumber(sheets),
605 change_sheet
608 /* build the property sheets early */
609 for ( i=0; i<XtNumber(sheets); i++ )
610 change_sheet( inner, i );
612 /* manage all of the sheets right now */
613 for ( i=0; i<XtNumber(sheets); i++ )
614 XtManageChild( sheets[i].holder );
615 XtManageChild( form );
617 /* remove all but the first one */
618 for ( i=0; i<XtNumber(sheets); i++ )
619 XtUnmanageChild( sheets[i].holder );
620 change_sheet( inner, 0 ); /* show first sheet first */
622 /* keep this global, we might destroy it later */
623 preferences = form;
625 /* done */
626 return form;
632 * module entry point
634 * __vi_show_options_dialog --
637 * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
639 void
640 __vi_show_options_dialog(Widget parent, String title)
642 Widget db = create_options_dialog( parent, title );
643 #if defined(SelfTest)
644 Widget shell = XtParent( db );
645 #endif
647 XtManageChild( db );
649 #if defined(SelfTest)
650 /* wait until it goes away */
651 XtPopup( shell, XtGrabNone );
652 #else
653 /* wait until it goes away */
654 __vi_modal_dialog( db );
655 #endif
660 /* module entry point
661 * Utilities for the search dialog
663 * __vi_toggle --
664 * Returns the current value of a toggle.
666 * PUBLIC: int __vi_toggle __P((char *));
669 __vi_toggle(char *name)
671 optData *opt;
673 #undef NSEARCH
674 #define NSEARCH(list) { \
675 for (opt = list; opt->kind != optTerminator; ++opt) \
676 if (!strcmp(opt->name, name)) \
677 return ((int)opt->value); \
679 NSEARCH(display);
680 NSEARCH(files);
681 NSEARCH(general);
682 NSEARCH(input);
683 NSEARCH(search);
685 return (0);
689 * __vi_create_search_toggles --
690 * Creates the search toggles. This is so the options and search widgets
691 * share their appearance.
693 * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
695 Widget
696 __vi_create_search_toggles(Widget parent, optData *list)
698 optData *opt;
701 * Copy current options information into the search table.
703 * XXX
704 * This is an O(M*N) loop, but I don't think it matters.
706 for (opt = list; opt->kind != optTerminator; ++opt)
707 opt->value = (void *)__vi_toggle(opt->name);
709 return (create_toggles(parent, list));
713 #if defined(SelfTest)
715 #if defined(__STDC__)
716 static void show_options( Widget w, XtPointer data, XtPointer cbs )
717 #else
718 static void show_options( w, data, cbs )
719 Widget w;
720 XtPointer data;
721 XtPointer cbs;
722 #endif
724 __vi_show_options_dialog( data, "Preferences" );
727 main( int argc, char *argv[] )
729 XtAppContext ctx;
730 Widget top_level, rc, button;
731 extern exit();
733 /* create a top-level shell for the window manager */
734 top_level = XtVaAppInitialize( &ctx,
735 argv[0],
736 NULL, 0, /* options */
737 (ArgcType) &argc,
738 argv, /* might get modified */
739 NULL,
740 NULL
743 rc = XtVaCreateManagedWidget( "rc",
744 xmRowColumnWidgetClass,
745 top_level,
749 button = XtVaCreateManagedWidget( "Pop up options dialog",
750 xmPushButtonGadgetClass,
754 XtAddCallback( button, XmNactivateCallback, show_options, rc );
756 button = XtVaCreateManagedWidget( "Quit",
757 xmPushButtonGadgetClass,
761 XtAddCallback( button, XmNactivateCallback, exit, 0 );
763 XtRealizeWidget(top_level);
764 XtAppMainLoop(ctx);
766 #endif