diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:23 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:23 +0000 |
commit | e87b0d408c8bef387afb069e25028d9a52c58a62 (patch) | |
tree | 0603114002777b275caa6d51a17e09e2ce657b85 /xmessage.c |
Initial revision
Diffstat (limited to 'xmessage.c')
-rw-r--r-- | xmessage.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/xmessage.c b/xmessage.c new file mode 100644 index 0000000..c5f367c --- /dev/null +++ b/xmessage.c @@ -0,0 +1,355 @@ +static char*id="$XConsortium: xmessage.c,v 1.6 95/01/04 16:29:54 gildea Exp $"; +/* + +Copyright (c) 1988, 1991, 1994 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/xmessage.c,v 1.4 2000/02/17 16:53:03 dawes Exp $ */ + +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <stdio.h> +#include <stdlib.h> + +extern char *read_file(); +extern Widget make_queryform(); + +/* + * data used by xmessage + */ + +const char *ProgramName; + +static struct _QueryResources { + char *file; + char *button_list; + char *default_button; + Boolean print_value; + Boolean center; + Boolean nearmouse; + int timeout_secs; + Dimension maxHeight; + Dimension maxWidth; +} qres; /* initialized by resources below */ + +#define offset(field) XtOffsetOf(struct _QueryResources, field) +static XtResource resources[] = { + { "file", "File", XtRString, sizeof (char *), + offset(file), XtRString, (XtPointer) NULL }, + { "buttons", "Buttons", XtRString, sizeof (char *), + offset(button_list), XtRString, (XtPointer) "okay:0" }, + { "defaultButton", "DefaultButton", XtRString, sizeof (char *), + offset(default_button), XtRString, (XtPointer) NULL }, + { "printValue", "PrintValue", XtRBoolean, sizeof (Boolean), + offset(print_value), XtRString, "false" }, + { "center", "Center", XtRBoolean, sizeof (Boolean), + offset(center), XtRString, "false" }, + { "nearMouse", "NearMouse", XtRBoolean, sizeof (Boolean), + offset(nearmouse), XtRString, "false" }, + { "timeout", "Timeout", XtRInt, sizeof (int), + offset(timeout_secs), XtRInt, 0 }, + { "maxHeight", "Maximum", XtRDimension, sizeof (Dimension), + offset(maxHeight), XtRDimension, 0 }, + { "maxWidth", "Maximum", XtRDimension, sizeof (Dimension), + offset(maxWidth), XtRDimension, 0 }, +}; +#undef offset + +static XrmOptionDescRec optionList[] = { + { "-file", ".file", XrmoptionSepArg, (XPointer) NULL }, + { "-buttons", ".buttons", XrmoptionSepArg, (XPointer) NULL }, + { "-default", ".defaultButton", XrmoptionSepArg, (XPointer) NULL }, + { "-print", ".printValue", XrmoptionNoArg, (XPointer) "on" }, + { "-center", ".center", XrmoptionNoArg, (XPointer) "on" }, + { "-nearmouse", ".nearMouse", XrmoptionNoArg, (XPointer) "on" }, + { "-timeout", ".timeout", XrmoptionSepArg, (XPointer) NULL }, +}; + +static String fallback_resources[] = { + "*baseTranslations: #override :<Key>Return: default-exit()", + "*message.Scroll: whenNeeded", + NULL}; + + +/* + * usage + */ + +static void usage (outf) + FILE *outf; +{ + static const char *options[] = { +" -file filename file to read message from, \"-\" for stdin", +" -buttons string comma-separated list of label:exitcode", +" -default button button to activate if Return is pressed", +" -print print the button label when selected", +" -center pop up at center of screen", +" -nearmouse pop up near the mouse cursor", +" -timeout secs exit with status 0 after \"secs\" seconds", +"", +NULL}; + const char **cpp; + + fprintf (outf, "usage: %s [-options] [message ...]\n\n", + ProgramName); + fprintf (outf, "where options include:\n"); + for (cpp = options; *cpp; cpp++) + fprintf (outf, "%s\n", *cpp); + fprintf (outf, "%s\n", id+1); +} + +/* + * Action to implement ICCCM delete_window and other translations. + * Takes one argument, the exit status. + */ +static Atom wm_delete_window; +/* ARGSUSED */ +static void +exit_action(w, event, params, num_params) + Widget w; /* unused */ + XEvent *event; + String *params; + Cardinal *num_params; +{ + int exit_status = 0; + + if(event->type == ClientMessage + && event->xclient.data.l[0] != wm_delete_window) + return; + + if (*num_params == 1) + exit_status = atoi(params[0]); + exit(exit_status); +} + +int default_exitstatus = -1; /* value of button named by -default */ + +/* ARGSUSED */ +static void +default_exit_action(w, event, params, num_params) + Widget w; + XEvent *event; + String *params; + Cardinal *num_params; +{ + if (default_exitstatus >= 0) + exit(default_exitstatus); +} + +static XtActionsRec actions_list[] = { + {"exit", exit_action}, + {"default-exit", default_exit_action}, +}; + +static String top_trans = + "<ClientMessage>WM_PROTOCOLS: exit(1)\n"; + +/* assumes shell widget has already been realized */ + +static void +position_near(shell, x, y) + Widget shell; + int x, y; +{ + int max_x, max_y; + Dimension width, height, border; + int gravity; + + /* some of this is copied from CenterWidgetOnPoint in Xaw/TextPop.c */ + + XtVaGetValues(shell, + XtNwidth, &width, + XtNheight, &height, + XtNborderWidth, &border, + NULL); + + width += 2 * border; + height += 2 * border; + + max_x = WidthOfScreen(XtScreen(shell)); + max_y = HeightOfScreen(XtScreen(shell)); + + /* set gravity hint based on position on screen */ + gravity = 1; + if (x > max_x/3) gravity += 1; + if (x > max_x*2/3) gravity += 1; + if (y > max_y/3) gravity += 3; + if (y > max_y*2/3) gravity += 3; + + max_x -= width; + max_y -= height; + + x -= ( (Position) width/2 ); + if (x < 0) x = 0; + if (x > max_x) x = max_x; + + y -= ( (Position) height/2 ); + if (y < 0) y = 0; + if ( y > max_y ) y = max_y; + + XtVaSetValues(shell, + XtNx, (Position)x, + XtNy, (Position)y, + XtNwinGravity, gravity, + NULL); +} + +static void +position_near_mouse(shell) + Widget shell; +{ + int x, y; + Window root, child; + int winx, winy; + unsigned int mask; + + XQueryPointer(XtDisplay(shell), XtWindow(shell), + &root, &child, &x, &y, &winx, &winy, &mask); + position_near(shell, x, y); +} + +static void +position_near_center(shell) + Widget shell; +{ + position_near(shell, + WidthOfScreen(XtScreen(shell))/2, + HeightOfScreen(XtScreen(shell))/2); +} + +/* ARGSUSED */ +static void +time_out(client_data, iid) + XtPointer client_data; + XtIntervalId *iid; +{ + exit(0); +} + +/* + * xmessage main program - make sure that there is a message, + * then create the query box and go. Callbacks take care of exiting. + */ +int +main (argc, argv) + int argc; + char **argv; +{ + Widget top, queryform; + XtAppContext app_con; + char *message_str; + int message_len; + + ProgramName = argv[0]; + + XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); + + top = XtAppInitialize (&app_con, "Xmessage", + optionList, XtNumber(optionList), &argc, argv, + fallback_resources, NULL, 0); + + XtGetApplicationResources (top, (XtPointer) &qres, resources, + XtNumber(resources), NULL, 0); + + if (argc > 1 && !strcmp(argv[1], "-help")) { + usage(stdout); + exit(0); + } + if (argc == 1 && qres.file != NULL) { + message_str = read_file (qres.file, &message_len); + if (message_str == NULL) { + fprintf (stderr, "%s: problems reading message file\n", + ProgramName); + exit (1); + } + } else if (argc > 1 && qres.file == NULL) { + int i, len; + char *cp; + + len = argc - 1; /* spaces between words and final NULL */ + for (i=1; i<argc; i++) + len += strlen(argv[i]); + message_str = malloc(len); + if (!message_str) { + fprintf (stderr, "%s: cannot get memory for message string\n", + ProgramName); + exit (1); + } + cp = message_str; + for (i=1; i<argc; i++) { + strcpy(cp, argv[i]); + cp += strlen(argv[i]); + if (i != argc-1) + *cp++ = ' '; + else + *cp = '\0'; + } + message_len = len; + } else { + usage(stderr); + exit(1); + } + + wm_delete_window = XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW", False); + XtAppAddActions(app_con, actions_list, XtNumber(actions_list)); + XtOverrideTranslations(top, XtParseTranslationTable(top_trans)); + + /* + * create the query form; this is where most of the real work is done + */ + queryform = make_queryform (top, message_str, message_len, + qres.button_list, + qres.print_value, qres.default_button, + qres.maxWidth, qres.maxHeight); + if (!queryform) { + fprintf (stderr, + "%s: unable to create query form with buttons: %s\n", + ProgramName, qres.button_list); + exit (1); + } + + XtSetMappedWhenManaged(top, FALSE); + XtRealizeWidget(top); + + /* do WM_DELETE_WINDOW before map */ + XSetWMProtocols(XtDisplay(top), XtWindow(top), &wm_delete_window, 1); + + if (qres.center) + position_near_center(top); + else if (qres.nearmouse) + position_near_mouse(top); + + XtMapWidget(top); + + if (qres.timeout_secs) + XtAppAddTimeOut(app_con, 1000*qres.timeout_secs, time_out, NULL); + + XtAppMainLoop(app_con); + + exit (0); +} |