sync code with last improvements from OpenBSD
This commit is contained in:
commit
88965415ff
26235 changed files with 29195616 additions and 0 deletions
341
app/xmessage/makeform.c
Normal file
341
app/xmessage/makeform.c
Normal file
|
@ -0,0 +1,341 @@
|
|||
/* $XConsortium: makeform.c,v 1.6 95/01/04 16:28:51 gildea Exp $ */
|
||||
/*
|
||||
|
||||
Copyright (c) 1988, 1991 X Consortium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the X Consortium shall
|
||||
not be used in advertising or otherwise to promote the sale, use or
|
||||
other dealings in this Software without prior written authorization
|
||||
from the X Consortium.
|
||||
|
||||
*/
|
||||
/* $XFree86: xc/programs/xmessage/makeform.c,v 1.6 2002/11/22 03:56:39 paulo Exp $ */
|
||||
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <X11/Shell.h>
|
||||
#include <X11/Xaw/Form.h>
|
||||
#include <X11/Xaw/AsciiText.h>
|
||||
#include <X11/Xaw/Command.h>
|
||||
#include <X11/Xaw/Label.h>
|
||||
#include <X11/Xaw/Scrollbar.h>
|
||||
|
||||
#include "xmessage.h"
|
||||
|
||||
typedef struct _ButtonRecord {
|
||||
char *name;
|
||||
int exitstatus;
|
||||
Boolean print_value;
|
||||
Widget widget;
|
||||
} ButtonRecord;
|
||||
|
||||
static void
|
||||
unquote_pairs (ButtonRecord *br, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++, br++) {
|
||||
char *dst, *src;
|
||||
int quoted = 0;
|
||||
|
||||
for (src = dst = br->name; *src; src++) {
|
||||
if (quoted) {
|
||||
*dst++ = *src;
|
||||
quoted = 0;
|
||||
} else if (src[0] == '\\') {
|
||||
quoted = 1;
|
||||
} else {
|
||||
*dst++ = *src;
|
||||
}
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* parses string of form "yes:11,no:12, ..."
|
||||
* sets brptr to point to parsed table
|
||||
* returns 0 if successful, -1 if not
|
||||
*/
|
||||
static int
|
||||
parse_name_and_exit_code_list (char *buttonlist, ButtonRecord **brptr)
|
||||
{
|
||||
char *cp;
|
||||
int shouldfind = 0, npairs = 0;
|
||||
int default_exitcode = 100;
|
||||
int quoted = 0;
|
||||
ButtonRecord *br;
|
||||
int len;
|
||||
char *copy;
|
||||
|
||||
*brptr = NULL;
|
||||
if (!buttonlist) return 0;
|
||||
|
||||
/*
|
||||
* Figure out how many matches we will find so that we can preallocate
|
||||
* space for button structures. If you add stripping of white space,
|
||||
* make sure that you update this as well as the walking algorithm below.
|
||||
*/
|
||||
if (buttonlist[0]) shouldfind++;
|
||||
for (cp = buttonlist; *cp; cp++) {
|
||||
if (quoted == 1) quoted = 0;
|
||||
else if (*cp == '\\') quoted = 1;
|
||||
else if (*cp == ',') shouldfind++;
|
||||
}
|
||||
len = (cp - buttonlist);
|
||||
|
||||
/*
|
||||
* allocate space for button record
|
||||
*/
|
||||
br = (ButtonRecord *) malloc (sizeof(ButtonRecord) * shouldfind);
|
||||
if (!br) return -1;
|
||||
|
||||
cp = malloc (len + 1);
|
||||
if (!cp) {
|
||||
free (br);
|
||||
return -1;
|
||||
}
|
||||
copy = cp;
|
||||
strcpy (copy, buttonlist);
|
||||
|
||||
|
||||
/*
|
||||
* walk down list separating into name:exitcode pairs
|
||||
*/
|
||||
while (*cp) {
|
||||
char *start, *colon, *comma;
|
||||
int exitcode;
|
||||
|
||||
start = cp;
|
||||
colon = comma = NULL;
|
||||
exitcode = ++default_exitcode;
|
||||
quoted = 0;
|
||||
|
||||
/* find the next name and exit code */
|
||||
for (; *cp; cp++) {
|
||||
if (quoted) quoted = 0;
|
||||
else if (*cp == '\\') quoted = 1;
|
||||
else if (*cp == ':') colon = cp;
|
||||
else if (*cp == ',') {
|
||||
comma = cp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If comma is NULL then we are at the end of the string. If colon
|
||||
* is NULL, then there was no exit code given, so default to zero.
|
||||
*/
|
||||
|
||||
if (comma) *comma = '\0';
|
||||
|
||||
if (colon) {
|
||||
exitcode = atoi (colon+1);
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure that we aren't about to stomp on memory
|
||||
*/
|
||||
if (npairs >= shouldfind) {
|
||||
fprintf (stderr,
|
||||
"%s: internal error, found extra pairs (should be %d)\n",
|
||||
ProgramName, shouldfind);
|
||||
free (br);
|
||||
free (copy);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* got it! start and exitcode contain the right values
|
||||
*/
|
||||
br[npairs].name = start;
|
||||
br[npairs].exitstatus = exitcode;
|
||||
npairs++;
|
||||
|
||||
if (comma) cp++;
|
||||
}
|
||||
|
||||
|
||||
if (npairs != shouldfind) {
|
||||
fprintf (stderr, "%s: internal error found %d instead of %d pairs\n",
|
||||
ProgramName, npairs, shouldfind);
|
||||
free (br);
|
||||
free (copy);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* now, strip any quoted characters
|
||||
*/
|
||||
unquote_pairs (br, npairs);
|
||||
*brptr = br;
|
||||
return npairs;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
handle_button (Widget w, XtPointer closure, XtPointer client_data)
|
||||
{
|
||||
ButtonRecord *br = (ButtonRecord *) closure;
|
||||
|
||||
if (br->print_value)
|
||||
puts (br->name);
|
||||
exit (br->exitstatus);
|
||||
}
|
||||
|
||||
Widget
|
||||
make_queryform(Widget parent, /* into whom widget should be placed */
|
||||
char *msgstr, /* message string */
|
||||
int msglen, /* characters in msgstr */
|
||||
char *button_list, /* list of button title:status */
|
||||
Boolean print_value, /* print button string on stdout? */
|
||||
char *default_button, /* button activated by Return */
|
||||
Dimension max_width,
|
||||
Dimension max_height)
|
||||
{
|
||||
ButtonRecord *br;
|
||||
int npairs, i;
|
||||
Widget form, text, prev;
|
||||
Arg args[10];
|
||||
Cardinal n, thisn;
|
||||
char *shell_geom;
|
||||
int x, y, geom_flags;
|
||||
unsigned int shell_w, shell_h;
|
||||
|
||||
npairs = parse_name_and_exit_code_list (button_list, &br);
|
||||
|
||||
form = XtCreateManagedWidget ("form", formWidgetClass, parent, NULL, 0);
|
||||
|
||||
text = XtVaCreateManagedWidget
|
||||
("message", asciiTextWidgetClass, form,
|
||||
XtNleft, XtChainLeft,
|
||||
XtNright, XtChainRight,
|
||||
XtNtop, XtChainTop,
|
||||
XtNbottom, XtChainBottom,
|
||||
XtNdisplayCaret, False,
|
||||
XtNlength, msglen,
|
||||
XtNstring, msgstr,
|
||||
NULL);
|
||||
/*
|
||||
* Did the user specify our geometry?
|
||||
* If so, don't bother computing it ourselves, since we will be overridden.
|
||||
*/
|
||||
XtVaGetValues(parent, XtNgeometry, &shell_geom, NULL);
|
||||
geom_flags = XParseGeometry(shell_geom, &x, &y, &shell_w, &shell_h);
|
||||
if (!(geom_flags & WidthValue && geom_flags & HeightValue)) {
|
||||
Dimension width, height, height_addons = 0;
|
||||
Dimension scroll_size, border_width;
|
||||
Widget label, scroll;
|
||||
Position left, right, top, bottom;
|
||||
char *tmp;
|
||||
/*
|
||||
* A Text widget is used for the automatic scroll bars.
|
||||
* But Text widget doesn't automatically compute its size.
|
||||
* The Label widget does that nicely, so we create one and examine it.
|
||||
* This widget is never visible.
|
||||
*/
|
||||
XtVaGetValues(text, XtNtopMargin, &top, XtNbottomMargin, &bottom,
|
||||
XtNleftMargin, &left, XtNrightMargin, &right, NULL);
|
||||
label = XtVaCreateWidget("message", labelWidgetClass, form,
|
||||
XtNlabel, msgstr,
|
||||
XtNinternalWidth, (left+right+1)/2,
|
||||
XtNinternalHeight, (top+bottom+1)/2,
|
||||
NULL);
|
||||
XtVaGetValues(label, XtNwidth, &width, XtNheight, &height, NULL);
|
||||
XtDestroyWidget(label);
|
||||
if (max_width == 0)
|
||||
max_width = .7 * WidthOfScreen(XtScreen(text));
|
||||
if (max_height == 0)
|
||||
max_height = .7 * HeightOfScreen(XtScreen(text));
|
||||
if (width > max_width) {
|
||||
width = max_width;
|
||||
/* add in the height of any horizontal scroll bar */
|
||||
scroll = XtVaCreateWidget("hScrollbar", scrollbarWidgetClass, text,
|
||||
XtNorientation, XtorientHorizontal,
|
||||
NULL);
|
||||
XtVaGetValues(scroll, XtNheight, &scroll_size,
|
||||
XtNborderWidth, &border_width, NULL);
|
||||
XtDestroyWidget(scroll);
|
||||
height_addons = scroll_size + border_width;
|
||||
}
|
||||
|
||||
/* This fixes the xmessage assumption that the label widget and the
|
||||
* text widget have the same size. In Xaw 7, the text widget has
|
||||
* one extra pixel between lines.
|
||||
* Xmessage is not internationalized, so the code bellow is harmless.
|
||||
*/
|
||||
tmp = msgstr;
|
||||
while (tmp != NULL && *tmp) {
|
||||
++tmp;
|
||||
++height;
|
||||
tmp = strchr(tmp, '\n');
|
||||
}
|
||||
|
||||
if (height > max_height) {
|
||||
height = max_height;
|
||||
/* add in the width of any vertical scroll bar */
|
||||
scroll = XtVaCreateWidget("vScrollbar", scrollbarWidgetClass, text,
|
||||
XtNorientation, XtorientVertical, NULL);
|
||||
XtVaGetValues(scroll, XtNwidth, &scroll_size,
|
||||
XtNborderWidth, &border_width, NULL);
|
||||
XtDestroyWidget(scroll);
|
||||
width += scroll_size + border_width;
|
||||
}
|
||||
height += height_addons;
|
||||
XtVaSetValues(text, XtNwidth, width, XtNheight, height, NULL);
|
||||
}
|
||||
/*
|
||||
* Create the buttons
|
||||
*/
|
||||
n = 0;
|
||||
XtSetArg (args[n], XtNleft, XtChainLeft); n++;
|
||||
XtSetArg (args[n], XtNright, XtChainLeft); n++;
|
||||
XtSetArg (args[n], XtNtop, XtChainBottom); n++;
|
||||
XtSetArg (args[n], XtNbottom, XtChainBottom); n++;
|
||||
XtSetArg (args[n], XtNfromVert, text); n++;
|
||||
XtSetArg (args[n], XtNvertDistance, 5); n++;
|
||||
|
||||
prev = NULL;
|
||||
for (i = 0; i < npairs; i++) {
|
||||
thisn = n;
|
||||
XtSetArg (args[thisn], XtNfromHoriz, prev); thisn++;
|
||||
prev = XtCreateManagedWidget (br[i].name, commandWidgetClass,
|
||||
form, args, thisn);
|
||||
br[i].widget = prev;
|
||||
br[i].print_value = print_value;
|
||||
XtAddCallback (prev, XtNcallback, handle_button, (XtPointer) &br[i]);
|
||||
if (default_button && !strcmp(default_button, br[i].name)) {
|
||||
Dimension border;
|
||||
|
||||
default_exitstatus = br[i].exitstatus;
|
||||
XtVaGetValues(br[i].widget, XtNborderWidth, &border, NULL);
|
||||
border *= 2;
|
||||
XtVaSetValues(br[i].widget, XtNborderWidth, border, NULL);
|
||||
}
|
||||
}
|
||||
return form;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue