minor text whacking
[nvi.git] / motif_l / m_options.c
blob62dc47f25a2f21c7b4801082ad44e38ceb038169
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.16 1996/12/20 10:29:10 bostic Exp $ (Berkeley) $Date: 1996/12/20 10:29:10 $";
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 #include "../common/common.h"
36 #include "../ipc/ip.h"
37 #include "m_motif.h"
39 static void set_opt __P((Widget, XtPointer, XtPointer));
42 /* constants */
44 #if defined(SelfTest)
46 /* in production, get these from the resource list */
48 #define toggleColumns 6
50 #endif
54 * global data
57 static Widget preferences = NULL;
59 static optData display[] = {
60 { optToggle, "comment", },
61 { optToggle, "flash", },
62 { optToggle, "leftright", },
63 { optToggle, "list", },
64 { optToggle, "number", },
65 { optToggle, "octal", },
66 { optToggle, "ruler", },
67 { optToggle, "showmode", },
68 { optToggle, "slowopen", },
69 { optToggle, "verbose", },
70 { optToggle, "window", },
71 { optToggle, "windowname", },
72 { optTerminator, },
73 }, display_int[] = {
74 { optInteger, "report", },
75 { optInteger, "scroll", },
76 { optInteger, "shiftwidth", },
77 { optInteger, "sidescroll", },
78 { optInteger, "tabstop", },
79 { optTerminator, },
80 }, display_str[] = {
81 { optString, "noprint", },
82 { optString, "print", },
83 { optTerminator, },
84 }, files[] = {
85 { optToggle, "autowrite", },
86 { optToggle, "lock", },
87 { optToggle, "readonly", },
88 { optToggle, "writeany", },
89 { optTerminator, },
90 }, files_str[] = {
91 { optString, "backup", },
92 { optString, "path", },
93 { optTerminator, },
94 }, general[] = {
95 { optToggle, "exrc", },
96 { optToggle, "lisp", },
97 { optToggle, "modeline", },
98 { optToggle, "sourceany", },
99 { optToggle, "tildeop", },
100 { optTerminator, },
101 }, general_int[] = {
102 { optInteger, "taglength", },
103 { optTerminator, },
104 }, general_str[] = {
105 { optString, "cdpath", },
106 { optString, "directory", },
107 { optString, "msgcat", },
108 { optString, "recdir", },
109 { optString, "shell", },
110 { optString, "shellmeta", },
111 { optString, "tags", },
112 { optTerminator, },
113 }, input[] = {
114 { optToggle, "altwerase", },
115 { optToggle, "autoindent", },
116 { optToggle, "remap", },
117 { optToggle, "showmatch", },
118 { optToggle, "ttywerase", },
119 { optTerminator, },
120 }, input_int[] = {
121 { optInteger, "escapetime", },
122 { optInteger, "keytime", },
123 { optInteger, "matchtime", },
124 { optInteger, "timeout", },
125 { optInteger, "wraplen", },
126 { optInteger, "wrapmargin", },
127 { optTerminator, },
128 }, input_str[] = {
129 { optString, "cedit", },
130 { optString, "filec", },
131 { optTerminator, },
132 }, search[] = {
133 { optToggle, "extended", },
134 { optToggle, "iclower", },
135 { optToggle, "ignorecase", },
136 { optToggle, "magic", },
137 { optToggle, "searchincr", },
138 { optToggle, "wrapscan", },
139 { optTerminator, },
140 }, search_str[] = {
141 { optString, "paragraphs", },
142 { optString, "sections", },
143 { optTerminator, },
146 /* ********* NOTE ***********
147 * Sheet 0 will always be shown first. It does not matter to the Xt code
148 * which sheet that is, so it ought to be the one users interact with most.
149 * Best guess is that's general editor options, but it might be Search/re.
150 * ********* NOTE ***********
152 static optSheet sheets[] = {
153 { "Editor",
154 "These options control the general configuration\n\
155 and the editor as a whole",
156 NULL,
157 general,
158 general_int,
159 general_str,
161 { "Display",
162 "These options control the way things are displayed on the screen",
163 NULL,
164 display,
165 display_int,
166 display_str,
168 { "Files",
169 "These options globally modify how the editor handles files",
170 NULL,
171 files,
172 NULL,
173 files_str,
175 { "Input",
176 "These options modify how text input behaves",
177 NULL,
178 input,
179 input_int,
180 input_str,
182 { "Search/RE",
183 "These options modify searches and regular expression",
184 NULL,
185 search,
186 NULL,
187 search_str,
192 /* callbacks */
194 #if defined(SelfTest)
195 void __vi_cancel_cb()
197 puts( "cancelled" );
199 #endif
202 static void destroyed()
204 int i;
206 puts( "destroyed" );
208 /* some window managers destroy us upon popdown */
209 for (i=0; i<XtNumber(sheets); i++) {
210 sheets[i].holder = NULL;
212 preferences = NULL;
216 static void window_unmapped( w, ptr, ev, cont )
217 Widget w;
218 XtPointer ptr;
219 XEvent *ev;
220 Boolean *cont;
222 if ( ev->type == UnmapNotify ) {
223 #if defined(SelfTest)
224 puts( "unmapped" );
225 #endif
226 XtPopdown( XtParent( preferences ) );
231 * __vi_editopt --
232 * Set an edit option based on a core message.
234 * PUBLIC: int __vi_editopt __P((IP_BUF *));
237 __vi_editopt(ipbp)
238 IP_BUF *ipbp;
240 optData *opt;
242 #undef NSEARCH
243 #define NSEARCH(list) { \
244 for (opt = list; opt->kind != optTerminator; ++opt) \
245 if (!strcmp(opt->name, ipbp->str1)) \
246 goto found; \
249 NSEARCH(display);
250 NSEARCH(display_int);
251 NSEARCH(display_str);
252 NSEARCH(files);
253 NSEARCH(files_str);
254 NSEARCH(general);
255 NSEARCH(general_int);
256 NSEARCH(general_str);
257 NSEARCH(input);
258 NSEARCH(input_int);
259 NSEARCH(input_str);
260 NSEARCH(search);
261 NSEARCH(search_str);
263 return (0);
265 found: switch (opt->kind) {
266 case optToggle:
267 opt->value = (void *)ipbp->val1;
268 break;
269 case optInteger:
270 if (opt->value != NULL)
271 free(opt->value);
272 if ((opt->value = malloc(8)) != NULL)
273 (void)snprintf(opt->value,
274 8, "%lu", (u_long)ipbp->val1);
275 break;
276 case optString:
277 case optFile:
278 if (opt->value != NULL)
279 free(opt->value);
280 if ((opt->value = malloc(ipbp->len2)) != NULL)
281 memcpy(opt->value, ipbp->str2, ipbp->len2);
282 break;
283 case optTerminator:
284 abort();
286 return (0);
290 * set_opt --
291 * Send a set-edit-option message to core.
293 static void
294 set_opt(w, closure, call_data)
295 Widget w;
296 XtPointer closure, call_data;
298 optData *opt;
299 Boolean set;
300 IP_BUF ipb;
301 String str;
303 opt = closure;
305 ipb.code = VI_EDITOPT;
306 ipb.str1 = opt->name;
307 ipb.len1 = strlen(opt->name);
309 switch (opt->kind) {
310 case optToggle:
311 XtVaGetValues(w, XmNset, &set, 0);
312 ipb.val1 = set;
313 ipb.len2 = 0;
315 if (strcmp(opt->name, "ruler") == 0)
316 if (set)
317 __vi_show_text_ruler_dialog(
318 __vi_screen->area, "Ruler");
319 else
320 __vi_clear_text_ruler_dialog();
321 break;
322 case optInteger:
323 str = XmTextFieldGetString(w);
324 ipb.val1 = atoi(str);
325 ipb.len2 = 0;
326 break;
327 case optFile:
328 case optString:
329 ipb.str2 = XmTextFieldGetString(w);
330 ipb.len2 = strlen(ipb.str2);
331 break;
332 case optTerminator:
333 abort();
335 vi_send("ab1", &ipb);
339 /* add toggles to the property sheet */
341 #if defined(__STDC__)
342 static void add_toggle( Widget parent, optData *option )
343 #else
344 static void add_toggle( parent, option )
345 Widget parent;
346 optData *option;
347 #endif
349 Widget w;
351 w = XtVaCreateManagedWidget( option->name,
352 xmToggleButtonGadgetClass,
353 parent,
354 XmNset, (Boolean) option->value,
357 XtAddCallback( w, XmNvalueChangedCallback, set_opt, option );
361 static Widget create_toggles( outer, toggles )
362 Widget outer;
363 optData *toggles;
365 Widget inner;
366 int i;
368 inner = XtVaCreateWidget( "toggleOptions",
369 xmRowColumnWidgetClass,
370 outer,
371 XmNpacking, XmPACK_COLUMN,
372 XmNnumColumns, 4,
373 XmNtopAttachment, XmATTACH_FORM,
374 XmNrightAttachment, XmATTACH_FORM,
375 XmNleftAttachment, XmATTACH_FORM,
379 /* first the booleans */
380 for (i=0; toggles[i].kind != optTerminator; i++) {
381 add_toggle( inner, &toggles[i] );
383 XtManageChild( inner );
385 return inner;
389 /* draw text fields and their labels */
391 #if defined(__STDC__)
392 static void add_string_options( Widget parent,
393 optData *options
395 #else
396 static void add_string_options( parent, options )
397 Widget parent;
398 optData *options;
399 #endif
401 int i;
402 Widget f, w;
404 for ( i=0; options[i].kind != optTerminator; i++ ) {
406 f = XtVaCreateWidget( "form",
407 xmFormWidgetClass,
408 parent,
412 XtVaCreateManagedWidget( options[i].name,
413 xmLabelGadgetClass,
415 XmNtopAttachment, XmATTACH_FORM,
416 XmNbottomAttachment, XmATTACH_FORM,
417 XmNleftAttachment, XmATTACH_FORM,
418 XmNrightAttachment, XmATTACH_POSITION,
419 XmNrightPosition, 20,
420 XmNalignment, XmALIGNMENT_END,
424 w = XtVaCreateManagedWidget( "text",
425 xmTextFieldWidgetClass,
427 XmNtopAttachment, XmATTACH_FORM,
428 XmNbottomAttachment, XmATTACH_FORM,
429 XmNrightAttachment, XmATTACH_FORM,
430 XmNleftAttachment, XmATTACH_POSITION,
431 XmNleftPosition, 20,
435 XmTextFieldSetString( w, (char *) options[i].value );
436 XtAddCallback( w, XmNactivateCallback, set_opt, &options[i] );
437 XtManageChild( f );
442 /* draw and display a single page of properties */
444 #if defined(__STDC__)
445 static Widget create_sheet( Widget parent, optSheet *sheet )
446 #else
447 static Widget create_sheet( parent, sheet )
448 Widget parent;
449 optSheet *sheet;
450 #endif
452 Widget outer, inner, frame;
453 Dimension height;
454 XmString str;
456 outer = XtVaCreateWidget( sheet->name,
457 xmFormWidgetClass,
458 parent,
459 XmNtopAttachment, XmATTACH_FORM,
460 XmNrightAttachment, XmATTACH_FORM,
461 XmNbottomAttachment, XmATTACH_FORM,
462 XmNleftAttachment, XmATTACH_FORM,
463 XmNshadowType, XmSHADOW_ETCHED_IN,
464 XmNshadowThickness, 2,
465 XmNverticalSpacing, 4,
466 XmNhorizontalSpacing, 4,
470 /* add descriptive text */
471 frame = XtVaCreateManagedWidget( "frame",
472 xmFrameWidgetClass,
473 outer,
474 XmNtopAttachment, XmATTACH_FORM,
475 XmNrightAttachment, XmATTACH_FORM,
476 XmNleftAttachment, XmATTACH_FORM,
479 str = XmStringCreateLtoR( sheet->description, XmSTRING_DEFAULT_CHARSET );
480 XtVaCreateManagedWidget( "description",
481 xmLabelGadgetClass,
482 frame,
483 XmNlabelString, str,
486 XmStringFree( str );
488 /* Add the toggles. */
489 inner = create_toggles( outer, sheet->toggles );
490 XtVaSetValues( inner,
491 XmNtopAttachment, XmATTACH_WIDGET,
492 XmNtopWidget, frame,
496 /* the string options go here */
497 inner = XtVaCreateWidget( "otherOptions",
498 xmRowColumnWidgetClass,
499 outer,
500 XmNpacking, XmPACK_COLUMN,
501 XmNtopAttachment, XmATTACH_WIDGET,
502 XmNtopWidget, inner,
503 XmNrightAttachment, XmATTACH_FORM,
504 XmNbottomAttachment, XmATTACH_FORM,
505 XmNleftAttachment, XmATTACH_FORM,
509 /* Optionally, the ints. */
510 if ( sheet->ints != NULL )
511 add_string_options( inner, sheet->ints );
513 /* Optionally, the rest. */
514 if ( sheet->others != NULL )
515 add_string_options( inner, sheet->others );
517 XtManageChild( inner );
519 /* finally, force resize of the parent */
520 XtVaGetValues( outer, XmNheight, &height, 0 );
521 XtVaSetValues( parent, XmNheight, height, 0 );
523 return outer;
527 /* change preferences to another sheet */
529 static void change_sheet( parent, current )
530 Widget parent;
531 int current;
533 static int current_sheet = -1;
535 /* create a new one? */
536 if ( sheets[current].holder == NULL )
537 sheets[current].holder = create_sheet( parent, &sheets[current] );
539 /* done with the old one? */
540 if ( current_sheet != -1 && sheets[current_sheet].holder != NULL )
541 XtUnmanageChild( sheets[current_sheet].holder );
543 current_sheet = current;
544 XtManageChild( sheets[current].holder );
545 XtManageChild( parent );
549 /* Draw and display a dialog the describes vi options */
551 #if defined(__STDC__)
552 static Widget create_options_dialog( Widget parent, String title )
553 #else
554 static Widget create_options_dialog( parent, title )
555 Widget parent;
556 String title;
557 #endif
559 Widget box, form, inner;
560 int i;
561 char buffer[1024];
563 /* already built? */
564 if ( preferences != NULL ) return preferences;
566 box = XtVaCreatePopupShell( title,
567 xmDialogShellWidgetClass,
568 parent,
569 XmNtitle, title,
570 XmNallowShellResize, False,
573 XtAddCallback( box, XmNpopdownCallback, __vi_cancel_cb, 0 );
574 XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
575 XtAddEventHandler( box,
576 SubstructureNotifyMask,
577 False,
578 window_unmapped,
579 NULL
582 form = XtVaCreateWidget( "options",
583 xmFormWidgetClass,
584 box,
588 /* copy the pointers to the sheet names */
589 *buffer = '\0';
590 for (i=0; i<XtNumber(sheets); i++) {
591 strcat( buffer, "|" );
592 strcat( buffer, sheets[i].name );
595 inner = __vi_CreateTabbedFolder( "tabs",
596 form,
597 buffer,
598 XtNumber(sheets),
599 change_sheet
602 /* build the property sheets early */
603 for ( i=0; i<XtNumber(sheets); i++ )
604 change_sheet( inner, i );
606 /* manage all of the sheets right now */
607 for ( i=0; i<XtNumber(sheets); i++ )
608 XtManageChild( sheets[i].holder );
609 XtManageChild( form );
611 /* remove all but the first one */
612 for ( i=0; i<XtNumber(sheets); i++ )
613 XtUnmanageChild( sheets[i].holder );
614 change_sheet( inner, 0 ); /* show first sheet first */
616 /* keep this global, we might destroy it later */
617 preferences = form;
619 /* done */
620 return form;
626 * module entry point
628 * __vi_show_options_dialog --
631 * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
633 void
634 __vi_show_options_dialog(parent, title)
635 Widget parent;
636 String title;
638 Widget db = create_options_dialog( parent, title );
639 #if defined(SelfTest)
640 Widget shell = XtParent( db );
641 #endif
643 XtManageChild( db );
645 #if defined(SelfTest)
646 /* wait until it goes away */
647 XtPopup( shell, XtGrabNone );
648 #else
649 /* wait until it goes away */
650 __vi_modal_dialog( db );
651 #endif
656 /* module entry point
657 * Utilities for the search dialog
659 * __vi_toggle --
660 * Returns the current value of a toggle.
662 * PUBLIC: int __vi_toggle __P((char *));
665 __vi_toggle(name)
666 char *name;
668 optData *opt;
670 #undef NSEARCH
671 #define NSEARCH(list) { \
672 for (opt = list; opt->kind != optTerminator; ++opt) \
673 if (!strcmp(opt->name, name)) \
674 return ((int)opt->value); \
676 NSEARCH(display);
677 NSEARCH(files);
678 NSEARCH(general);
679 NSEARCH(input);
680 NSEARCH(search);
682 return (0);
686 * __vi_create_search_toggles --
687 * Creates the search toggles. This is so the options and search widgets
688 * share their appearance.
690 * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
692 Widget
693 __vi_create_search_toggles(parent, list)
694 Widget parent;
695 optData list[];
697 optData *opt;
700 * Copy current options information into the search table.
702 * XXX
703 * This is an O(M*N) loop, but I don't think it matters.
705 for (opt = list; opt->kind != optTerminator; ++opt)
706 opt->value = (void *)__vi_toggle(opt->name);
708 return (create_toggles(parent, list));
712 #if defined(SelfTest)
714 #if defined(__STDC__)
715 static void show_options( Widget w, XtPointer data, XtPointer cbs )
716 #else
717 static void show_options( w, data, cbs )
718 Widget w;
719 XtPointer data;
720 XtPointer cbs;
721 #endif
723 __vi_show_options_dialog( data, "Preferences" );
726 main( int argc, char *argv[] )
728 XtAppContext ctx;
729 Widget top_level, rc, button;
730 extern exit();
732 /* create a top-level shell for the window manager */
733 top_level = XtVaAppInitialize( &ctx,
734 argv[0],
735 NULL, 0, /* options */
736 (ArgcType) &argc,
737 argv, /* might get modified */
738 NULL,
739 NULL
742 rc = XtVaCreateManagedWidget( "rc",
743 xmRowColumnWidgetClass,
744 top_level,
748 button = XtVaCreateManagedWidget( "Pop up options dialog",
749 xmPushButtonGadgetClass,
753 XtAddCallback( button, XmNactivateCallback, show_options, rc );
755 button = XtVaCreateManagedWidget( "Quit",
756 xmPushButtonGadgetClass,
760 XtAddCallback( button, XmNactivateCallback, exit, 0 );
762 XtRealizeWidget(top_level);
763 XtAppMainLoop(ctx);
765 #endif