static char*id="$XConsortium: xmessage.c,v 1.6 95/01/04 16:29:54 gildea 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();
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;
#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};
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);
}
static Atom wm_delete_window;
static void
exit_action(w, event, params, num_params)
Widget w;
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;
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";
static void
position_near(shell, x, y)
Widget shell;
int x, y;
{
int max_x, max_y;
Dimension width, height, border;
int gravity;
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));
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);
}
static void
time_out(client_data, iid)
XtPointer client_data;
XtIntervalId *iid;
{
exit(0);
}
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;
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));
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);
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);
}