3 * Rob Zimmermann. All rights reserved.
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
13 static const char sccsid
[] = "$Id: m_options.c,v 8.20 2000/07/05 11:33:19 skimo Exp $ (Berkeley) $Date: 2000/07/05 11:33:19 $";
16 #include <sys/types.h>
17 #include <sys/queue.h>
20 #include <X11/Intrinsic.h>
21 #include <Xm/DialogS.h>
24 #include <Xm/LabelG.h>
25 #include <Xm/PushBG.h>
27 #include <Xm/ToggleBG.h>
28 #include <Xm/RowColumn.h>
30 #include <bitstring.h>
35 #include "../common/common.h"
36 #include "../ipc/ip.h"
41 static void set_opt
__P((Widget
, XtPointer
, XtPointer
));
48 /* in production, get these from the resource list */
50 #define toggleColumns 6
59 static Widget preferences
= NULL
;
61 static optData display
[] = {
62 { optToggle
, "comment", },
63 { optToggle
, "flash", },
64 { optToggle
, "leftright", },
65 { optToggle
, "list", },
66 { optToggle
, "number", },
67 { optToggle
, "octal", },
68 { optToggle
, "ruler", },
69 { optToggle
, "showmode", },
70 { optToggle
, "slowopen", },
71 { optToggle
, "verbose", },
72 { optToggle
, "windowname", },
75 { optInteger
, "report", },
76 { optInteger
, "scroll", },
77 { optInteger
, "shiftwidth", },
78 { optInteger
, "sidescroll", },
79 { optInteger
, "tabstop", },
80 { optInteger
, "window", },
83 { optString
, "noprint", },
84 { optString
, "print", },
87 { optToggle
, "autowrite", },
88 { optToggle
, "lock", },
89 { optToggle
, "readonly", },
90 { optToggle
, "writeany", },
93 { optString
, "backup", },
94 { optString
, "path", },
97 { optToggle
, "exrc", },
98 { optToggle
, "lisp", },
99 { optToggle
, "modeline", },
100 { optToggle
, "sourceany", },
101 { optToggle
, "tildeop", },
104 { optInteger
, "taglength", },
107 { optString
, "cdpath", },
108 { optString
, "directory", },
109 { optString
, "msgcat", },
110 { optString
, "recdir", },
111 { optString
, "shell", },
112 { optString
, "shellmeta", },
113 { optString
, "tags", },
116 { optToggle
, "altwerase", },
117 { optToggle
, "autoindent", },
118 { optToggle
, "remap", },
119 { optToggle
, "showmatch", },
120 { optToggle
, "ttywerase", },
123 { optInteger
, "escapetime", },
124 { optInteger
, "keytime", },
125 { optInteger
, "matchtime", },
126 { optInteger
, "timeout", },
127 { optInteger
, "wraplen", },
128 { optInteger
, "wrapmargin", },
131 { optString
, "cedit", },
132 { optString
, "filec", },
135 { optToggle
, "extended", },
136 { optToggle
, "iclower", },
137 { optToggle
, "ignorecase", },
138 { optToggle
, "magic", },
139 { optToggle
, "searchincr", },
140 { optToggle
, "wrapscan", },
143 { optString
, "paragraphs", },
144 { optString
, "sections", },
148 /* ********* NOTE ***********
149 * Sheet 0 will always be shown first. It does not matter to the Xt code
150 * which sheet that is, so it ought to be the one users interact with most.
151 * Best guess is that's general editor options, but it might be Search/re.
152 * ********* NOTE ***********
154 static optSheet sheets
[] = {
156 "These options control how text is displayed on the screen",
163 "These options control how the editor handles files",
170 "These options control text input behavior",
177 "These options control searching and Regular Expression behavior",
184 "These options control general editor configuration",
195 #if defined(SelfTest)
196 void __vi_cancel_cb()
203 static void destroyed()
209 /* some window managers destroy us upon popdown */
210 for (i
=0; i
<XtNumber(sheets
); i
++) {
211 sheets
[i
].holder
= NULL
;
217 static void window_unmapped( w
, ptr
, ev
, cont
)
223 if ( ev
->type
== UnmapNotify
) {
224 #if defined(SelfTest)
227 XtPopdown( XtParent( preferences
) );
233 * Set an edit option based on a core message.
235 * PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
238 __vi_editopt(ipvi
, str1
, len1
, str2
, len2
, val1
)
249 #define NSEARCH(list) { \
250 for (opt = list; opt->kind != optTerminator; ++opt) \
251 if (!strcmp(opt->name, str1)) \
256 NSEARCH(display_int
);
257 NSEARCH(display_str
);
261 NSEARCH(general_int
);
262 NSEARCH(general_str
);
271 found
: switch (opt
->kind
) {
273 opt
->value
= (void *)val1
;
276 if (opt
->value
!= NULL
)
278 if ((opt
->value
= malloc(8)) != NULL
)
279 (void)snprintf(opt
->value
,
280 8, "%lu", (u_long
)val1
);
284 if (opt
->value
!= NULL
)
286 if ((opt
->value
= malloc(len2
)) != NULL
)
287 memcpy(opt
->value
, str2
, len2
);
297 * Send a set-edit-option message to core.
300 set_opt(w
, closure
, call_data
)
302 XtPointer closure
, call_data
;
308 extern IPVI ipvi_motif
;
312 ipb
.code
= VI_EDITOPT
;
313 ipb
.str1
= opt
->name
;
314 ipb
.len1
= strlen(opt
->name
);
318 XtVaGetValues(w
, XmNset
, &set
, 0);
322 vi_wsend(&ipvi_motif
, "ab1", &ipb
);
324 opt
->value
= (void *)!set
;
327 * How do we turn off the button? We don't want to
328 * go recursive where we set it and it calls set_opt
329 * to tell the core. Is that possible?
331 XtVaSetValues(w
, XmNset
, &set
, 0);
335 if (strcmp(opt
->name
, "ruler") == 0)
337 __vi_show_text_ruler_dialog(
338 __vi_screen
->area
, "Ruler");
340 __vi_clear_text_ruler_dialog();
343 str
= XmTextFieldGetString(w
);
344 ipb
.val1
= atoi(str
);
346 vi_send(vi_ofd
, "ab1", &ipb
);
350 ipb
.str2
= XmTextFieldGetString(w
);
351 ipb
.len2
= strlen(ipb
.str2
);
352 vi_send(vi_ofd
, "ab1", &ipb
);
360 /* add toggles to the property sheet */
362 #if defined(__STDC__)
363 static void add_toggle( Widget parent
, optData
*option
)
365 static void add_toggle( parent
, option
)
372 w
= XtVaCreateManagedWidget( option
->name
,
373 xmToggleButtonGadgetClass
,
375 XmNset
, (Boolean
) option
->value
,
378 XtAddCallback( w
, XmNvalueChangedCallback
, set_opt
, option
);
382 static Widget
create_toggles( outer
, toggles
)
389 inner
= XtVaCreateWidget( "toggleOptions",
390 xmRowColumnWidgetClass
,
392 XmNpacking
, XmPACK_COLUMN
,
394 XmNtopAttachment
, XmATTACH_FORM
,
395 XmNrightAttachment
, XmATTACH_FORM
,
396 XmNleftAttachment
, XmATTACH_FORM
,
400 /* first the booleans */
401 for (i
=0; toggles
[i
].kind
!= optTerminator
; i
++) {
402 add_toggle( inner
, &toggles
[i
] );
404 XtManageChild( inner
);
410 /* draw text fields and their labels */
412 #if defined(__STDC__)
413 static void add_string_options( Widget parent
,
417 static void add_string_options( parent
, options
)
425 for ( i
=0; options
[i
].kind
!= optTerminator
; i
++ ) {
427 f
= XtVaCreateWidget( "form",
433 XtVaCreateManagedWidget( options
[i
].name
,
436 XmNtopAttachment
, XmATTACH_FORM
,
437 XmNbottomAttachment
, XmATTACH_FORM
,
438 XmNleftAttachment
, XmATTACH_FORM
,
439 XmNrightAttachment
, XmATTACH_POSITION
,
440 XmNrightPosition
, 20,
441 XmNalignment
, XmALIGNMENT_END
,
445 w
= XtVaCreateManagedWidget( "text",
446 xmTextFieldWidgetClass
,
448 XmNtopAttachment
, XmATTACH_FORM
,
449 XmNbottomAttachment
, XmATTACH_FORM
,
450 XmNrightAttachment
, XmATTACH_FORM
,
451 XmNleftAttachment
, XmATTACH_POSITION
,
456 XmTextFieldSetString( w
, (char *) options
[i
].value
);
457 XtAddCallback( w
, XmNactivateCallback
, set_opt
, &options
[i
] );
463 /* draw and display a single page of properties */
465 #if defined(__STDC__)
466 static Widget
create_sheet( Widget parent
, optSheet
*sheet
)
468 static Widget
create_sheet( parent
, sheet
)
473 Widget outer
, inner
, frame
;
477 outer
= XtVaCreateWidget( sheet
->name
,
480 XmNtopAttachment
, XmATTACH_FORM
,
481 XmNrightAttachment
, XmATTACH_FORM
,
482 XmNbottomAttachment
, XmATTACH_FORM
,
483 XmNleftAttachment
, XmATTACH_FORM
,
484 XmNshadowType
, XmSHADOW_ETCHED_IN
,
485 XmNshadowThickness
, 2,
486 XmNverticalSpacing
, 4,
487 XmNhorizontalSpacing
, 4,
491 /* add descriptive text */
492 frame
= XtVaCreateManagedWidget( "frame",
495 XmNtopAttachment
, XmATTACH_FORM
,
496 XmNrightAttachment
, XmATTACH_FORM
,
497 XmNleftAttachment
, XmATTACH_FORM
,
500 str
= XmStringCreateLtoR( sheet
->description
, XmSTRING_DEFAULT_CHARSET
);
501 XtVaCreateManagedWidget( "description",
509 /* Add the toggles. */
510 inner
= create_toggles( outer
, sheet
->toggles
);
511 XtVaSetValues( inner
,
512 XmNtopAttachment
, XmATTACH_WIDGET
,
517 /* the string options go here */
518 inner
= XtVaCreateWidget( "otherOptions",
519 xmRowColumnWidgetClass
,
521 XmNpacking
, XmPACK_COLUMN
,
522 XmNtopAttachment
, XmATTACH_WIDGET
,
524 XmNrightAttachment
, XmATTACH_FORM
,
525 XmNbottomAttachment
, XmATTACH_FORM
,
526 XmNleftAttachment
, XmATTACH_FORM
,
530 /* Optionally, the ints. */
531 if ( sheet
->ints
!= NULL
)
532 add_string_options( inner
, sheet
->ints
);
534 /* Optionally, the rest. */
535 if ( sheet
->others
!= NULL
)
536 add_string_options( inner
, sheet
->others
);
538 XtManageChild( inner
);
540 /* finally, force resize of the parent */
541 XtVaGetValues( outer
, XmNheight
, &height
, 0 );
542 XtVaSetValues( parent
, XmNheight
, height
, 0 );
548 /* change preferences to another sheet */
550 static void change_sheet( parent
, current
)
554 static int current_sheet
= -1;
556 /* create a new one? */
557 if ( sheets
[current
].holder
== NULL
)
558 sheets
[current
].holder
= create_sheet( parent
, &sheets
[current
] );
560 /* done with the old one? */
561 if ( current_sheet
!= -1 && sheets
[current_sheet
].holder
!= NULL
)
562 XtUnmanageChild( sheets
[current_sheet
].holder
);
564 current_sheet
= current
;
565 XtManageChild( sheets
[current
].holder
);
566 XtManageChild( parent
);
570 /* Draw and display a dialog the describes vi options */
572 #if defined(__STDC__)
573 static Widget
create_options_dialog( Widget parent
, String title
)
575 static Widget
create_options_dialog( parent
, title
)
580 Widget box
, form
, inner
;
585 if ( preferences
!= NULL
) return preferences
;
587 box
= XtVaCreatePopupShell( title
,
588 xmDialogShellWidgetClass
,
591 XmNallowShellResize
, False
,
594 XtAddCallback( box
, XmNpopdownCallback
, __vi_cancel_cb
, 0 );
595 XtAddCallback( box
, XmNdestroyCallback
, destroyed
, 0 );
596 XtAddEventHandler( box
,
597 SubstructureNotifyMask
,
603 form
= XtVaCreateWidget( "options",
609 /* copy the pointers to the sheet names */
611 for (i
=0; i
<XtNumber(sheets
); i
++) {
612 strcat( buffer
, "|" );
613 strcat( buffer
, sheets
[i
].name
);
616 inner
= __vi_CreateTabbedFolder( "tabs",
623 /* build the property sheets early */
624 for ( i
=0; i
<XtNumber(sheets
); i
++ )
625 change_sheet( inner
, i
);
627 /* manage all of the sheets right now */
628 for ( i
=0; i
<XtNumber(sheets
); i
++ )
629 XtManageChild( sheets
[i
].holder
);
630 XtManageChild( form
);
632 /* remove all but the first one */
633 for ( i
=0; i
<XtNumber(sheets
); i
++ )
634 XtUnmanageChild( sheets
[i
].holder
);
635 change_sheet( inner
, 0 ); /* show first sheet first */
637 /* keep this global, we might destroy it later */
649 * __vi_show_options_dialog --
652 * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
655 __vi_show_options_dialog(parent
, title
)
659 Widget db
= create_options_dialog( parent
, title
);
660 #if defined(SelfTest)
661 Widget shell
= XtParent( db
);
666 #if defined(SelfTest)
667 /* wait until it goes away */
668 XtPopup( shell
, XtGrabNone
);
670 /* wait until it goes away */
671 __vi_modal_dialog( db
);
677 /* module entry point
678 * Utilities for the search dialog
681 * Returns the current value of a toggle.
683 * PUBLIC: int __vi_toggle __P((char *));
692 #define NSEARCH(list) { \
693 for (opt = list; opt->kind != optTerminator; ++opt) \
694 if (!strcmp(opt->name, name)) \
695 return ((int)opt->value); \
707 * __vi_create_search_toggles --
708 * Creates the search toggles. This is so the options and search widgets
709 * share their appearance.
711 * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
714 __vi_create_search_toggles(parent
, list
)
721 * Copy current options information into the search table.
724 * This is an O(M*N) loop, but I don't think it matters.
726 for (opt
= list
; opt
->kind
!= optTerminator
; ++opt
)
727 opt
->value
= (void *)__vi_toggle(opt
->name
);
729 return (create_toggles(parent
, list
));
733 #if defined(SelfTest)
735 #if defined(__STDC__)
736 static void show_options( Widget w
, XtPointer data
, XtPointer cbs
)
738 static void show_options( w
, data
, cbs
)
744 __vi_show_options_dialog( data
, "Preferences" );
747 main( int argc
, char *argv
[] )
750 Widget top_level
, rc
, button
;
753 /* create a top-level shell for the window manager */
754 top_level
= XtVaAppInitialize( &ctx
,
756 NULL
, 0, /* options */
758 argv
, /* might get modified */
763 rc
= XtVaCreateManagedWidget( "rc",
764 xmRowColumnWidgetClass
,
769 button
= XtVaCreateManagedWidget( "Pop up options dialog",
770 xmPushButtonGadgetClass
,
774 XtAddCallback( button
, XmNactivateCallback
, show_options
, rc
);
776 button
= XtVaCreateManagedWidget( "Quit",
777 xmPushButtonGadgetClass
,
781 XtAddCallback( button
, XmNactivateCallback
, exit
, 0 );
783 XtRealizeWidget(top_level
);