minix/dist/nvi/motif_l/m_options.c

769 lines
16 KiB
C
Raw Normal View History

/* $NetBSD: m_options.c,v 1.1.1.2 2008/05/18 14:31:27 aymeric Exp $ */
/*-
* Copyright (c) 1996
* Rob Zimmermann. All rights reserved.
* Copyright (c) 1996
* Keith Bostic. All rights reserved.
*
* See the LICENSE file for redistribution information.
*/
#include "config.h"
#ifndef lint
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";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
#include <X11/X.h>
#include <X11/Intrinsic.h>
#include <Xm/DialogS.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/LabelG.h>
#include <Xm/PushBG.h>
#include <Xm/TextF.h>
#include <Xm/ToggleBG.h>
#include <Xm/RowColumn.h>
#include <bitstring.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#undef LOCK_SUCCESS
#include "../common/common.h"
#include "../ipc/ip.h"
#include "m_motif.h"
extern int vi_ofd;
static void set_opt __P((Widget, XtPointer, XtPointer));
/* constants */
#if defined(SelfTest)
/* in production, get these from the resource list */
#define toggleColumns 6
#endif
/*
* global data
*/
static Widget preferences = NULL;
static optData display[] = {
{ optToggle, "comment", },
{ optToggle, "flash", },
{ optToggle, "leftright", },
{ optToggle, "list", },
{ optToggle, "number", },
{ optToggle, "octal", },
{ optToggle, "ruler", },
{ optToggle, "showmode", },
{ optToggle, "slowopen", },
{ optToggle, "verbose", },
{ optToggle, "windowname", },
{ optTerminator, },
}, display_int[] = {
{ optInteger, "report", },
{ optInteger, "scroll", },
{ optInteger, "shiftwidth", },
{ optInteger, "sidescroll", },
{ optInteger, "tabstop", },
{ optInteger, "window", },
{ optTerminator, },
}, display_str[] = {
{ optString, "noprint", },
{ optString, "print", },
{ optTerminator, },
}, files[] = {
{ optToggle, "autowrite", },
{ optToggle, "lock", },
{ optToggle, "readonly", },
{ optToggle, "writeany", },
{ optTerminator, },
}, files_str[] = {
{ optString, "backup", },
{ optString, "path", },
{ optTerminator, },
}, general[] = {
{ optToggle, "exrc", },
{ optToggle, "lisp", },
{ optToggle, "modeline", },
{ optToggle, "sourceany", },
{ optToggle, "tildeop", },
{ optTerminator, },
}, general_int[] = {
{ optInteger, "taglength", },
{ optTerminator, },
}, general_str[] = {
{ optString, "cdpath", },
{ optString, "directory", },
{ optString, "msgcat", },
{ optString, "recdir", },
{ optString, "shell", },
{ optString, "shellmeta", },
{ optString, "tags", },
{ optTerminator, },
}, input[] = {
{ optToggle, "altwerase", },
{ optToggle, "autoindent", },
{ optToggle, "remap", },
{ optToggle, "showmatch", },
{ optToggle, "ttywerase", },
{ optTerminator, },
}, input_int[] = {
{ optInteger, "escapetime", },
{ optInteger, "keytime", },
{ optInteger, "matchtime", },
{ optInteger, "timeout", },
{ optInteger, "wraplen", },
{ optInteger, "wrapmargin", },
{ optTerminator, },
}, input_str[] = {
{ optString, "cedit", },
{ optString, "filec", },
{ optTerminator, },
}, search[] = {
{ optToggle, "extended", },
{ optToggle, "iclower", },
{ optToggle, "ignorecase", },
{ optToggle, "magic", },
{ optToggle, "searchincr", },
{ optToggle, "wrapscan", },
{ optTerminator, },
}, search_str[] = {
{ optString, "paragraphs", },
{ optString, "sections", },
{ optTerminator, },
};
/* ********* NOTE ***********
* Sheet 0 will always be shown first. It does not matter to the Xt code
* which sheet that is, so it ought to be the one users interact with most.
* Best guess is that's general editor options, but it might be Search/re.
* ********* NOTE ***********
*/
static optSheet sheets[] = {
{ "Display",
"These options control how text is displayed on the screen",
NULL,
display,
display_int,
display_str,
},
{ "Files",
"These options control how the editor handles files",
NULL,
files,
NULL,
files_str,
},
{ "Input",
"These options control text input behavior",
NULL,
input,
input_int,
input_str,
},
{ "Search/RE",
"These options control searching and Regular Expression behavior",
NULL,
search,
NULL,
search_str,
},
{ "Editor",
"These options control general editor configuration",
NULL,
general,
general_int,
general_str,
},
};
/* callbacks */
#if defined(SelfTest)
void __vi_cancel_cb()
{
puts( "cancelled" );
}
#endif
static void destroyed(void)
{
int i;
puts( "destroyed" );
/* some window managers destroy us upon popdown */
for (i=0; i<XtNumber(sheets); i++) {
sheets[i].holder = NULL;
}
preferences = NULL;
}
static void window_unmapped(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
{
if ( ev->type == UnmapNotify ) {
#if defined(SelfTest)
puts( "unmapped" );
#endif
XtPopdown( XtParent( preferences ) );
}
}
/*
* __vi_editopt --
* Set an edit option based on a core message.
*
* PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
*/
int
__vi_editopt(IPVI *ipvi, const char *str1, u_int32_t len1, const char *str2, u_int32_t len2, u_int32_t val1)
{
optData *opt;
#undef NSEARCH
#define NSEARCH(list) { \
for (opt = list; opt->kind != optTerminator; ++opt) \
if (!strcmp(opt->name, str1)) \
goto found; \
}
NSEARCH(display);
NSEARCH(display_int);
NSEARCH(display_str);
NSEARCH(files);
NSEARCH(files_str);
NSEARCH(general);
NSEARCH(general_int);
NSEARCH(general_str);
NSEARCH(input);
NSEARCH(input_int);
NSEARCH(input_str);
NSEARCH(search);
NSEARCH(search_str);
return (0);
found: switch (opt->kind) {
case optToggle:
opt->value = (void *)val1;
break;
case optInteger:
if (opt->value != NULL)
free(opt->value);
if ((opt->value = malloc(8)) != NULL)
(void)snprintf(opt->value,
8, "%lu", (u_long)val1);
break;
case optString:
case optFile:
if (opt->value != NULL)
free(opt->value);
if ((opt->value = malloc(len2)) != NULL)
memcpy(opt->value, str2, len2);
break;
case optTerminator:
abort();
}
return (0);
}
/*
* set_opt --
* Send a set-edit-option message to core.
*/
static void
set_opt(Widget w, XtPointer closure, XtPointer call_data)
{
optData *opt;
Boolean set;
IP_BUF ipb;
String str;
extern IPVI ipvi_motif;
opt = closure;
ipb.code = VI_EDITOPT;
ipb.str1 = opt->name;
ipb.len1 = strlen(opt->name);
switch (opt->kind) {
case optToggle:
XtVaGetValues(w, XmNset, &set, 0);
ipb.val1 = set;
ipb.len2 = 0;
vi_wsend(&ipvi_motif, "ab1", &ipb);
if (ipb.val1) {
opt->value = (void *)!set;
/*
* RAZ:
* How do we turn off the button? We don't want to
* go recursive where we set it and it calls set_opt
* to tell the core. Is that possible?
*/
XtVaSetValues(w, XmNset, &set, 0);
break;
}
if (strcmp(opt->name, "ruler") == 0)
if (set)
__vi_show_text_ruler_dialog(
__vi_screen->area, "Ruler");
else
__vi_clear_text_ruler_dialog();
break;
case optInteger:
str = XmTextFieldGetString(w);
ipb.val1 = atoi(str);
ipb.len2 = 0;
vi_send(vi_ofd, "ab1", &ipb);
break;
case optFile:
case optString:
ipb.str2 = XmTextFieldGetString(w);
ipb.len2 = strlen(ipb.str2);
vi_send(vi_ofd, "ab1", &ipb);
break;
case optTerminator:
abort();
}
}
/* add toggles to the property sheet */
#if defined(__STDC__)
static void add_toggle( Widget parent, optData *option )
#else
static void add_toggle( parent, option )
Widget parent;
optData *option;
#endif
{
Widget w;
w = XtVaCreateManagedWidget( option->name,
xmToggleButtonGadgetClass,
parent,
XmNset, (Boolean) option->value,
0
);
XtAddCallback( w, XmNvalueChangedCallback, set_opt, option );
}
static Widget create_toggles(Widget outer, optData *toggles)
{
Widget inner;
int i;
inner = XtVaCreateWidget( "toggleOptions",
xmRowColumnWidgetClass,
outer,
XmNpacking, XmPACK_COLUMN,
XmNnumColumns, 4,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
0
);
/* first the booleans */
for (i=0; toggles[i].kind != optTerminator; i++) {
add_toggle( inner, &toggles[i] );
}
XtManageChild( inner );
return inner;
}
/* draw text fields and their labels */
#if defined(__STDC__)
static void add_string_options( Widget parent,
optData *options
)
#else
static void add_string_options( parent, options )
Widget parent;
optData *options;
#endif
{
int i;
Widget f, w;
for ( i=0; options[i].kind != optTerminator; i++ ) {
f = XtVaCreateWidget( "form",
xmFormWidgetClass,
parent,
0
);
XtVaCreateManagedWidget( options[i].name,
xmLabelGadgetClass,
f,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 20,
XmNalignment, XmALIGNMENT_END,
0
);
w = XtVaCreateManagedWidget( "text",
xmTextFieldWidgetClass,
f,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 20,
0
);
XmTextFieldSetString( w, (char *) options[i].value );
XtAddCallback( w, XmNactivateCallback, set_opt, &options[i] );
XtManageChild( f );
}
}
/* draw and display a single page of properties */
#if defined(__STDC__)
static Widget create_sheet( Widget parent, optSheet *sheet )
#else
static Widget create_sheet( parent, sheet )
Widget parent;
optSheet *sheet;
#endif
{
Widget outer, inner, frame;
Dimension height;
XmString str;
outer = XtVaCreateWidget( sheet->name,
xmFormWidgetClass,
parent,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNshadowType, XmSHADOW_ETCHED_IN,
XmNshadowThickness, 2,
XmNverticalSpacing, 4,
XmNhorizontalSpacing, 4,
0
);
/* add descriptive text */
frame = XtVaCreateManagedWidget( "frame",
xmFrameWidgetClass,
outer,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
0
);
str = XmStringCreateLtoR( sheet->description, XmSTRING_DEFAULT_CHARSET );
XtVaCreateManagedWidget( "description",
xmLabelGadgetClass,
frame,
XmNlabelString, str,
0
);
XmStringFree( str );
/* Add the toggles. */
inner = create_toggles( outer, sheet->toggles );
XtVaSetValues( inner,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, frame,
0
);
/* the string options go here */
inner = XtVaCreateWidget( "otherOptions",
xmRowColumnWidgetClass,
outer,
XmNpacking, XmPACK_COLUMN,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, inner,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
0
);
/* Optionally, the ints. */
if ( sheet->ints != NULL )
add_string_options( inner, sheet->ints );
/* Optionally, the rest. */
if ( sheet->others != NULL )
add_string_options( inner, sheet->others );
XtManageChild( inner );
/* finally, force resize of the parent */
XtVaGetValues( outer, XmNheight, &height, 0 );
XtVaSetValues( parent, XmNheight, height, 0 );
return outer;
}
/* change preferences to another sheet */
static void change_sheet(Widget parent, int current)
{
static int current_sheet = -1;
/* create a new one? */
if ( sheets[current].holder == NULL )
sheets[current].holder = create_sheet( parent, &sheets[current] );
/* done with the old one? */
if ( current_sheet != -1 && sheets[current_sheet].holder != NULL )
XtUnmanageChild( sheets[current_sheet].holder );
current_sheet = current;
XtManageChild( sheets[current].holder );
XtManageChild( parent );
}
/* Draw and display a dialog the describes vi options */
#if defined(__STDC__)
static Widget create_options_dialog( Widget parent, String title )
#else
static Widget create_options_dialog( parent, title )
Widget parent;
String title;
#endif
{
Widget box, form, inner;
int i;
char buffer[1024];
/* already built? */
if ( preferences != NULL ) return preferences;
box = XtVaCreatePopupShell( title,
xmDialogShellWidgetClass,
parent,
XmNtitle, title,
XmNallowShellResize, False,
0
);
XtAddCallback( box, XmNpopdownCallback, __vi_cancel_cb, 0 );
XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
XtAddEventHandler( box,
SubstructureNotifyMask,
False,
window_unmapped,
NULL
);
form = XtVaCreateWidget( "options",
xmFormWidgetClass,
box,
0
);
/* copy the pointers to the sheet names */
*buffer = '\0';
for (i=0; i<XtNumber(sheets); i++) {
strcat( buffer, "|" );
strcat( buffer, sheets[i].name );
}
inner = __vi_CreateTabbedFolder( "tabs",
form,
buffer,
XtNumber(sheets),
change_sheet
);
/* build the property sheets early */
for ( i=0; i<XtNumber(sheets); i++ )
change_sheet( inner, i );
/* manage all of the sheets right now */
for ( i=0; i<XtNumber(sheets); i++ )
XtManageChild( sheets[i].holder );
XtManageChild( form );
/* remove all but the first one */
for ( i=0; i<XtNumber(sheets); i++ )
XtUnmanageChild( sheets[i].holder );
change_sheet( inner, 0 ); /* show first sheet first */
/* keep this global, we might destroy it later */
preferences = form;
/* done */
return form;
}
/*
* module entry point
*
* __vi_show_options_dialog --
*
*
* PUBLIC: void __vi_show_options_dialog __P((Widget, String));
*/
void
__vi_show_options_dialog(Widget parent, String title)
{
Widget db = create_options_dialog( parent, title );
#if defined(SelfTest)
Widget shell = XtParent( db );
#endif
XtManageChild( db );
#if defined(SelfTest)
/* wait until it goes away */
XtPopup( shell, XtGrabNone );
#else
/* wait until it goes away */
__vi_modal_dialog( db );
#endif
}
/* module entry point
* Utilities for the search dialog
*
* __vi_toggle --
* Returns the current value of a toggle.
*
* PUBLIC: int __vi_toggle __P((char *));
*/
int
__vi_toggle(char *name)
{
optData *opt;
#undef NSEARCH
#define NSEARCH(list) { \
for (opt = list; opt->kind != optTerminator; ++opt) \
if (!strcmp(opt->name, name)) \
return ((int)opt->value); \
}
NSEARCH(display);
NSEARCH(files);
NSEARCH(general);
NSEARCH(input);
NSEARCH(search);
return (0);
}
/*
* __vi_create_search_toggles --
* Creates the search toggles. This is so the options and search widgets
* share their appearance.
*
* PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
*/
Widget
__vi_create_search_toggles(Widget parent, optData *list)
{
optData *opt;
/*
* Copy current options information into the search table.
*
* XXX
* This is an O(M*N) loop, but I don't think it matters.
*/
for (opt = list; opt->kind != optTerminator; ++opt)
opt->value = (void *)__vi_toggle(opt->name);
return (create_toggles(parent, list));
}
#if defined(SelfTest)
#if defined(__STDC__)
static void show_options( Widget w, XtPointer data, XtPointer cbs )
#else
static void show_options( w, data, cbs )
Widget w;
XtPointer data;
XtPointer cbs;
#endif
{
__vi_show_options_dialog( data, "Preferences" );
}
main( int argc, char *argv[] )
{
XtAppContext ctx;
Widget top_level, rc, button;
extern exit();
/* create a top-level shell for the window manager */
top_level = XtVaAppInitialize( &ctx,
argv[0],
NULL, 0, /* options */
(ArgcType) &argc,
argv, /* might get modified */
NULL,
NULL
);
rc = XtVaCreateManagedWidget( "rc",
xmRowColumnWidgetClass,
top_level,
0
);
button = XtVaCreateManagedWidget( "Pop up options dialog",
xmPushButtonGadgetClass,
rc,
0
);
XtAddCallback( button, XmNactivateCallback, show_options, rc );
button = XtVaCreateManagedWidget( "Quit",
xmPushButtonGadgetClass,
rc,
0
);
XtAddCallback( button, XmNactivateCallback, exit, 0 );
XtRealizeWidget(top_level);
XtAppMainLoop(ctx);
}
#endif