5 * Rob Zimmermann. All rights reserved.
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
15 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";
18 #include <sys/types.h>
19 #include <sys/queue.h>
22 #include <X11/Intrinsic.h>
23 #include <Xm/DialogS.h>
26 #include <Xm/LabelG.h>
27 #include <Xm/PushBG.h>
29 #include <Xm/ToggleBG.h>
30 #include <Xm/RowColumn.h>
32 #include <bitstring.h>
38 #include "../common/common.h"
39 #include "../ipc/ip.h"
44 static void set_opt
__P((Widget
, XtPointer
, XtPointer
));
51 /* in production, get these from the resource list */
53 #define toggleColumns 6
62 static Widget preferences
= NULL
;
64 static optData display
[] = {
65 { optToggle
, "comment", },
66 { optToggle
, "flash", },
67 { optToggle
, "leftright", },
68 { optToggle
, "list", },
69 { optToggle
, "number", },
70 { optToggle
, "octal", },
71 { optToggle
, "ruler", },
72 { optToggle
, "showmode", },
73 { optToggle
, "slowopen", },
74 { optToggle
, "verbose", },
75 { optToggle
, "windowname", },
78 { optInteger
, "report", },
79 { optInteger
, "scroll", },
80 { optInteger
, "shiftwidth", },
81 { optInteger
, "sidescroll", },
82 { optInteger
, "tabstop", },
83 { optInteger
, "window", },
86 { optString
, "noprint", },
87 { optString
, "print", },
90 { optToggle
, "autowrite", },
91 { optToggle
, "lock", },
92 { optToggle
, "readonly", },
93 { optToggle
, "writeany", },
96 { optString
, "backup", },
97 { optString
, "path", },
100 { optToggle
, "exrc", },
101 { optToggle
, "lisp", },
102 { optToggle
, "modeline", },
103 { optToggle
, "sourceany", },
104 { optToggle
, "tildeop", },
107 { optInteger
, "taglength", },
110 { optString
, "cdpath", },
111 { optString
, "directory", },
112 { optString
, "msgcat", },
113 { optString
, "recdir", },
114 { optString
, "shell", },
115 { optString
, "shellmeta", },
116 { optString
, "tags", },
119 { optToggle
, "altwerase", },
120 { optToggle
, "autoindent", },
121 { optToggle
, "remap", },
122 { optToggle
, "showmatch", },
123 { optToggle
, "ttywerase", },
126 { optInteger
, "escapetime", },
127 { optInteger
, "keytime", },
128 { optInteger
, "matchtime", },
129 { optInteger
, "timeout", },
130 { optInteger
, "wraplen", },
131 { optInteger
, "wrapmargin", },
134 { optString
, "cedit", },
135 { optString
, "filec", },
138 { optToggle
, "extended", },
139 { optToggle
, "iclower", },
140 { optToggle
, "ignorecase", },
141 { optToggle
, "magic", },
142 { optToggle
, "searchincr", },
143 { optToggle
, "wrapscan", },
146 { optString
, "paragraphs", },
147 { optString
, "sections", },
151 /* ********* NOTE ***********
152 * Sheet 0 will always be shown first. It does not matter to the Xt code
153 * which sheet that is, so it ought to be the one users interact with most.
154 * Best guess is that's general editor options, but it might be Search/re.
155 * ********* NOTE ***********
157 static optSheet sheets
[] = {
159 "These options control how text is displayed on the screen",
166 "These options control how the editor handles files",
173 "These options control text input behavior",
180 "These options control searching and Regular Expression behavior",
187 "These options control general editor configuration",
198 #if defined(SelfTest)
199 void __vi_cancel_cb()
206 static void destroyed(void)
212 /* some window managers destroy us upon popdown */
213 for (i
=0; i
<XtNumber(sheets
); i
++) {
214 sheets
[i
].holder
= NULL
;
220 static void window_unmapped(Widget w
, XtPointer ptr
, XEvent
*ev
, Boolean
*cont
)
222 if ( ev
->type
== UnmapNotify
) {
223 #if defined(SelfTest)
226 XtPopdown( XtParent( preferences
) );
232 * Set an edit option based on a core message.
234 * PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
237 __vi_editopt(IPVI
*ipvi
, const char *str1
, u_int32_t len1
, const char *str2
, u_int32_t len2
, u_int32_t val1
)
242 #define NSEARCH(list) { \
243 for (opt = list; opt->kind != optTerminator; ++opt) \
244 if (!strcmp(opt->name, str1)) \
249 NSEARCH(display_int
);
250 NSEARCH(display_str
);
254 NSEARCH(general_int
);
255 NSEARCH(general_str
);
264 found
: switch (opt
->kind
) {
266 opt
->value
= (void *)val1
;
269 if (opt
->value
!= NULL
)
271 if ((opt
->value
= malloc(8)) != NULL
)
272 (void)snprintf(opt
->value
,
273 8, "%lu", (u_long
)val1
);
277 if (opt
->value
!= NULL
)
279 if ((opt
->value
= malloc(len2
)) != NULL
)
280 memcpy(opt
->value
, str2
, len2
);
290 * Send a set-edit-option message to core.
293 set_opt(Widget w
, XtPointer closure
, XtPointer call_data
)
299 extern IPVI ipvi_motif
;
303 ipb
.code
= VI_EDITOPT
;
304 ipb
.str1
= opt
->name
;
305 ipb
.len1
= strlen(opt
->name
);
309 XtVaGetValues(w
, XmNset
, &set
, 0);
313 vi_wsend(&ipvi_motif
, "ab1", &ipb
);
315 opt
->value
= (void *)!set
;
318 * How do we turn off the button? We don't want to
319 * go recursive where we set it and it calls set_opt
320 * to tell the core. Is that possible?
322 XtVaSetValues(w
, XmNset
, &set
, 0);
326 if (strcmp(opt
->name
, "ruler") == 0)
328 __vi_show_text_ruler_dialog(
329 __vi_screen
->area
, "Ruler");
331 __vi_clear_text_ruler_dialog();
334 str
= XmTextFieldGetString(w
);
335 ipb
.val1
= atoi(str
);
337 vi_send(vi_ofd
, "ab1", &ipb
);
341 ipb
.str2
= XmTextFieldGetString(w
);
342 ipb
.len2
= strlen(ipb
.str2
);
343 vi_send(vi_ofd
, "ab1", &ipb
);
351 /* add toggles to the property sheet */
353 #if defined(__STDC__)
354 static void add_toggle( Widget parent
, optData
*option
)
356 static void add_toggle( parent
, option
)
363 w
= XtVaCreateManagedWidget( option
->name
,
364 xmToggleButtonGadgetClass
,
366 XmNset
, (Boolean
) option
->value
,
369 XtAddCallback( w
, XmNvalueChangedCallback
, set_opt
, option
);
373 static Widget
create_toggles(Widget outer
, optData
*toggles
)
378 inner
= XtVaCreateWidget( "toggleOptions",
379 xmRowColumnWidgetClass
,
381 XmNpacking
, XmPACK_COLUMN
,
383 XmNtopAttachment
, XmATTACH_FORM
,
384 XmNrightAttachment
, XmATTACH_FORM
,
385 XmNleftAttachment
, XmATTACH_FORM
,
389 /* first the booleans */
390 for (i
=0; toggles
[i
].kind
!= optTerminator
; i
++) {
391 add_toggle( inner
, &toggles
[i
] );
393 XtManageChild( inner
);
399 /* draw text fields and their labels */
401 #if defined(__STDC__)
402 static void add_string_options( Widget parent
,
406 static void add_string_options( parent
, options
)
414 for ( i
=0; options
[i
].kind
!= optTerminator
; i
++ ) {
416 f
= XtVaCreateWidget( "form",
422 XtVaCreateManagedWidget( options
[i
].name
,
425 XmNtopAttachment
, XmATTACH_FORM
,
426 XmNbottomAttachment
, XmATTACH_FORM
,
427 XmNleftAttachment
, XmATTACH_FORM
,
428 XmNrightAttachment
, XmATTACH_POSITION
,
429 XmNrightPosition
, 20,
430 XmNalignment
, XmALIGNMENT_END
,
434 w
= XtVaCreateManagedWidget( "text",
435 xmTextFieldWidgetClass
,
437 XmNtopAttachment
, XmATTACH_FORM
,
438 XmNbottomAttachment
, XmATTACH_FORM
,
439 XmNrightAttachment
, XmATTACH_FORM
,
440 XmNleftAttachment
, XmATTACH_POSITION
,
445 XmTextFieldSetString( w
, (char *) options
[i
].value
);
446 XtAddCallback( w
, XmNactivateCallback
, set_opt
, &options
[i
] );
452 /* draw and display a single page of properties */
454 #if defined(__STDC__)
455 static Widget
create_sheet( Widget parent
, optSheet
*sheet
)
457 static Widget
create_sheet( parent
, sheet
)
462 Widget outer
, inner
, frame
;
466 outer
= XtVaCreateWidget( sheet
->name
,
469 XmNtopAttachment
, XmATTACH_FORM
,
470 XmNrightAttachment
, XmATTACH_FORM
,
471 XmNbottomAttachment
, XmATTACH_FORM
,
472 XmNleftAttachment
, XmATTACH_FORM
,
473 XmNshadowType
, XmSHADOW_ETCHED_IN
,
474 XmNshadowThickness
, 2,
475 XmNverticalSpacing
, 4,
476 XmNhorizontalSpacing
, 4,
480 /* add descriptive text */
481 frame
= XtVaCreateManagedWidget( "frame",
484 XmNtopAttachment
, XmATTACH_FORM
,
485 XmNrightAttachment
, XmATTACH_FORM
,
486 XmNleftAttachment
, XmATTACH_FORM
,
489 str
= XmStringCreateLtoR( sheet
->description
, XmSTRING_DEFAULT_CHARSET
);
490 XtVaCreateManagedWidget( "description",
498 /* Add the toggles. */
499 inner
= create_toggles( outer
, sheet
->toggles
);
500 XtVaSetValues( inner
,
501 XmNtopAttachment
, XmATTACH_WIDGET
,
506 /* the string options go here */
507 inner
= XtVaCreateWidget( "otherOptions",
508 xmRowColumnWidgetClass
,
510 XmNpacking
, XmPACK_COLUMN
,
511 XmNtopAttachment
, XmATTACH_WIDGET
,
513 XmNrightAttachment
, XmATTACH_FORM
,
514 XmNbottomAttachment
, XmATTACH_FORM
,
515 XmNleftAttachment
, XmATTACH_FORM
,
519 /* Optionally, the ints. */
520 if ( sheet
->ints
!= NULL
)
521 add_string_options( inner
, sheet
->ints
);
523 /* Optionally, the rest. */
524 if ( sheet
->others
!= NULL
)
525 add_string_options( inner
, sheet
->others
);
527 XtManageChild( inner
);
529 /* finally, force resize of the parent */
530 XtVaGetValues( outer
, XmNheight
, &height
, 0 );
531 XtVaSetValues( parent
, XmNheight
, height
, 0 );
537 /* change preferences to another sheet */
539 static void change_sheet(Widget parent
, int current
)
541 static int current_sheet
= -1;
543 /* create a new one? */
544 if ( sheets
[current
].holder
== NULL
)
545 sheets
[current
].holder
= create_sheet( parent
, &sheets
[current
] );
547 /* done with the old one? */
548 if ( current_sheet
!= -1 && sheets
[current_sheet
].holder
!= NULL
)
549 XtUnmanageChild( sheets
[current_sheet
].holder
);
551 current_sheet
= current
;
552 XtManageChild( sheets
[current
].holder
);
553 XtManageChild( parent
);
557 /* Draw and display a dialog the describes vi options */
559 #if defined(__STDC__)
560 static Widget
create_options_dialog( Widget parent
, String title
)
562 static Widget
create_options_dialog( parent
, title
)
567 Widget box
, form
, inner
;
572 if ( preferences
!= NULL
) return preferences
;
574 box
= XtVaCreatePopupShell( title
,
575 xmDialogShellWidgetClass
,
578 XmNallowShellResize
, False
,
581 XtAddCallback( box
, XmNpopdownCallback
, __vi_cancel_cb
, 0 );
582 XtAddCallback( box
, XmNdestroyCallback
, destroyed
, 0 );
583 XtAddEventHandler( box
,
584 SubstructureNotifyMask
,
590 form
= XtVaCreateWidget( "options",
596 /* copy the pointers to the sheet names */
598 for (i
=0; i
<XtNumber(sheets
); i
++) {
599 strcat( buffer
, "|" );
600 strcat( buffer
, sheets
[i
].name
);
603 inner
= __vi_CreateTabbedFolder( "tabs",
610 /* build the property sheets early */
611 for ( i
=0; i
<XtNumber(sheets
); i
++ )
612 change_sheet( inner
, i
);
614 /* manage all of the sheets right now */
615 for ( i
=0; i
<XtNumber(sheets
); i
++ )
616 XtManageChild( sheets
[i
].holder
);
617 XtManageChild( form
);
619 /* remove all but the first one */
620 for ( i
=0; i
<XtNumber(sheets
); i
++ )
621 XtUnmanageChild( sheets
[i
].holder
);
622 change_sheet( inner
, 0 ); /* show first sheet first */
624 /* keep this global, we might destroy it later */
636 * __vi_show_options_dialog --
639 * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
642 __vi_show_options_dialog(Widget parent
, String title
)
644 Widget db
= create_options_dialog( parent
, title
);
645 #if defined(SelfTest)
646 Widget shell
= XtParent( db
);
651 #if defined(SelfTest)
652 /* wait until it goes away */
653 XtPopup( shell
, XtGrabNone
);
655 /* wait until it goes away */
656 __vi_modal_dialog( db
);
662 /* module entry point
663 * Utilities for the search dialog
666 * Returns the current value of a toggle.
668 * PUBLIC: int __vi_toggle __P((char *));
671 __vi_toggle(char *name
)
676 #define NSEARCH(list) { \
677 for (opt = list; opt->kind != optTerminator; ++opt) \
678 if (!strcmp(opt->name, name)) \
679 return ((int)opt->value); \
691 * __vi_create_search_toggles --
692 * Creates the search toggles. This is so the options and search widgets
693 * share their appearance.
695 * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
698 __vi_create_search_toggles(Widget parent
, optData
*list
)
703 * Copy current options information into the search table.
706 * This is an O(M*N) loop, but I don't think it matters.
708 for (opt
= list
; opt
->kind
!= optTerminator
; ++opt
)
709 opt
->value
= (void *)__vi_toggle(opt
->name
);
711 return (create_toggles(parent
, list
));
715 #if defined(SelfTest)
717 #if defined(__STDC__)
718 static void show_options( Widget w
, XtPointer data
, XtPointer cbs
)
720 static void show_options( w
, data
, cbs
)
726 __vi_show_options_dialog( data
, "Preferences" );
729 main( int argc
, char *argv
[] )
732 Widget top_level
, rc
, button
;
735 /* create a top-level shell for the window manager */
736 top_level
= XtVaAppInitialize( &ctx
,
738 NULL
, 0, /* options */
740 argv
, /* might get modified */
745 rc
= XtVaCreateManagedWidget( "rc",
746 xmRowColumnWidgetClass
,
751 button
= XtVaCreateManagedWidget( "Pop up options dialog",
752 xmPushButtonGadgetClass
,
756 XtAddCallback( button
, XmNactivateCallback
, show_options
, rc
);
758 button
= XtVaCreateManagedWidget( "Quit",
759 xmPushButtonGadgetClass
,
763 XtAddCallback( button
, XmNactivateCallback
, exit
, 0 );
765 XtRealizeWidget(top_level
);