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.21 2001/06/25 15:19:27 skimo Exp $ (Berkeley) $Date: 2001/06/25 15:19:27 $";
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(void)
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(Widget w
, XtPointer ptr
, XEvent
*ev
, Boolean
*cont
)
219 if ( ev
->type
== UnmapNotify
) {
220 #if defined(SelfTest)
223 XtPopdown( XtParent( preferences
) );
229 * Set an edit option based on a core message.
231 * PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
234 __vi_editopt(IPVI
*ipvi
, const char *str1
, u_int32_t len1
, const char *str2
, u_int32_t len2
, u_int32_t val1
)
239 #define NSEARCH(list) { \
240 for (opt = list; opt->kind != optTerminator; ++opt) \
241 if (!strcmp(opt->name, str1)) \
246 NSEARCH(display_int
);
247 NSEARCH(display_str
);
251 NSEARCH(general_int
);
252 NSEARCH(general_str
);
261 found
: switch (opt
->kind
) {
263 opt
->value
= (void *)val1
;
266 if (opt
->value
!= NULL
)
268 if ((opt
->value
= malloc(8)) != NULL
)
269 (void)snprintf(opt
->value
,
270 8, "%lu", (u_long
)val1
);
274 if (opt
->value
!= NULL
)
276 if ((opt
->value
= malloc(len2
)) != NULL
)
277 memcpy(opt
->value
, str2
, len2
);
287 * Send a set-edit-option message to core.
290 set_opt(Widget w
, XtPointer closure
, XtPointer call_data
)
296 extern IPVI ipvi_motif
;
300 ipb
.code
= VI_EDITOPT
;
301 ipb
.str1
= opt
->name
;
302 ipb
.len1
= strlen(opt
->name
);
306 XtVaGetValues(w
, XmNset
, &set
, 0);
310 vi_wsend(&ipvi_motif
, "ab1", &ipb
);
312 opt
->value
= (void *)!set
;
315 * How do we turn off the button? We don't want to
316 * go recursive where we set it and it calls set_opt
317 * to tell the core. Is that possible?
319 XtVaSetValues(w
, XmNset
, &set
, 0);
323 if (strcmp(opt
->name
, "ruler") == 0)
325 __vi_show_text_ruler_dialog(
326 __vi_screen
->area
, "Ruler");
328 __vi_clear_text_ruler_dialog();
331 str
= XmTextFieldGetString(w
);
332 ipb
.val1
= atoi(str
);
334 vi_send(vi_ofd
, "ab1", &ipb
);
338 ipb
.str2
= XmTextFieldGetString(w
);
339 ipb
.len2
= strlen(ipb
.str2
);
340 vi_send(vi_ofd
, "ab1", &ipb
);
348 /* add toggles to the property sheet */
350 #if defined(__STDC__)
351 static void add_toggle( Widget parent
, optData
*option
)
353 static void add_toggle( parent
, option
)
360 w
= XtVaCreateManagedWidget( option
->name
,
361 xmToggleButtonGadgetClass
,
363 XmNset
, (Boolean
) option
->value
,
366 XtAddCallback( w
, XmNvalueChangedCallback
, set_opt
, option
);
370 static Widget
create_toggles(Widget outer
, optData
*toggles
)
375 inner
= XtVaCreateWidget( "toggleOptions",
376 xmRowColumnWidgetClass
,
378 XmNpacking
, XmPACK_COLUMN
,
380 XmNtopAttachment
, XmATTACH_FORM
,
381 XmNrightAttachment
, XmATTACH_FORM
,
382 XmNleftAttachment
, XmATTACH_FORM
,
386 /* first the booleans */
387 for (i
=0; toggles
[i
].kind
!= optTerminator
; i
++) {
388 add_toggle( inner
, &toggles
[i
] );
390 XtManageChild( inner
);
396 /* draw text fields and their labels */
398 #if defined(__STDC__)
399 static void add_string_options( Widget parent
,
403 static void add_string_options( parent
, options
)
411 for ( i
=0; options
[i
].kind
!= optTerminator
; i
++ ) {
413 f
= XtVaCreateWidget( "form",
419 XtVaCreateManagedWidget( options
[i
].name
,
422 XmNtopAttachment
, XmATTACH_FORM
,
423 XmNbottomAttachment
, XmATTACH_FORM
,
424 XmNleftAttachment
, XmATTACH_FORM
,
425 XmNrightAttachment
, XmATTACH_POSITION
,
426 XmNrightPosition
, 20,
427 XmNalignment
, XmALIGNMENT_END
,
431 w
= XtVaCreateManagedWidget( "text",
432 xmTextFieldWidgetClass
,
434 XmNtopAttachment
, XmATTACH_FORM
,
435 XmNbottomAttachment
, XmATTACH_FORM
,
436 XmNrightAttachment
, XmATTACH_FORM
,
437 XmNleftAttachment
, XmATTACH_POSITION
,
442 XmTextFieldSetString( w
, (char *) options
[i
].value
);
443 XtAddCallback( w
, XmNactivateCallback
, set_opt
, &options
[i
] );
449 /* draw and display a single page of properties */
451 #if defined(__STDC__)
452 static Widget
create_sheet( Widget parent
, optSheet
*sheet
)
454 static Widget
create_sheet( parent
, sheet
)
459 Widget outer
, inner
, frame
;
463 outer
= XtVaCreateWidget( sheet
->name
,
466 XmNtopAttachment
, XmATTACH_FORM
,
467 XmNrightAttachment
, XmATTACH_FORM
,
468 XmNbottomAttachment
, XmATTACH_FORM
,
469 XmNleftAttachment
, XmATTACH_FORM
,
470 XmNshadowType
, XmSHADOW_ETCHED_IN
,
471 XmNshadowThickness
, 2,
472 XmNverticalSpacing
, 4,
473 XmNhorizontalSpacing
, 4,
477 /* add descriptive text */
478 frame
= XtVaCreateManagedWidget( "frame",
481 XmNtopAttachment
, XmATTACH_FORM
,
482 XmNrightAttachment
, XmATTACH_FORM
,
483 XmNleftAttachment
, XmATTACH_FORM
,
486 str
= XmStringCreateLtoR( sheet
->description
, XmSTRING_DEFAULT_CHARSET
);
487 XtVaCreateManagedWidget( "description",
495 /* Add the toggles. */
496 inner
= create_toggles( outer
, sheet
->toggles
);
497 XtVaSetValues( inner
,
498 XmNtopAttachment
, XmATTACH_WIDGET
,
503 /* the string options go here */
504 inner
= XtVaCreateWidget( "otherOptions",
505 xmRowColumnWidgetClass
,
507 XmNpacking
, XmPACK_COLUMN
,
508 XmNtopAttachment
, XmATTACH_WIDGET
,
510 XmNrightAttachment
, XmATTACH_FORM
,
511 XmNbottomAttachment
, XmATTACH_FORM
,
512 XmNleftAttachment
, XmATTACH_FORM
,
516 /* Optionally, the ints. */
517 if ( sheet
->ints
!= NULL
)
518 add_string_options( inner
, sheet
->ints
);
520 /* Optionally, the rest. */
521 if ( sheet
->others
!= NULL
)
522 add_string_options( inner
, sheet
->others
);
524 XtManageChild( inner
);
526 /* finally, force resize of the parent */
527 XtVaGetValues( outer
, XmNheight
, &height
, 0 );
528 XtVaSetValues( parent
, XmNheight
, height
, 0 );
534 /* change preferences to another sheet */
536 static void change_sheet(Widget parent
, int current
)
538 static int current_sheet
= -1;
540 /* create a new one? */
541 if ( sheets
[current
].holder
== NULL
)
542 sheets
[current
].holder
= create_sheet( parent
, &sheets
[current
] );
544 /* done with the old one? */
545 if ( current_sheet
!= -1 && sheets
[current_sheet
].holder
!= NULL
)
546 XtUnmanageChild( sheets
[current_sheet
].holder
);
548 current_sheet
= current
;
549 XtManageChild( sheets
[current
].holder
);
550 XtManageChild( parent
);
554 /* Draw and display a dialog the describes vi options */
556 #if defined(__STDC__)
557 static Widget
create_options_dialog( Widget parent
, String title
)
559 static Widget
create_options_dialog( parent
, title
)
564 Widget box
, form
, inner
;
569 if ( preferences
!= NULL
) return preferences
;
571 box
= XtVaCreatePopupShell( title
,
572 xmDialogShellWidgetClass
,
575 XmNallowShellResize
, False
,
578 XtAddCallback( box
, XmNpopdownCallback
, __vi_cancel_cb
, 0 );
579 XtAddCallback( box
, XmNdestroyCallback
, destroyed
, 0 );
580 XtAddEventHandler( box
,
581 SubstructureNotifyMask
,
587 form
= XtVaCreateWidget( "options",
593 /* copy the pointers to the sheet names */
595 for (i
=0; i
<XtNumber(sheets
); i
++) {
596 strcat( buffer
, "|" );
597 strcat( buffer
, sheets
[i
].name
);
600 inner
= __vi_CreateTabbedFolder( "tabs",
607 /* build the property sheets early */
608 for ( i
=0; i
<XtNumber(sheets
); i
++ )
609 change_sheet( inner
, i
);
611 /* manage all of the sheets right now */
612 for ( i
=0; i
<XtNumber(sheets
); i
++ )
613 XtManageChild( sheets
[i
].holder
);
614 XtManageChild( form
);
616 /* remove all but the first one */
617 for ( i
=0; i
<XtNumber(sheets
); i
++ )
618 XtUnmanageChild( sheets
[i
].holder
);
619 change_sheet( inner
, 0 ); /* show first sheet first */
621 /* keep this global, we might destroy it later */
633 * __vi_show_options_dialog --
636 * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
639 __vi_show_options_dialog(Widget parent
, String title
)
641 Widget db
= create_options_dialog( parent
, title
);
642 #if defined(SelfTest)
643 Widget shell
= XtParent( db
);
648 #if defined(SelfTest)
649 /* wait until it goes away */
650 XtPopup( shell
, XtGrabNone
);
652 /* wait until it goes away */
653 __vi_modal_dialog( db
);
659 /* module entry point
660 * Utilities for the search dialog
663 * Returns the current value of a toggle.
665 * PUBLIC: int __vi_toggle __P((char *));
668 __vi_toggle(char *name
)
673 #define NSEARCH(list) { \
674 for (opt = list; opt->kind != optTerminator; ++opt) \
675 if (!strcmp(opt->name, name)) \
676 return ((int)opt->value); \
688 * __vi_create_search_toggles --
689 * Creates the search toggles. This is so the options and search widgets
690 * share their appearance.
692 * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
695 __vi_create_search_toggles(Widget parent
, optData
*list
)
700 * Copy current options information into the search table.
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
)
717 static void show_options( w
, data
, cbs
)
723 __vi_show_options_dialog( data
, "Preferences" );
726 main( int argc
, char *argv
[] )
729 Widget top_level
, rc
, button
;
732 /* create a top-level shell for the window manager */
733 top_level
= XtVaAppInitialize( &ctx
,
735 NULL
, 0, /* options */
737 argv
, /* might get modified */
742 rc
= XtVaCreateManagedWidget( "rc",
743 xmRowColumnWidgetClass
,
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
);