x11-ssh-askpass.c revision 8db30ca8
18db30ca8Sthorpej/* x11-ssh-askpass.c:  A generic X11-based password dialog for OpenSSH.
28db30ca8Sthorpej * created 1999-Nov-17 03:40 Jim Knoble <jmknoble@pobox.com>
38db30ca8Sthorpej * autodate: 1999-Nov-23 02:52
48db30ca8Sthorpej *
58db30ca8Sthorpej * by Jim Knoble <jmknoble@pobox.com>
68db30ca8Sthorpej * Copyright � 1999 Jim Knoble
78db30ca8Sthorpej *
88db30ca8Sthorpej * Disclaimer:
98db30ca8Sthorpej *
108db30ca8Sthorpej * The software is provided "as is", without warranty of any kind,
118db30ca8Sthorpej * express or implied, including but not limited to the warranties of
128db30ca8Sthorpej * merchantability, fitness for a particular purpose and
138db30ca8Sthorpej * noninfringement. In no event shall the author(s) be liable for any
148db30ca8Sthorpej * claim, damages or other liability, whether in an action of
158db30ca8Sthorpej * contract, tort or otherwise, arising from, out of or in connection
168db30ca8Sthorpej * with the software or the use or other dealings in the software.
178db30ca8Sthorpej *
188db30ca8Sthorpej * Portions of this code are distantly derived from code in xscreensaver
198db30ca8Sthorpej * by Jamie Zawinski <jwz@jwz.org>.  That code says:
208db30ca8Sthorpej *
218db30ca8Sthorpej * --------8<------------------------------------------------8<--------
228db30ca8Sthorpej * xscreensaver, Copyright (c) 1991-1999 Jamie Zawinski <jwz@jwz.org>
238db30ca8Sthorpej *
248db30ca8Sthorpej * Permission to use, copy, modify, distribute, and sell this software and its
258db30ca8Sthorpej * documentation for any purpose is hereby granted without fee, provided that
268db30ca8Sthorpej * the above copyright notice appear in all copies and that both that
278db30ca8Sthorpej * copyright notice and this permission notice appear in supporting
288db30ca8Sthorpej * documentation.  No representations are made about the suitability of this
298db30ca8Sthorpej * software for any purpose.  It is provided "as is" without express or
308db30ca8Sthorpej * implied warranty.
318db30ca8Sthorpej * --------8<------------------------------------------------8<--------
328db30ca8Sthorpej *
338db30ca8Sthorpej * The remainder of this code falls under the same permissions and
348db30ca8Sthorpej * provisions as those of the xscreensaver code.
358db30ca8Sthorpej */
368db30ca8Sthorpej
378db30ca8Sthorpej#include <stdio.h>
388db30ca8Sthorpej#include <stdlib.h>
398db30ca8Sthorpej#include <string.h>
408db30ca8Sthorpej
418db30ca8Sthorpej/* For (get|set)rlimit() ... */
428db30ca8Sthorpej#include <sys/time.h>
438db30ca8Sthorpej#include <sys/resource.h>
448db30ca8Sthorpej#include <unistd.h>
458db30ca8Sthorpej/* ... end */
468db30ca8Sthorpej
478db30ca8Sthorpej/* For errno ... */
488db30ca8Sthorpej#include <errno.h>
498db30ca8Sthorpej/* ... end */
508db30ca8Sthorpej
518db30ca8Sthorpej#include <X11/Xlib.h>
528db30ca8Sthorpej#include <X11/Intrinsic.h>
538db30ca8Sthorpej#include <X11/Shell.h>
548db30ca8Sthorpej#include <X11/Xos.h>
558db30ca8Sthorpej#include "dynlist.h"
568db30ca8Sthorpej#include "drawing.h"
578db30ca8Sthorpej#include "resources.h"
588db30ca8Sthorpej#include "x11-ssh-askpass.h"
598db30ca8Sthorpej
608db30ca8Sthorpej#undef MAX
618db30ca8Sthorpej#define MAX(a,b) (((a) > (b)) ? (a) : (b))
628db30ca8Sthorpej
638db30ca8Sthorpejchar *progname = NULL;
648db30ca8Sthorpejchar *progclass = NULL;
658db30ca8SthorpejXrmDatabase db = 0;
668db30ca8Sthorpej
678db30ca8Sthorpejstatic char *defaults[] = {
688db30ca8Sthorpej#include "SshAskpass_ad.h"
698db30ca8Sthorpej   0
708db30ca8Sthorpej};
718db30ca8Sthorpej
728db30ca8Sthorpejvoid outOfMemory(AppInfo *app, int line)
738db30ca8Sthorpej{
748db30ca8Sthorpej   fprintf(stderr, "%s: Aaahhh! I ran out of memory at line %d.\n",
758db30ca8Sthorpej	   app->appName, line);
768db30ca8Sthorpej   exit(EXIT_STATUS_NO_MEMORY);
778db30ca8Sthorpej}
788db30ca8Sthorpej
798db30ca8Sthorpejvoid freeIf(void *p)
808db30ca8Sthorpej{
818db30ca8Sthorpej   if (p) {
828db30ca8Sthorpej      free(p);
838db30ca8Sthorpej   }
848db30ca8Sthorpej}
858db30ca8Sthorpej
868db30ca8Sthorpejvoid freeFontIf(AppInfo *app, XFontStruct *f)
878db30ca8Sthorpej{
888db30ca8Sthorpej   if (f) {
898db30ca8Sthorpej      XFreeFont(app->dpy, f);
908db30ca8Sthorpej   }
918db30ca8Sthorpej}
928db30ca8Sthorpej
938db30ca8SthorpejXFontStruct *getFontResource(AppInfo *app, char *instanceName, char *className)
948db30ca8Sthorpej{
958db30ca8Sthorpej   char *fallbackFont = "fixed";
968db30ca8Sthorpej
978db30ca8Sthorpej   XFontStruct *f = NULL;
988db30ca8Sthorpej   char *s = get_string_resource(instanceName, className);
998db30ca8Sthorpej   f = XLoadQueryFont(app->dpy, (s ? s : fallbackFont));
1008db30ca8Sthorpej   if (!f) {
1018db30ca8Sthorpej      f = XLoadQueryFont(app->dpy, fallbackFont);
1028db30ca8Sthorpej   }
1038db30ca8Sthorpej   if (s) {
1048db30ca8Sthorpej      free(s);
1058db30ca8Sthorpej   }
1068db30ca8Sthorpej   return(f);
1078db30ca8Sthorpej}
1088db30ca8Sthorpej
1098db30ca8Sthorpejchar *getStringResourceWithDefault(char *instanceName, char *className,
1108db30ca8Sthorpej				   char *defaultText)
1118db30ca8Sthorpej{
1128db30ca8Sthorpej   char *s = get_string_resource(instanceName, className);
1138db30ca8Sthorpej   if (!s) {
1148db30ca8Sthorpej      if (!defaultText) {
1158db30ca8Sthorpej	 s = strdup("");
1168db30ca8Sthorpej      } else {
1178db30ca8Sthorpej	 s = strdup(defaultText);
1188db30ca8Sthorpej      }
1198db30ca8Sthorpej   }
1208db30ca8Sthorpej   return(s);
1218db30ca8Sthorpej}
1228db30ca8Sthorpej
1238db30ca8Sthorpejvoid calcLabelTextExtents(LabelInfo *label)
1248db30ca8Sthorpej{
1258db30ca8Sthorpej   if ((!label) || (!(label->text)) || (!(label->font))) {
1268db30ca8Sthorpej      return;
1278db30ca8Sthorpej   }
1288db30ca8Sthorpej   label->textLength = strlen(label->text);
1298db30ca8Sthorpej   XTextExtents(label->font, label->text, label->textLength,
1308db30ca8Sthorpej		&(label->direction), &(label->ascent), &(label->descent),
1318db30ca8Sthorpej		&(label->overall));
1328db30ca8Sthorpej   label->w.height = label->descent + label->ascent;
1338db30ca8Sthorpej   label->w.width = label->overall.width;
1348db30ca8Sthorpej}
1358db30ca8Sthorpej
1368db30ca8Sthorpejvoid calcTotalButtonExtents(ButtonInfo *button)
1378db30ca8Sthorpej{
1388db30ca8Sthorpej   if (!button) {
1398db30ca8Sthorpej      return;
1408db30ca8Sthorpej   }
1418db30ca8Sthorpej   button->w3.w.width = (button->w3.interiorWidth +
1428db30ca8Sthorpej			 (2 * button->w3.shadowThickness));
1438db30ca8Sthorpej   button->w3.w.width += (2 * button->w3.borderWidth);
1448db30ca8Sthorpej   button->w3.w.height = (button->w3.interiorHeight +
1458db30ca8Sthorpej			  (2 * button->w3.shadowThickness));
1468db30ca8Sthorpej   button->w3.w.height += (2 * button->w3.borderWidth);
1478db30ca8Sthorpej}
1488db30ca8Sthorpej
1498db30ca8Sthorpejvoid calcButtonExtents(ButtonInfo *button)
1508db30ca8Sthorpej{
1518db30ca8Sthorpej   if (!button) {
1528db30ca8Sthorpej      return;
1538db30ca8Sthorpej   }
1548db30ca8Sthorpej   calcLabelTextExtents(&(button->label));
1558db30ca8Sthorpej   button->w3.interiorWidth = (button->label.w.width +
1568db30ca8Sthorpej			       (2 * button->w3.horizontalSpacing));
1578db30ca8Sthorpej   button->w3.interiorHeight = (button->label.w.height +
1588db30ca8Sthorpej				(2 * button->w3.verticalSpacing));
1598db30ca8Sthorpej   calcTotalButtonExtents(button);
1608db30ca8Sthorpej}
1618db30ca8Sthorpej
1628db30ca8Sthorpejvoid balanceButtonExtents(ButtonInfo *button1, ButtonInfo *button2)
1638db30ca8Sthorpej{
1648db30ca8Sthorpej   if ((!button1) || (!button2)) {
1658db30ca8Sthorpej      return;
1668db30ca8Sthorpej   }
1678db30ca8Sthorpej   button1->w3.interiorWidth = button2->w3.interiorWidth =
1688db30ca8Sthorpej      MAX(button1->w3.interiorWidth, button2->w3.interiorWidth);
1698db30ca8Sthorpej   button1->w3.interiorHeight = button2->w3.interiorHeight =
1708db30ca8Sthorpej      MAX(button1->w3.interiorHeight, button2->w3.interiorHeight);
1718db30ca8Sthorpej   calcTotalButtonExtents(button1);
1728db30ca8Sthorpej   calcTotalButtonExtents(button2);
1738db30ca8Sthorpej}
1748db30ca8Sthorpej
1758db30ca8Sthorpejvoid calcButtonLabelPosition(ButtonInfo *button)
1768db30ca8Sthorpej{
1778db30ca8Sthorpej   if (!button) {
1788db30ca8Sthorpej      return;
1798db30ca8Sthorpej   }
1808db30ca8Sthorpej   button->label.w.x = button->w3.w.x +
1818db30ca8Sthorpej      ((button->w3.w.width - button->label.w.width) / 2);
1828db30ca8Sthorpej   button->label.w.y = button->w3.w.y +
1838db30ca8Sthorpej      ((button->w3.w.height - button->label.w.height) / 2)
1848db30ca8Sthorpej      + button->label.ascent;
1858db30ca8Sthorpej}
1868db30ca8Sthorpej
1878db30ca8Sthorpejvoid createDialog(AppInfo *app)
1888db30ca8Sthorpej{
1898db30ca8Sthorpej   DialogInfo *d;
1908db30ca8Sthorpej
1918db30ca8Sthorpej   if (app->dialog) {
1928db30ca8Sthorpej      return;
1938db30ca8Sthorpej   }
1948db30ca8Sthorpej   d = malloc(sizeof(*d));
1958db30ca8Sthorpej   if (NULL == d) {
1968db30ca8Sthorpej      outOfMemory(app, __LINE__);
1978db30ca8Sthorpej   }
1988db30ca8Sthorpej   memset(d, 0, sizeof(*d));
1998db30ca8Sthorpej
2008db30ca8Sthorpej   app->grabKeyboard =
2018db30ca8Sthorpej      get_boolean_resource("grabKeyboard", "GrabKeyboard", True);
2028db30ca8Sthorpej   app->grabPointer =
2038db30ca8Sthorpej      get_boolean_resource("grabPointer", "GrabPointer", False);
2048db30ca8Sthorpej   app->grabPointer =
2058db30ca8Sthorpej      get_boolean_resource("grabServer", "GrabServer", False);
2068db30ca8Sthorpej
2078db30ca8Sthorpej   d->title =
2088db30ca8Sthorpej      getStringResourceWithDefault("dialog.title", "Dialog.Title",
2098db30ca8Sthorpej				   "OpenSSH Authentication Passphrase Request");
2108db30ca8Sthorpej   d->w3.w.foreground =
2118db30ca8Sthorpej      get_pixel_resource("foreground", "Foreground",
2128db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2138db30ca8Sthorpej   d->w3.w.background =
2148db30ca8Sthorpej      get_pixel_resource("background", "Background",
2158db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
2168db30ca8Sthorpej   d->w3.topShadowColor =
2178db30ca8Sthorpej      get_pixel_resource("topShadowColor", "TopShadowColor",
2188db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
2198db30ca8Sthorpej   d->w3.bottomShadowColor =
2208db30ca8Sthorpej      get_pixel_resource("bottomShadowColor", "BottomShadowColor",
2218db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2228db30ca8Sthorpej   d->w3.shadowThickness =
2238db30ca8Sthorpej      get_integer_resource("shadowThickness", "ShadowThickness", 3);
2248db30ca8Sthorpej   d->w3.borderColor =
2258db30ca8Sthorpej      get_pixel_resource("borderColor", "BorderColor",
2268db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2278db30ca8Sthorpej   d->w3.borderWidth =
2288db30ca8Sthorpej      get_integer_resource("borderWidth", "BorderWidth", 1);
2298db30ca8Sthorpej
2308db30ca8Sthorpej   d->w3.horizontalSpacing =
2318db30ca8Sthorpej      get_integer_resource("horizontalSpacing", "Spacing", 5);
2328db30ca8Sthorpej   d->w3.verticalSpacing =
2338db30ca8Sthorpej      get_integer_resource("verticalSpacing", "Spacing", 6);
2348db30ca8Sthorpej
2358db30ca8Sthorpej   if (2 == app->argc) {
2368db30ca8Sthorpej      d->label.text = strdup(app->argv[1]);
2378db30ca8Sthorpej   } else {
2388db30ca8Sthorpej      d->label.text =
2398db30ca8Sthorpej	 getStringResourceWithDefault("dialog.label", "Dialog.Label",
2408db30ca8Sthorpej				      "Please enter your authentication passphrase:");
2418db30ca8Sthorpej   }
2428db30ca8Sthorpej   d->label.font = getFontResource(app, "dialog.font", "Dialog.Font");
2438db30ca8Sthorpej   calcLabelTextExtents(&(d->label));
2448db30ca8Sthorpej   d->label.w.foreground = d->w3.w.foreground;
2458db30ca8Sthorpej   d->label.w.background = d->w3.w.background;
2468db30ca8Sthorpej
2478db30ca8Sthorpej   d->okButton.w3.w.foreground =
2488db30ca8Sthorpej      get_pixel_resource("okButton.foreground", "Button.Foreground",
2498db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2508db30ca8Sthorpej   d->okButton.w3.w.background =
2518db30ca8Sthorpej      get_pixel_resource("okButton.background", "Button.Background",
2528db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
2538db30ca8Sthorpej   d->okButton.w3.topShadowColor =
2548db30ca8Sthorpej      get_pixel_resource("okButton.topShadowColor", "Button.TopShadowColor",
2558db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
2568db30ca8Sthorpej   d->okButton.w3.bottomShadowColor =
2578db30ca8Sthorpej      get_pixel_resource("okButton.bottomShadowColor",
2588db30ca8Sthorpej			 "Button.BottomShadowColor",
2598db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2608db30ca8Sthorpej   d->okButton.w3.shadowThickness =
2618db30ca8Sthorpej      get_integer_resource("okButton.shadowThickness",
2628db30ca8Sthorpej			   "Button.ShadowThickness", 2);
2638db30ca8Sthorpej   d->okButton.w3.borderColor =
2648db30ca8Sthorpej      get_pixel_resource("okButton.borderColor", "Button.BorderColor",
2658db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2668db30ca8Sthorpej   d->okButton.w3.borderWidth =
2678db30ca8Sthorpej      get_integer_resource("okButton.borderWidth", "Button.BorderWidth", 1);
2688db30ca8Sthorpej   d->okButton.w3.horizontalSpacing =
2698db30ca8Sthorpej      get_integer_resource("okButton.horizontalSpacing", "Button.Spacing", 4);
2708db30ca8Sthorpej   d->okButton.w3.verticalSpacing =
2718db30ca8Sthorpej      get_integer_resource("okButton.verticalSpacing", "Button.Spacing", 2);
2728db30ca8Sthorpej   d->okButton.label.text =
2738db30ca8Sthorpej      getStringResourceWithDefault("okButton.label", "Button.Label", "OK");
2748db30ca8Sthorpej   d->okButton.label.font =
2758db30ca8Sthorpej      getFontResource(app, "okButton.font", "Button.Font");
2768db30ca8Sthorpej   calcButtonExtents(&(d->okButton));
2778db30ca8Sthorpej   d->okButton.label.w.foreground = d->okButton.w3.w.foreground;
2788db30ca8Sthorpej   d->okButton.label.w.background = d->okButton.w3.w.background;
2798db30ca8Sthorpej
2808db30ca8Sthorpej   d->cancelButton.w3.w.foreground =
2818db30ca8Sthorpej      get_pixel_resource("cancelButton.foreground", "Button.Foreground",
2828db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2838db30ca8Sthorpej   d->cancelButton.w3.w.background =
2848db30ca8Sthorpej      get_pixel_resource("cancelButton.background", "Button.Background",
2858db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
2868db30ca8Sthorpej   d->cancelButton.w3.topShadowColor =
2878db30ca8Sthorpej      get_pixel_resource("cancelButton.topShadowColor",
2888db30ca8Sthorpej			 "Button.TopShadowColor",
2898db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
2908db30ca8Sthorpej   d->cancelButton.w3.bottomShadowColor =
2918db30ca8Sthorpej      get_pixel_resource("cancelButton.bottomShadowColor",
2928db30ca8Sthorpej			 "Button.BottomShadowColor",
2938db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
2948db30ca8Sthorpej   d->cancelButton.w3.shadowThickness =
2958db30ca8Sthorpej      get_integer_resource("cancelButton.shadowThickness",
2968db30ca8Sthorpej			   "Button.ShadowThickness", 2);
2978db30ca8Sthorpej   d->cancelButton.w3.borderColor =
2988db30ca8Sthorpej      get_pixel_resource("cancelButton.borderColor", "Button.BorderColor",
2998db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
3008db30ca8Sthorpej   d->cancelButton.w3.borderWidth =
3018db30ca8Sthorpej      get_integer_resource("cancelButton.borderWidth", "Button.BorderWidth",
3028db30ca8Sthorpej			   1);
3038db30ca8Sthorpej   d->cancelButton.w3.horizontalSpacing =
3048db30ca8Sthorpej      get_integer_resource("cancelButton.horizontalSpacing", "Button.Spacing",
3058db30ca8Sthorpej			   4);
3068db30ca8Sthorpej   d->cancelButton.w3.verticalSpacing =
3078db30ca8Sthorpej      get_integer_resource("cancelButton.verticalSpacing", "Button.Spacing",
3088db30ca8Sthorpej			   2);
3098db30ca8Sthorpej   d->cancelButton.label.text =
3108db30ca8Sthorpej      getStringResourceWithDefault("cancelButton.label", "Button.Label",
3118db30ca8Sthorpej				   "Cancel");
3128db30ca8Sthorpej   d->cancelButton.label.font =
3138db30ca8Sthorpej      getFontResource(app, "cancelButton.font", "Button.Font");
3148db30ca8Sthorpej   calcButtonExtents(&(d->cancelButton));
3158db30ca8Sthorpej   d->cancelButton.label.w.foreground = d->cancelButton.w3.w.foreground;
3168db30ca8Sthorpej   d->cancelButton.label.w.background = d->cancelButton.w3.w.background;
3178db30ca8Sthorpej
3188db30ca8Sthorpej   balanceButtonExtents(&(d->okButton), &(d->cancelButton));
3198db30ca8Sthorpej
3208db30ca8Sthorpej   d->indicator.w3.w.foreground =
3218db30ca8Sthorpej      get_pixel_resource("indicator.foreground", "Indicator.Foreground",
3228db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
3238db30ca8Sthorpej   d->indicator.w3.w.background =
3248db30ca8Sthorpej      get_pixel_resource("indicator.background", "Indicator.Background",
3258db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
3268db30ca8Sthorpej   d->indicator.w3.w.width =
3278db30ca8Sthorpej      get_integer_resource("indicator.width", "Indicator.Width", 15);
3288db30ca8Sthorpej   d->indicator.w3.w.height =
3298db30ca8Sthorpej      get_integer_resource("indicator.height", "Indicator.Height", 7);
3308db30ca8Sthorpej   d->indicator.w3.topShadowColor =
3318db30ca8Sthorpej      get_pixel_resource("indicator.topShadowColor",
3328db30ca8Sthorpej			 "Indicator.TopShadowColor",
3338db30ca8Sthorpej			 app->dpy, app->colormap, app->white);
3348db30ca8Sthorpej   d->indicator.w3.bottomShadowColor =
3358db30ca8Sthorpej      get_pixel_resource("indicator.bottomShadowColor",
3368db30ca8Sthorpej			 "Indicator.BottomShadowColor",
3378db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
3388db30ca8Sthorpej   d->indicator.w3.shadowThickness =
3398db30ca8Sthorpej      get_integer_resource("indicator.shadowThickness",
3408db30ca8Sthorpej			   "Indicator.ShadowThickness", 2);
3418db30ca8Sthorpej   d->indicator.w3.borderColor =
3428db30ca8Sthorpej      get_pixel_resource("indicator.borderColor", "Indicator.BorderColor",
3438db30ca8Sthorpej			 app->dpy, app->colormap, app->black);
3448db30ca8Sthorpej   d->indicator.w3.borderWidth =
3458db30ca8Sthorpej      get_integer_resource("indicator.borderWidth", "Indicator.BorderWidth",
3468db30ca8Sthorpej			   0);
3478db30ca8Sthorpej   d->indicator.w3.horizontalSpacing =
3488db30ca8Sthorpej      get_integer_resource("indicator.horizontalSpacing", "Indicator.Spacing",
3498db30ca8Sthorpej			   2);
3508db30ca8Sthorpej   d->indicator.w3.verticalSpacing =
3518db30ca8Sthorpej      get_integer_resource("indicator.verticalSpacing", "Indicator.Spacing",
3528db30ca8Sthorpej			   4);
3538db30ca8Sthorpej   d->indicator.minimumCount =
3548db30ca8Sthorpej      get_integer_resource("indicator.minimumCount", "Indicator.MinimumCount",
3558db30ca8Sthorpej			   8);
3568db30ca8Sthorpej   d->indicator.maximumCount =
3578db30ca8Sthorpej      get_integer_resource("indicator.maximumCount", "Indicator.MaximumCount",
3588db30ca8Sthorpej			   24);
3598db30ca8Sthorpej   d->indicator.w3.interiorWidth = d->indicator.w3.w.width;
3608db30ca8Sthorpej   d->indicator.w3.interiorHeight = d->indicator.w3.w.height;
3618db30ca8Sthorpej   d->indicator.w3.w.width += (2 * d->indicator.w3.shadowThickness);
3628db30ca8Sthorpej   d->indicator.w3.w.width += (2 * d->indicator.w3.borderWidth);
3638db30ca8Sthorpej   d->indicator.w3.w.height += (2 * d->indicator.w3.shadowThickness);
3648db30ca8Sthorpej   d->indicator.w3.w.height += (2 * d->indicator.w3.borderWidth);
3658db30ca8Sthorpej   {
3668db30ca8Sthorpej      /* Make sure the indicators can all fit on the screen.
3678db30ca8Sthorpej       * 80% of the screen width seems fine.
3688db30ca8Sthorpej       */
3698db30ca8Sthorpej      Dimension maxWidth = (WidthOfScreen(app->screen) * 8 / 10);
3708db30ca8Sthorpej      Dimension extraSpace = ((2 * d->w3.horizontalSpacing) +
3718db30ca8Sthorpej			      (2 * d->w3.shadowThickness));
3728db30ca8Sthorpej
3738db30ca8Sthorpej      if (d->indicator.maximumCount < 8) {
3748db30ca8Sthorpej	 d->indicator.maximumCount = 8;
3758db30ca8Sthorpej      }
3768db30ca8Sthorpej      if (((d->indicator.maximumCount * d->indicator.w3.w.width) +
3778db30ca8Sthorpej	   ((d->indicator.maximumCount - 1) *
3788db30ca8Sthorpej	    d->indicator.w3.horizontalSpacing) + extraSpace) > maxWidth) {
3798db30ca8Sthorpej	 d->indicator.maximumCount =
3808db30ca8Sthorpej	    ((maxWidth - extraSpace - d->indicator.w3.w.width) /
3818db30ca8Sthorpej	     (d->indicator.w3.w.width + d->indicator.w3.horizontalSpacing))
3828db30ca8Sthorpej	    + 1;
3838db30ca8Sthorpej      }
3848db30ca8Sthorpej      if (d->indicator.minimumCount <= 6) {
3858db30ca8Sthorpej	 d->indicator.minimumCount = 6;
3868db30ca8Sthorpej      }
3878db30ca8Sthorpej      if (d->indicator.minimumCount > d->indicator.maximumCount) {
3888db30ca8Sthorpej	 d->indicator.minimumCount = d->indicator.maximumCount;
3898db30ca8Sthorpej      }
3908db30ca8Sthorpej   }
3918db30ca8Sthorpej
3928db30ca8Sthorpej   {
3938db30ca8Sthorpej      /* Calculate the width and horizontal position of things. */
3948db30ca8Sthorpej      Dimension labelAreaWidth;
3958db30ca8Sthorpej      Dimension buttonAreaWidth;
3968db30ca8Sthorpej      Dimension indicatorAreaWidth;
3978db30ca8Sthorpej      Dimension extraIndicatorSpace;
3988db30ca8Sthorpej      Dimension singleIndicatorSpace;
3998db30ca8Sthorpej      Dimension interButtonSpace;
4008db30ca8Sthorpej      Dimension w;
4018db30ca8Sthorpej      Position leftX;
4028db30ca8Sthorpej      int i;
4038db30ca8Sthorpej
4048db30ca8Sthorpej      labelAreaWidth = d->label.w.width + (2 * d->w3.horizontalSpacing);
4058db30ca8Sthorpej      buttonAreaWidth = ((3 * d->w3.horizontalSpacing) +
4068db30ca8Sthorpej			 d->okButton.w3.w.width +
4078db30ca8Sthorpej			 d->cancelButton.w3.w.width);
4088db30ca8Sthorpej      w = MAX(labelAreaWidth, buttonAreaWidth);
4098db30ca8Sthorpej      extraIndicatorSpace = ((2 * d->w3.horizontalSpacing) +
4108db30ca8Sthorpej			     d->indicator.w3.w.width);
4118db30ca8Sthorpej      singleIndicatorSpace = (d->indicator.w3.w.width +
4128db30ca8Sthorpej			      d->indicator.w3.horizontalSpacing);
4138db30ca8Sthorpej      d->indicator.count = ((w - extraIndicatorSpace) / singleIndicatorSpace);
4148db30ca8Sthorpej      d->indicator.current = 0;
4158db30ca8Sthorpej      d->indicator.count++; /* For gatepost indicator in extra space. */
4168db30ca8Sthorpej      if (((w - extraIndicatorSpace) % singleIndicatorSpace) >
4178db30ca8Sthorpej	  (singleIndicatorSpace / 2)) {
4188db30ca8Sthorpej	 d->indicator.count++;
4198db30ca8Sthorpej      }
4208db30ca8Sthorpej      if (d->indicator.count < d->indicator.minimumCount) {
4218db30ca8Sthorpej	 d->indicator.count = d->indicator.minimumCount;
4228db30ca8Sthorpej      }
4238db30ca8Sthorpej      if (d->indicator.count > d->indicator.maximumCount) {
4248db30ca8Sthorpej	 d->indicator.count = d->indicator.maximumCount;
4258db30ca8Sthorpej      }
4268db30ca8Sthorpej      indicatorAreaWidth = ((singleIndicatorSpace * (d->indicator.count - 1)) +
4278db30ca8Sthorpej			    extraIndicatorSpace);
4288db30ca8Sthorpej      d->w3.interiorWidth = MAX(w, indicatorAreaWidth);
4298db30ca8Sthorpej      d->w3.w.width = d->w3.interiorWidth + (2 * d->w3.shadowThickness);
4308db30ca8Sthorpej
4318db30ca8Sthorpej      leftX = (d->w3.w.width - d->label.w.width) / 2;
4328db30ca8Sthorpej      d->label.w.x = leftX;
4338db30ca8Sthorpej
4348db30ca8Sthorpej      leftX = ((d->w3.w.width -
4358db30ca8Sthorpej	       (d->indicator.count * d->indicator.w3.w.width) -
4368db30ca8Sthorpej	       ((d->indicator.count - 1) * d->indicator.w3.horizontalSpacing))
4378db30ca8Sthorpej	       / 2);
4388db30ca8Sthorpej      {
4398db30ca8Sthorpej	 int n = d->indicator.count * sizeof(IndicatorElement);
4408db30ca8Sthorpej	 d->indicators = malloc(n);
4418db30ca8Sthorpej	 if (NULL == d->indicators) {
4428db30ca8Sthorpej	    destroyDialog(app);
4438db30ca8Sthorpej	    outOfMemory(app, __LINE__);
4448db30ca8Sthorpej	 }
4458db30ca8Sthorpej	 memset(d->indicators, 0, n);
4468db30ca8Sthorpej      }
4478db30ca8Sthorpej      d->indicators[0].parent = &(d->indicator);
4488db30ca8Sthorpej      d->indicators[0].w.x = d->indicator.w3.w.x = leftX;
4498db30ca8Sthorpej      d->indicators[0].w.width = d->indicator.w3.w.width;
4508db30ca8Sthorpej      d->indicators[0].isLit = False;
4518db30ca8Sthorpej      for (i = 1; i < d->indicator.count; i++) {
4528db30ca8Sthorpej	 d->indicators[i].parent = &(d->indicator);
4538db30ca8Sthorpej	 d->indicators[i].w.x = (d->indicators[i - 1].w.x +
4548db30ca8Sthorpej				 d->indicator.w3.w.width +
4558db30ca8Sthorpej				 d->indicator.w3.horizontalSpacing);
4568db30ca8Sthorpej	 d->indicators[i].w.width = d->indicator.w3.w.width;
4578db30ca8Sthorpej	 d->indicators[i].isLit = False;
4588db30ca8Sthorpej      }
4598db30ca8Sthorpej      interButtonSpace = ((d->w3.interiorWidth - d->okButton.w3.w.width -
4608db30ca8Sthorpej			   d->cancelButton.w3.w.width) / 3);
4618db30ca8Sthorpej      d->okButton.w3.w.x = interButtonSpace + d->w3.shadowThickness;
4628db30ca8Sthorpej      d->cancelButton.w3.w.x = (d->okButton.w3.w.x + d->okButton.w3.w.width +
4638db30ca8Sthorpej				interButtonSpace);
4648db30ca8Sthorpej   }
4658db30ca8Sthorpej   {
4668db30ca8Sthorpej      /* Calculate the height and vertical position of things. */
4678db30ca8Sthorpej      int i;
4688db30ca8Sthorpej
4698db30ca8Sthorpej      d->w3.interiorHeight = ((4 * d->w3.verticalSpacing) +
4708db30ca8Sthorpej			      (2 * d->indicator.w3.verticalSpacing) +
4718db30ca8Sthorpej			      d->label.w.height +
4728db30ca8Sthorpej			      d->indicator.w3.w.height +
4738db30ca8Sthorpej			      d->okButton.w3.w.height);
4748db30ca8Sthorpej      d->w3.w.height = d->w3.interiorHeight + (2 * d->w3.shadowThickness);
4758db30ca8Sthorpej      d->label.w.y = (d->w3.shadowThickness + d->w3.verticalSpacing +
4768db30ca8Sthorpej		      d->label.ascent);
4778db30ca8Sthorpej      d->indicator.w3.w.y = (d->label.w.y + d->label.descent +
4788db30ca8Sthorpej			     d->w3.verticalSpacing +
4798db30ca8Sthorpej			     d->indicator.w3.verticalSpacing);
4808db30ca8Sthorpej      for (i = 0; i < d->indicator.count; i++) {
4818db30ca8Sthorpej	 d->indicators[i].w.y = d->indicator.w3.w.y;
4828db30ca8Sthorpej	 d->indicators[i].w.height = d->indicator.w3.w.height;
4838db30ca8Sthorpej      }
4848db30ca8Sthorpej      d->okButton.w3.w.y = d->cancelButton.w3.w.y =
4858db30ca8Sthorpej	 (d->indicator.w3.w.y + d->indicator.w3.w.height +
4868db30ca8Sthorpej	  d->w3.verticalSpacing + d->indicator.w3.verticalSpacing);
4878db30ca8Sthorpej   }
4888db30ca8Sthorpej   calcButtonLabelPosition(&(d->okButton));
4898db30ca8Sthorpej   calcButtonLabelPosition(&(d->cancelButton));
4908db30ca8Sthorpej
4918db30ca8Sthorpej   d->w3.w.x = (WidthOfScreen(app->screen) - d->w3.w.width) / 2;
4928db30ca8Sthorpej   d->w3.w.y = (HeightOfScreen(app->screen) - d->w3.w.height) / 3;
4938db30ca8Sthorpej
4948db30ca8Sthorpej   app->dialog = d;
4958db30ca8Sthorpej}
4968db30ca8Sthorpej
4978db30ca8Sthorpejvoid destroyDialog(AppInfo *app)
4988db30ca8Sthorpej{
4998db30ca8Sthorpej   DialogInfo *d = app->dialog;
5008db30ca8Sthorpej
5018db30ca8Sthorpej   freeIf(d->title);
5028db30ca8Sthorpej   freeIf(d->label.text);
5038db30ca8Sthorpej   freeIf(d->okButton.label.text);
5048db30ca8Sthorpej   freeIf(d->cancelButton.label.text);
5058db30ca8Sthorpej   freeIf(d->indicators);
5068db30ca8Sthorpej
5078db30ca8Sthorpej   freeFontIf(app, d->label.font);
5088db30ca8Sthorpej   freeFontIf(app, d->okButton.label.font);
5098db30ca8Sthorpej   freeFontIf(app, d->cancelButton.label.font);
5108db30ca8Sthorpej
5118db30ca8Sthorpej   XFree(d->sizeHints);
5128db30ca8Sthorpej   XFree(d->wmHints);
5138db30ca8Sthorpej   XFree(d->classHints);
5148db30ca8Sthorpej   XFree(d->windowName.value);
5158db30ca8Sthorpej
5168db30ca8Sthorpej   freeIf(d);
5178db30ca8Sthorpej}
5188db30ca8Sthorpej
5198db30ca8Sthorpejvoid createDialogWindow(AppInfo *app)
5208db30ca8Sthorpej{
5218db30ca8Sthorpej   XSetWindowAttributes attr;
5228db30ca8Sthorpej   unsigned long attrMask = 0;
5238db30ca8Sthorpej   DialogInfo *d = app->dialog;
5248db30ca8Sthorpej
5258db30ca8Sthorpej   attr.background_pixel = d->w3.w.background;
5268db30ca8Sthorpej   attrMask |= CWBackPixel;
5278db30ca8Sthorpej   attr.border_pixel = d->w3.borderColor;
5288db30ca8Sthorpej   attrMask |= CWBorderPixel;
5298db30ca8Sthorpej   attr.cursor = None;
5308db30ca8Sthorpej   attrMask |= CWCursor;
5318db30ca8Sthorpej   attr.event_mask = 0;
5328db30ca8Sthorpej   attr.event_mask |= ExposureMask;
5338db30ca8Sthorpej   attr.event_mask |= ButtonPressMask;
5348db30ca8Sthorpej   attr.event_mask |= ButtonReleaseMask;
5358db30ca8Sthorpej   attr.event_mask |= KeyPressMask;
5368db30ca8Sthorpej   attrMask |= CWEventMask;
5378db30ca8Sthorpej
5388db30ca8Sthorpej   d->dialogWindow = XCreateWindow(app->dpy, app->rootWindow,
5398db30ca8Sthorpej				   d->w3.w.x, d->w3.w.y,
5408db30ca8Sthorpej				   d->w3.w.width, d->w3.w.height,
5418db30ca8Sthorpej				   d->w3.borderWidth,
5428db30ca8Sthorpej				   DefaultDepthOfScreen(app->screen),
5438db30ca8Sthorpej				   InputOutput,
5448db30ca8Sthorpej				   DefaultVisualOfScreen(app->screen),
5458db30ca8Sthorpej				   attrMask, &attr);
5468db30ca8Sthorpej
5478db30ca8Sthorpej   d->sizeHints = XAllocSizeHints();
5488db30ca8Sthorpej   if (!(d->sizeHints)) {
5498db30ca8Sthorpej      destroyDialog(app);
5508db30ca8Sthorpej      outOfMemory(app, __LINE__);
5518db30ca8Sthorpej   }
5528db30ca8Sthorpej   d->sizeHints->flags = 0;
5538db30ca8Sthorpej   d->sizeHints->flags |= PPosition;
5548db30ca8Sthorpej   d->sizeHints->flags |= PSize;
5558db30ca8Sthorpej   d->sizeHints->min_width = d->w3.w.width;
5568db30ca8Sthorpej   d->sizeHints->min_height = d->w3.w.height;
5578db30ca8Sthorpej   d->sizeHints->flags |= PMinSize;
5588db30ca8Sthorpej   d->sizeHints->max_width = d->w3.w.width;
5598db30ca8Sthorpej   d->sizeHints->max_height = d->w3.w.height;
5608db30ca8Sthorpej   d->sizeHints->flags |= PMaxSize;
5618db30ca8Sthorpej   d->sizeHints->base_width = d->w3.w.width;
5628db30ca8Sthorpej   d->sizeHints->base_height = d->w3.w.height;
5638db30ca8Sthorpej   d->sizeHints->flags |= PBaseSize;
5648db30ca8Sthorpej
5658db30ca8Sthorpej   d->wmHints = XAllocWMHints();
5668db30ca8Sthorpej   if (!(d->wmHints)) {
5678db30ca8Sthorpej      destroyDialog(app);
5688db30ca8Sthorpej      outOfMemory(app, __LINE__);
5698db30ca8Sthorpej   }
5708db30ca8Sthorpej   d->wmHints->flags = 0;
5718db30ca8Sthorpej   d->wmHints->input = True;
5728db30ca8Sthorpej   d->wmHints->flags |= InputHint;
5738db30ca8Sthorpej   d->wmHints->initial_state = NormalState;
5748db30ca8Sthorpej   d->wmHints->flags |= StateHint;
5758db30ca8Sthorpej
5768db30ca8Sthorpej   d->classHints = XAllocClassHint();
5778db30ca8Sthorpej   if (!(d->classHints)) {
5788db30ca8Sthorpej      destroyDialog(app);
5798db30ca8Sthorpej      outOfMemory(app, __LINE__);
5808db30ca8Sthorpej   }
5818db30ca8Sthorpej   d->classHints->res_name = app->appName;
5828db30ca8Sthorpej   d->classHints->res_class = app->appClass;
5838db30ca8Sthorpej
5848db30ca8Sthorpej   if (!XStringListToTextProperty(&(d->title), 1, &(d->windowName))) {
5858db30ca8Sthorpej      destroyDialog(app);
5868db30ca8Sthorpej      outOfMemory(app, __LINE__);
5878db30ca8Sthorpej   }
5888db30ca8Sthorpej   XSetWMProperties(app->dpy, d->dialogWindow, &(d->windowName), NULL,
5898db30ca8Sthorpej		    app->argv, app->argc, d->sizeHints,
5908db30ca8Sthorpej		    d->wmHints, d->classHints);
5918db30ca8Sthorpej   XSetTransientForHint(app->dpy, d->dialogWindow, d->dialogWindow);
5928db30ca8Sthorpej
5938db30ca8Sthorpej   app->wmDeleteWindowAtom = XInternAtom(app->dpy, "WM_DELETE_WINDOW", False);
5948db30ca8Sthorpej   XSetWMProtocols(app->dpy, d->dialogWindow, &(app->wmDeleteWindowAtom), 1);
5958db30ca8Sthorpej}
5968db30ca8Sthorpej
5978db30ca8Sthorpejvoid createGCs(AppInfo *app)
5988db30ca8Sthorpej{
5998db30ca8Sthorpej   DialogInfo *d = app->dialog;
6008db30ca8Sthorpej
6018db30ca8Sthorpej   XGCValues gcv;
6028db30ca8Sthorpej   unsigned long gcvMask;
6038db30ca8Sthorpej
6048db30ca8Sthorpej   gcvMask = 0;
6058db30ca8Sthorpej   gcv.foreground = d->w3.w.background;
6068db30ca8Sthorpej   gcvMask |= GCForeground;
6078db30ca8Sthorpej   gcv.fill_style = FillSolid;
6088db30ca8Sthorpej   gcvMask |= GCFillStyle;
6098db30ca8Sthorpej   app->fillGC = XCreateGC(app->dpy, app->rootWindow, gcvMask, &gcv);
6108db30ca8Sthorpej
6118db30ca8Sthorpej   gcvMask = 0;
6128db30ca8Sthorpej   gcv.foreground = d->w3.borderColor;
6138db30ca8Sthorpej   gcvMask |= GCForeground;
6148db30ca8Sthorpej   gcv.line_width = d->w3.borderWidth;
6158db30ca8Sthorpej   gcvMask |= GCLineWidth;
6168db30ca8Sthorpej   gcv.line_style = LineSolid;
6178db30ca8Sthorpej   gcvMask |= GCLineStyle;
6188db30ca8Sthorpej   gcv.cap_style = CapButt;
6198db30ca8Sthorpej   gcvMask |= GCCapStyle;
6208db30ca8Sthorpej   gcv.join_style = JoinMiter;
6218db30ca8Sthorpej   gcvMask |= GCJoinStyle;
6228db30ca8Sthorpej   app->borderGC = XCreateGC(app->dpy, app->rootWindow, gcvMask, &gcv);
6238db30ca8Sthorpej
6248db30ca8Sthorpej   gcvMask = 0;
6258db30ca8Sthorpej   gcv.foreground = d->label.w.foreground;
6268db30ca8Sthorpej   gcvMask |= GCForeground;
6278db30ca8Sthorpej   gcv.background = d->label.w.background;
6288db30ca8Sthorpej   gcvMask |= GCBackground;
6298db30ca8Sthorpej   gcv.font = d->label.font->fid;
6308db30ca8Sthorpej   gcvMask |= GCFont;
6318db30ca8Sthorpej   app->textGC = XCreateGC(app->dpy, app->rootWindow, gcvMask, &gcv);
6328db30ca8Sthorpej
6338db30ca8Sthorpej   gcvMask = 0;
6348db30ca8Sthorpej   gcv.foreground = d->indicator.w3.w.foreground;
6358db30ca8Sthorpej   gcvMask |= GCForeground;
6368db30ca8Sthorpej   gcv.fill_style = FillSolid;
6378db30ca8Sthorpej   gcvMask |= GCFillStyle;
6388db30ca8Sthorpej   app->brightGC = XCreateGC(app->dpy, app->rootWindow, gcvMask, &gcv);
6398db30ca8Sthorpej
6408db30ca8Sthorpej   gcvMask = 0;
6418db30ca8Sthorpej   gcv.foreground = d->indicator.w3.w.background;
6428db30ca8Sthorpej   gcvMask |= GCForeground;
6438db30ca8Sthorpej   gcv.fill_style = FillSolid;
6448db30ca8Sthorpej   gcvMask |= GCFillStyle;
6458db30ca8Sthorpej   app->dimGC = XCreateGC(app->dpy, app->rootWindow, gcvMask, &gcv);
6468db30ca8Sthorpej}
6478db30ca8Sthorpej
6488db30ca8Sthorpejvoid destroyGCs(AppInfo *app)
6498db30ca8Sthorpej{
6508db30ca8Sthorpej   XFreeGC(app->dpy, app->fillGC);
6518db30ca8Sthorpej   XFreeGC(app->dpy, app->borderGC);
6528db30ca8Sthorpej   XFreeGC(app->dpy, app->textGC);
6538db30ca8Sthorpej   XFreeGC(app->dpy, app->brightGC);
6548db30ca8Sthorpej   XFreeGC(app->dpy, app->dimGC);
6558db30ca8Sthorpej}
6568db30ca8Sthorpej
6578db30ca8Sthorpejvoid paintLabel(AppInfo *app, Drawable draw, LabelInfo label)
6588db30ca8Sthorpej{
6598db30ca8Sthorpej   if (!(label.text)) {
6608db30ca8Sthorpej      return;
6618db30ca8Sthorpej   }
6628db30ca8Sthorpej   XSetForeground(app->dpy, app->textGC, label.w.foreground);
6638db30ca8Sthorpej   XSetBackground(app->dpy, app->textGC, label.w.background);
6648db30ca8Sthorpej   XSetFont(app->dpy, app->textGC, label.font->fid);
6658db30ca8Sthorpej   XDrawString(app->dpy, draw, app->textGC, label.w.x, label.w.y, label.text,
6668db30ca8Sthorpej	       label.textLength);
6678db30ca8Sthorpej}
6688db30ca8Sthorpej
6698db30ca8Sthorpejvoid paintButton(AppInfo *app, Drawable draw, ButtonInfo button)
6708db30ca8Sthorpej{
6718db30ca8Sthorpej   Position x;
6728db30ca8Sthorpej   Position y;
6738db30ca8Sthorpej   Dimension width;
6748db30ca8Sthorpej   Dimension height;
6758db30ca8Sthorpej
6768db30ca8Sthorpej   if (button.w3.borderWidth > 0) {
6778db30ca8Sthorpej      XSetForeground(app->dpy, app->borderGC, button.w3.borderColor);
6788db30ca8Sthorpej      XFillRectangle(app->dpy, draw, app->borderGC, button.w3.w.x,
6798db30ca8Sthorpej		     button.w3.w.y, button.w3.w.width, button.w3.w.height);
6808db30ca8Sthorpej   }
6818db30ca8Sthorpej   if ((button.w3.shadowThickness <= 0) && (button.pressed)) {
6828db30ca8Sthorpej      Pixel tmp = button.w3.w.background;
6838db30ca8Sthorpej      button.w3.w.background = button.w3.w.foreground;
6848db30ca8Sthorpej      button.w3.w.foreground = tmp;
6858db30ca8Sthorpej      tmp = button.label.w.background;
6868db30ca8Sthorpej      button.label.w.background = button.label.w.foreground;
6878db30ca8Sthorpej      button.label.w.foreground = tmp;
6888db30ca8Sthorpej   }
6898db30ca8Sthorpej   x = (button.w3.w.x + button.w3.borderWidth);
6908db30ca8Sthorpej   y = (button.w3.w.y + button.w3.borderWidth);
6918db30ca8Sthorpej   width = (button.w3.w.width - (2 * button.w3.borderWidth));
6928db30ca8Sthorpej   height = (button.w3.w.height - (2 * button.w3.borderWidth));
6938db30ca8Sthorpej   if ((button.w3.shadowThickness > 0) && (button.pressed)) {
6948db30ca8Sthorpej      XSetForeground(app->dpy, app->fillGC, button.w3.topShadowColor);
6958db30ca8Sthorpej   } else {
6968db30ca8Sthorpej      XSetForeground(app->dpy, app->fillGC, button.w3.w.background);
6978db30ca8Sthorpej   }
6988db30ca8Sthorpej   XFillRectangle(app->dpy, draw, app->fillGC, x, y, width, height);
6998db30ca8Sthorpej   if (button.w3.shadowThickness > 0) {
7008db30ca8Sthorpej      if (button.pressed) {
7018db30ca8Sthorpej	 draw_shaded_rectangle(app->dpy, draw, x, y, width, height,
7028db30ca8Sthorpej			       button.w3.shadowThickness,
7038db30ca8Sthorpej			       button.w3.bottomShadowColor,
7048db30ca8Sthorpej			       button.w3.topShadowColor);
7058db30ca8Sthorpej      } else {
7068db30ca8Sthorpej	 draw_shaded_rectangle(app->dpy, draw, x, y, width, height,
7078db30ca8Sthorpej			       button.w3.shadowThickness,
7088db30ca8Sthorpej			       button.w3.topShadowColor,
7098db30ca8Sthorpej			       button.w3.bottomShadowColor);
7108db30ca8Sthorpej      }
7118db30ca8Sthorpej   }
7128db30ca8Sthorpej   paintLabel(app, draw, button.label);
7138db30ca8Sthorpej   if ((button.w3.shadowThickness <= 0) && (button.pressed)) {
7148db30ca8Sthorpej      Pixel tmp = button.w3.w.background;
7158db30ca8Sthorpej      button.w3.w.background = button.w3.w.foreground;
7168db30ca8Sthorpej      button.w3.w.foreground = tmp;
7178db30ca8Sthorpej      tmp = button.label.w.background;
7188db30ca8Sthorpej      button.label.w.background = button.label.w.foreground;
7198db30ca8Sthorpej      button.label.w.foreground = tmp;
7208db30ca8Sthorpej   }
7218db30ca8Sthorpej}
7228db30ca8Sthorpej
7238db30ca8Sthorpejvoid paintIndicator(AppInfo *app, Drawable draw, IndicatorElement indicator)
7248db30ca8Sthorpej{
7258db30ca8Sthorpej   Position x;
7268db30ca8Sthorpej   Position y;
7278db30ca8Sthorpej   Dimension width;
7288db30ca8Sthorpej   Dimension height;
7298db30ca8Sthorpej   GC gc = app->dimGC;
7308db30ca8Sthorpej
7318db30ca8Sthorpej   if (indicator.parent->w3.borderWidth > 0) {
7328db30ca8Sthorpej      XSetForeground(app->dpy, app->borderGC,
7338db30ca8Sthorpej		     indicator.parent->w3.borderColor);
7348db30ca8Sthorpej      XFillRectangle(app->dpy, draw, app->borderGC, indicator.w.x,
7358db30ca8Sthorpej		     indicator.w.y, indicator.w.width, indicator.w.height);
7368db30ca8Sthorpej   }
7378db30ca8Sthorpej   if (indicator.isLit) {
7388db30ca8Sthorpej      gc = app->brightGC;
7398db30ca8Sthorpej   }
7408db30ca8Sthorpej   x = (indicator.w.x + indicator.parent->w3.borderWidth);
7418db30ca8Sthorpej   y = (indicator.w.y + indicator.parent->w3.borderWidth);
7428db30ca8Sthorpej   width = (indicator.w.width - (2 * indicator.parent->w3.borderWidth));
7438db30ca8Sthorpej   height = (indicator.w.height - (2 * indicator.parent->w3.borderWidth));
7448db30ca8Sthorpej   XFillRectangle(app->dpy, draw, gc, x, y, width, height);
7458db30ca8Sthorpej   if (indicator.parent->w3.shadowThickness > 0) {
7468db30ca8Sthorpej      draw_shaded_rectangle(app->dpy, draw, x, y, width, height,
7478db30ca8Sthorpej			    indicator.parent->w3.shadowThickness,
7488db30ca8Sthorpej			    indicator.parent->w3.bottomShadowColor,
7498db30ca8Sthorpej			    indicator.parent->w3.topShadowColor);
7508db30ca8Sthorpej   }
7518db30ca8Sthorpej}
7528db30ca8Sthorpej
7538db30ca8Sthorpejvoid updateIndicatorElement(AppInfo *app, int i)
7548db30ca8Sthorpej{
7558db30ca8Sthorpej   DialogInfo *d = app->dialog;
7568db30ca8Sthorpej
7578db30ca8Sthorpej   d->indicators[i].isLit = !(d->indicators[i].isLit);
7588db30ca8Sthorpej   paintIndicator(app, d->dialogWindow, d->indicators[i]);
7598db30ca8Sthorpej}
7608db30ca8Sthorpej
7618db30ca8Sthorpejvoid updateIndicators(AppInfo *app, int condition)
7628db30ca8Sthorpej{
7638db30ca8Sthorpej   DialogInfo *d = app->dialog;
7648db30ca8Sthorpej
7658db30ca8Sthorpej   if (condition > 0) {
7668db30ca8Sthorpej      /* Move forward one. */
7678db30ca8Sthorpej      updateIndicatorElement(app, d->indicator.current);
7688db30ca8Sthorpej      if (d->indicator.current < (d->indicator.count - 1)) {
7698db30ca8Sthorpej	 (d->indicator.current)++;
7708db30ca8Sthorpej      } else {
7718db30ca8Sthorpej	 d->indicator.current = 0;
7728db30ca8Sthorpej      }
7738db30ca8Sthorpej   } else if (condition < 0) {
7748db30ca8Sthorpej      /* Move backward one. */
7758db30ca8Sthorpej      if (d->indicator.current > 0) {
7768db30ca8Sthorpej	 (d->indicator.current)--;
7778db30ca8Sthorpej      } else {
7788db30ca8Sthorpej	 d->indicator.current = d->indicator.count - 1;
7798db30ca8Sthorpej      }
7808db30ca8Sthorpej      updateIndicatorElement(app, d->indicator.current);
7818db30ca8Sthorpej   } else {
7828db30ca8Sthorpej      /* Erase them all. */
7838db30ca8Sthorpej      int i;
7848db30ca8Sthorpej
7858db30ca8Sthorpej      for (i = 0; i < d->indicator.count; i++) {
7868db30ca8Sthorpej	 d->indicators[i].isLit = False;
7878db30ca8Sthorpej	 paintIndicator(app, d->dialogWindow, d->indicators[i]);
7888db30ca8Sthorpej      }
7898db30ca8Sthorpej      d->indicator.current = 0;
7908db30ca8Sthorpej   }
7918db30ca8Sthorpej   XSync(app->dpy, False);
7928db30ca8Sthorpej}
7938db30ca8Sthorpej
7948db30ca8Sthorpejvoid paintDialog(AppInfo *app)
7958db30ca8Sthorpej{
7968db30ca8Sthorpej   DialogInfo *d = app->dialog;
7978db30ca8Sthorpej   Drawable draw = d->dialogWindow;
7988db30ca8Sthorpej   int i;
7998db30ca8Sthorpej
8008db30ca8Sthorpej   XSetForeground(app->dpy, app->fillGC, d->w3.w.background);
8018db30ca8Sthorpej   XFillRectangle(app->dpy, draw, app->fillGC, 0, 0,
8028db30ca8Sthorpej		  d->w3.w.width, d->w3.w.height);
8038db30ca8Sthorpej   if (d->w3.shadowThickness > 0) {
8048db30ca8Sthorpej      draw_shaded_rectangle(app->dpy, draw, 0, 0,
8058db30ca8Sthorpej			    d->w3.w.width, d->w3.w.height,
8068db30ca8Sthorpej			    d->w3.shadowThickness,
8078db30ca8Sthorpej			    d->w3.topShadowColor,
8088db30ca8Sthorpej			    d->w3.bottomShadowColor);
8098db30ca8Sthorpej   }
8108db30ca8Sthorpej   paintLabel(app, draw, d->label);
8118db30ca8Sthorpej   for (i = 0; i < d->indicator.count; i++) {
8128db30ca8Sthorpej      paintIndicator(app, draw, d->indicators[i]);
8138db30ca8Sthorpej   }
8148db30ca8Sthorpej   paintButton(app, draw, d->okButton);
8158db30ca8Sthorpej   paintButton(app, draw, d->cancelButton);
8168db30ca8Sthorpej   XSync(app->dpy, False);
8178db30ca8Sthorpej}
8188db30ca8Sthorpej
8198db30ca8Sthorpejvoid grabKeyboard(AppInfo *app)
8208db30ca8Sthorpej{
8218db30ca8Sthorpej   if ((!(app->grabKeyboard)) || (app->isKeyboardGrabbed)) {
8228db30ca8Sthorpej      return;
8238db30ca8Sthorpej   } else {
8248db30ca8Sthorpej      int status;
8258db30ca8Sthorpej      Window grabWindow = app->dialog->dialogWindow;
8268db30ca8Sthorpej      Bool ownerEvents = False;
8278db30ca8Sthorpej      Bool pointerMode = GrabModeAsync;
8288db30ca8Sthorpej      Bool keyboardMode = GrabModeAsync;
8298db30ca8Sthorpej
8308db30ca8Sthorpej      app->isKeyboardGrabbed = True;
8318db30ca8Sthorpej      XSync(app->dpy, False);
8328db30ca8Sthorpej      status = XGrabKeyboard(app->dpy, grabWindow, ownerEvents,
8338db30ca8Sthorpej			     pointerMode, keyboardMode, CurrentTime);
8348db30ca8Sthorpej      XSync(app->dpy, False);
8358db30ca8Sthorpej      if (GrabSuccess != status) {
8368db30ca8Sthorpej	 char *reason = "reason unknown";
8378db30ca8Sthorpej
8388db30ca8Sthorpej	 switch (status) {
8398db30ca8Sthorpej	  case AlreadyGrabbed:
8408db30ca8Sthorpej	    reason = "someone else already has the keyboard";
8418db30ca8Sthorpej	    break;
8428db30ca8Sthorpej	  case GrabFrozen:
8438db30ca8Sthorpej	    reason = "someone else has frozen the keyboard";
8448db30ca8Sthorpej	    break;
8458db30ca8Sthorpej	  case GrabInvalidTime:
8468db30ca8Sthorpej	    reason = "bad grab time [this shouldn't happen]";
8478db30ca8Sthorpej	    break;
8488db30ca8Sthorpej	  case GrabNotViewable:
8498db30ca8Sthorpej	    reason = "grab not viewable [this shouldn't happen]";
8508db30ca8Sthorpej	    break;
8518db30ca8Sthorpej	 }
8528db30ca8Sthorpej	 fprintf(stderr, "%s: Could not grab keyboard (%s)\n", app->appName);
8538db30ca8Sthorpej	 exitApp(app, EXIT_STATUS_ERROR);
8548db30ca8Sthorpej      }
8558db30ca8Sthorpej   }
8568db30ca8Sthorpej}
8578db30ca8Sthorpej
8588db30ca8Sthorpejvoid ungrabKeyboard(AppInfo *app)
8598db30ca8Sthorpej{
8608db30ca8Sthorpej   if (app->grabKeyboard) {
8618db30ca8Sthorpej      XUngrabKeyboard(app->dpy, CurrentTime);
8628db30ca8Sthorpej   }
8638db30ca8Sthorpej}
8648db30ca8Sthorpej
8658db30ca8Sthorpejvoid grabPointer(AppInfo *app)
8668db30ca8Sthorpej{
8678db30ca8Sthorpej   if ((!(app->grabPointer)) || (app->isPointerGrabbed)) {
8688db30ca8Sthorpej      return;
8698db30ca8Sthorpej   } else {
8708db30ca8Sthorpej      int status;
8718db30ca8Sthorpej      Window grabWindow = app->dialog->dialogWindow;
8728db30ca8Sthorpej      Bool ownerEvents = False;
8738db30ca8Sthorpej      unsigned int eventMask = ButtonPressMask | ButtonReleaseMask;
8748db30ca8Sthorpej      Bool pointerMode = GrabModeAsync;
8758db30ca8Sthorpej      Bool keyboardMode = GrabModeAsync;
8768db30ca8Sthorpej      Window confineTo = None;
8778db30ca8Sthorpej      Cursor cursor = None;
8788db30ca8Sthorpej
8798db30ca8Sthorpej      app->isPointerGrabbed = True;
8808db30ca8Sthorpej      XSync(app->dpy, False);
8818db30ca8Sthorpej      status = XGrabPointer(app->dpy, grabWindow, ownerEvents, eventMask,
8828db30ca8Sthorpej			    pointerMode, keyboardMode, confineTo, cursor,
8838db30ca8Sthorpej			    CurrentTime);
8848db30ca8Sthorpej      XSync(app->dpy, False);
8858db30ca8Sthorpej      if (GrabSuccess != status) {
8868db30ca8Sthorpej	 char *reason = "reason unknown";
8878db30ca8Sthorpej
8888db30ca8Sthorpej	 switch (status) {
8898db30ca8Sthorpej	  case AlreadyGrabbed:
8908db30ca8Sthorpej	    reason = "someone else already has the pointer";
8918db30ca8Sthorpej	    break;
8928db30ca8Sthorpej	  case GrabFrozen:
8938db30ca8Sthorpej	    reason = "someone else has frozen the pointer";
8948db30ca8Sthorpej	    break;
8958db30ca8Sthorpej	  case GrabInvalidTime:
8968db30ca8Sthorpej	    reason = "bad grab time [this shouldn't happen]";
8978db30ca8Sthorpej	    break;
8988db30ca8Sthorpej	  case GrabNotViewable:
8998db30ca8Sthorpej	    reason = "grab not viewable [this shouldn't happen]";
9008db30ca8Sthorpej	    break;
9018db30ca8Sthorpej	 }
9028db30ca8Sthorpej	 fprintf(stderr, "%s: Could not grab pointer (%s)\n", app->appName);
9038db30ca8Sthorpej	 exitApp(app, EXIT_STATUS_ERROR);
9048db30ca8Sthorpej      }
9058db30ca8Sthorpej   }
9068db30ca8Sthorpej}
9078db30ca8Sthorpej
9088db30ca8Sthorpejvoid ungrabPointer(AppInfo *app)
9098db30ca8Sthorpej{
9108db30ca8Sthorpej   if (app->grabPointer) {
9118db30ca8Sthorpej      XUngrabPointer(app->dpy, CurrentTime);
9128db30ca8Sthorpej   }
9138db30ca8Sthorpej}
9148db30ca8Sthorpej
9158db30ca8Sthorpejvoid grabServer(AppInfo *app)
9168db30ca8Sthorpej{
9178db30ca8Sthorpej   if ((!(app->grabServer)) || (app->isServerGrabbed)) {
9188db30ca8Sthorpej      return;
9198db30ca8Sthorpej   } else {
9208db30ca8Sthorpej      app->isServerGrabbed = True;
9218db30ca8Sthorpej      XSync(app->dpy, False);
9228db30ca8Sthorpej      XGrabServer(app->dpy);
9238db30ca8Sthorpej      XSync(app->dpy, False);
9248db30ca8Sthorpej   }
9258db30ca8Sthorpej}
9268db30ca8Sthorpej
9278db30ca8Sthorpejvoid ungrabServer(AppInfo *app)
9288db30ca8Sthorpej{
9298db30ca8Sthorpej   if (app->grabServer) {
9308db30ca8Sthorpej      XUngrabServer(app->dpy);
9318db30ca8Sthorpej   }
9328db30ca8Sthorpej}
9338db30ca8Sthorpej
9348db30ca8Sthorpejvoid cleanUp(AppInfo *app)
9358db30ca8Sthorpej{
9368db30ca8Sthorpej   XDestroyWindow(app->dpy, app->dialog->dialogWindow);
9378db30ca8Sthorpej   destroyGCs(app);
9388db30ca8Sthorpej   destroyDialog(app);
9398db30ca8Sthorpej   if (app->buf) {
9408db30ca8Sthorpej      memset(app->buf, 0, app->bufSize);
9418db30ca8Sthorpej   }
9428db30ca8Sthorpej   freeIf(app->buf);
9438db30ca8Sthorpej   ungrabPointer(app);
9448db30ca8Sthorpej   ungrabKeyboard(app);
9458db30ca8Sthorpej   ungrabServer(app);
9468db30ca8Sthorpej}
9478db30ca8Sthorpej
9488db30ca8Sthorpejvoid exitApp(AppInfo *app, int exitCode)
9498db30ca8Sthorpej{
9508db30ca8Sthorpej   cleanUp(app);
9518db30ca8Sthorpej   exit(exitCode);
9528db30ca8Sthorpej}
9538db30ca8Sthorpej
9548db30ca8Sthorpejvoid acceptAction(AppInfo *app)
9558db30ca8Sthorpej{
9568db30ca8Sthorpej   int status = append_to_buf(&(app->buf), &(app->bufSize),
9578db30ca8Sthorpej			      &(app->bufIndex), '\0');
9588db30ca8Sthorpej   if (APPEND_FAILURE == status) {
9598db30ca8Sthorpej      cleanUp(app);
9608db30ca8Sthorpej      outOfMemory(app, __LINE__);
9618db30ca8Sthorpej   }
9628db30ca8Sthorpej   fputs(app->buf, stdout);
9638db30ca8Sthorpej   fputc('\n', stdout);
9648db30ca8Sthorpej   exitApp(app, EXIT_STATUS_ACCEPT);
9658db30ca8Sthorpej}
9668db30ca8Sthorpej
9678db30ca8Sthorpejvoid cancelAction(AppInfo *app)
9688db30ca8Sthorpej{
9698db30ca8Sthorpej   exitApp(app, EXIT_STATUS_CANCEL);
9708db30ca8Sthorpej}
9718db30ca8Sthorpej
9728db30ca8Sthorpejvoid backspacePassphrase(AppInfo *app)
9738db30ca8Sthorpej{
9748db30ca8Sthorpej   if (0 >= app->bufIndex) {
9758db30ca8Sthorpej      XBell(app->dpy, 0);
9768db30ca8Sthorpej      return;
9778db30ca8Sthorpej   }
9788db30ca8Sthorpej   (app->bufIndex)--;
9798db30ca8Sthorpej   updateIndicators(app, -1);
9808db30ca8Sthorpej}
9818db30ca8Sthorpej
9828db30ca8Sthorpejvoid erasePassphrase(AppInfo *app)
9838db30ca8Sthorpej{
9848db30ca8Sthorpej   if (0 >= app->bufIndex) {
9858db30ca8Sthorpej      XBell(app->dpy, 0);
9868db30ca8Sthorpej      return;
9878db30ca8Sthorpej   }
9888db30ca8Sthorpej   updateIndicators(app, 0);
9898db30ca8Sthorpej   app->bufIndex = 0;
9908db30ca8Sthorpej}
9918db30ca8Sthorpej
9928db30ca8Sthorpejvoid addToPassphrase(AppInfo *app, char c)
9938db30ca8Sthorpej{
9948db30ca8Sthorpej   int status = append_to_buf(&(app->buf), &(app->bufSize),
9958db30ca8Sthorpej			      &(app->bufIndex), c);
9968db30ca8Sthorpej   if (APPEND_FAILURE == status) {
9978db30ca8Sthorpej      cleanUp(app);
9988db30ca8Sthorpej      outOfMemory(app, __LINE__);
9998db30ca8Sthorpej   }
10008db30ca8Sthorpej   updateIndicators(app, 1);
10018db30ca8Sthorpej}
10028db30ca8Sthorpej
10038db30ca8Sthorpejvoid handleKeyPress(AppInfo *app, XKeyEvent *event)
10048db30ca8Sthorpej{
10058db30ca8Sthorpej   char s[2];
10068db30ca8Sthorpej   int n;
10078db30ca8Sthorpej
10088db30ca8Sthorpej   if (event->send_event) {
10098db30ca8Sthorpej      /* Pay no attention to synthetic key events. */
10108db30ca8Sthorpej      return;
10118db30ca8Sthorpej   }
10128db30ca8Sthorpej   n = XLookupString(event, s, 1, NULL, NULL);
10138db30ca8Sthorpej
10148db30ca8Sthorpej   if (1 != n) {
10158db30ca8Sthorpej      return;
10168db30ca8Sthorpej   }
10178db30ca8Sthorpej   s[1] = '\0';
10188db30ca8Sthorpej   switch (s[0]) {
10198db30ca8Sthorpej    case '\010':
10208db30ca8Sthorpej    case '\177':
10218db30ca8Sthorpej      backspacePassphrase(app);
10228db30ca8Sthorpej      break;
10238db30ca8Sthorpej    case '\025':
10248db30ca8Sthorpej    case '\030':
10258db30ca8Sthorpej      erasePassphrase(app);
10268db30ca8Sthorpej      break;
10278db30ca8Sthorpej    case '\012':
10288db30ca8Sthorpej    case '\015':
10298db30ca8Sthorpej      acceptAction(app);
10308db30ca8Sthorpej      break;
10318db30ca8Sthorpej    case '\033':
10328db30ca8Sthorpej      cancelAction(app);
10338db30ca8Sthorpej      break;
10348db30ca8Sthorpej    default:
10358db30ca8Sthorpej      addToPassphrase(app, s[0]);
10368db30ca8Sthorpej      break;
10378db30ca8Sthorpej   }
10388db30ca8Sthorpej}
10398db30ca8Sthorpej
10408db30ca8SthorpejBool eventIsInsideButton(AppInfo *app, XButtonEvent *event, ButtonInfo button)
10418db30ca8Sthorpej{
10428db30ca8Sthorpej   int status = False;
10438db30ca8Sthorpej
10448db30ca8Sthorpej   if ((event->x >= (button.w3.w.x + button.w3.borderWidth)) &&
10458db30ca8Sthorpej       (event->x < (button.w3.w.x + button.w3.w.width -
10468db30ca8Sthorpej		    (2 * button.w3.borderWidth))) &&
10478db30ca8Sthorpej       (event->y >= (button.w3.w.y + button.w3.borderWidth)) &&
10488db30ca8Sthorpej       (event->y < (button.w3.w.y + button.w3.w.height -
10498db30ca8Sthorpej		    (2 * button.w3.borderWidth)))) {
10508db30ca8Sthorpej      status = True;
10518db30ca8Sthorpej   }
10528db30ca8Sthorpej   return(status);
10538db30ca8Sthorpej}
10548db30ca8Sthorpej
10558db30ca8Sthorpejvoid handleButtonPress(AppInfo *app, XButtonEvent *event)
10568db30ca8Sthorpej{
10578db30ca8Sthorpej   DialogInfo *d = app->dialog;
10588db30ca8Sthorpej
10598db30ca8Sthorpej   if (event->button != Button1) {
10608db30ca8Sthorpej      return;
10618db30ca8Sthorpej   }
10628db30ca8Sthorpej   if (ButtonPress == event->type) {
10638db30ca8Sthorpej      if (eventIsInsideButton(app, event, d->okButton)) {
10648db30ca8Sthorpej	 d->pressedButton = OK_BUTTON;
10658db30ca8Sthorpej	 d->okButton.pressed = True;
10668db30ca8Sthorpej	 paintButton(app, d->dialogWindow, d->okButton);
10678db30ca8Sthorpej      } else if (eventIsInsideButton(app, event, d->cancelButton)) {
10688db30ca8Sthorpej	 d->pressedButton = CANCEL_BUTTON;
10698db30ca8Sthorpej	 d->cancelButton.pressed = True;
10708db30ca8Sthorpej	 paintButton(app, d->dialogWindow, d->cancelButton);
10718db30ca8Sthorpej      } else {
10728db30ca8Sthorpej	 d->pressedButton = NO_BUTTON;
10738db30ca8Sthorpej      }
10748db30ca8Sthorpej   } else if (ButtonRelease == event->type) {
10758db30ca8Sthorpej      if (OK_BUTTON == d->pressedButton) {
10768db30ca8Sthorpej	 if (eventIsInsideButton(app, event, d->okButton)) {
10778db30ca8Sthorpej	    acceptAction(app);
10788db30ca8Sthorpej	 } else {
10798db30ca8Sthorpej	    d->okButton.pressed = False;
10808db30ca8Sthorpej	    paintButton(app, d->dialogWindow, d->okButton);
10818db30ca8Sthorpej	 }
10828db30ca8Sthorpej      } else if (CANCEL_BUTTON == d->pressedButton) {
10838db30ca8Sthorpej	 if (eventIsInsideButton(app, event, d->cancelButton)) {
10848db30ca8Sthorpej	    cancelAction(app);
10858db30ca8Sthorpej	 } else {
10868db30ca8Sthorpej	    d->cancelButton.pressed = False;
10878db30ca8Sthorpej	    paintButton(app, d->dialogWindow, d->cancelButton);
10888db30ca8Sthorpej	 }
10898db30ca8Sthorpej      }
10908db30ca8Sthorpej      d->pressedButton = NO_BUTTON;
10918db30ca8Sthorpej   }
10928db30ca8Sthorpej}
10938db30ca8Sthorpej
10948db30ca8Sthorpejint main(int argc, char **argv)
10958db30ca8Sthorpej{
10968db30ca8Sthorpej   AppInfo app;
10978db30ca8Sthorpej   XEvent event;
10988db30ca8Sthorpej
10998db30ca8Sthorpej   memset(&app, 0, sizeof(app));
11008db30ca8Sthorpej
11018db30ca8Sthorpej   app.argc = argc;
11028db30ca8Sthorpej   app.argv = argv;
11038db30ca8Sthorpej
11048db30ca8Sthorpej   progclass = "SshAskpass";
11058db30ca8Sthorpej   app.toplevelShell = XtAppInitialize(&(app.appContext), progclass,
11068db30ca8Sthorpej					NULL, 0, &argc, argv,
11078db30ca8Sthorpej					defaults, NULL, 0);
11088db30ca8Sthorpej   app.dpy = XtDisplay(app.toplevelShell);
11098db30ca8Sthorpej   app.screen = DefaultScreenOfDisplay(app.dpy);
11108db30ca8Sthorpej   app.rootWindow = RootWindowOfScreen(app.screen);
11118db30ca8Sthorpej   app.black = BlackPixel(app.dpy, DefaultScreen(app.dpy));
11128db30ca8Sthorpej   app.white = WhitePixel(app.dpy, DefaultScreen(app.dpy));
11138db30ca8Sthorpej   app.colormap = DefaultColormapOfScreen(app.screen);
11148db30ca8Sthorpej   app.resourceDb = XtDatabase(app.dpy);
11158db30ca8Sthorpej   XtGetApplicationNameAndClass(app.dpy, &progname, &progclass);
11168db30ca8Sthorpej   app.appName = progname;
11178db30ca8Sthorpej   app.appClass = progclass;
11188db30ca8Sthorpej   /* For resources.c. */
11198db30ca8Sthorpej   db = app.resourceDb;
11208db30ca8Sthorpej
11218db30ca8Sthorpej   {
11228db30ca8Sthorpej      struct rlimit resourceLimit;
11238db30ca8Sthorpej      int status;
11248db30ca8Sthorpej
11258db30ca8Sthorpej      status = getrlimit(RLIMIT_CORE, &resourceLimit);
11268db30ca8Sthorpej      if (-1 == status) {
11278db30ca8Sthorpej	 fprintf(stderr, "%s: getrlimit failed (%s)\n", app.appName,
11288db30ca8Sthorpej		 strerror(errno));
11298db30ca8Sthorpej	 exit(EXIT_STATUS_ERROR);
11308db30ca8Sthorpej      }
11318db30ca8Sthorpej      resourceLimit.rlim_cur = 0;
11328db30ca8Sthorpej      status = setrlimit(RLIMIT_CORE, &resourceLimit);
11338db30ca8Sthorpej      if (-1 == status) {
11348db30ca8Sthorpej	 fprintf(stderr, "%s: setrlimit failed (%s)\n", app.appName,
11358db30ca8Sthorpej		 strerror(errno));
11368db30ca8Sthorpej	 exit(EXIT_STATUS_ERROR);
11378db30ca8Sthorpej      }
11388db30ca8Sthorpej   }
11398db30ca8Sthorpej
11408db30ca8Sthorpej   createDialog(&app);
11418db30ca8Sthorpej   createGCs(&app);
11428db30ca8Sthorpej   createDialogWindow(&app);
11438db30ca8Sthorpej
11448db30ca8Sthorpej   XMapWindow(app.dpy, app.dialog->dialogWindow);
11458db30ca8Sthorpej
11468db30ca8Sthorpej   while(True) {
11478db30ca8Sthorpej      XNextEvent(app.dpy, &event);
11488db30ca8Sthorpej      switch (event.type) {
11498db30ca8Sthorpej       case Expose:
11508db30ca8Sthorpej	 grabServer(&app);
11518db30ca8Sthorpej	 grabKeyboard(&app);
11528db30ca8Sthorpej	 grabPointer(&app);
11538db30ca8Sthorpej	 if (event.xexpose.count) {
11548db30ca8Sthorpej	    break;
11558db30ca8Sthorpej	 }
11568db30ca8Sthorpej	 paintDialog(&app);
11578db30ca8Sthorpej	 break;
11588db30ca8Sthorpej       case ButtonPress:
11598db30ca8Sthorpej       case ButtonRelease:
11608db30ca8Sthorpej	 handleButtonPress(&app, &(event.xbutton));
11618db30ca8Sthorpej	 break;
11628db30ca8Sthorpej       case KeyPress:
11638db30ca8Sthorpej	 handleKeyPress(&app, &(event.xkey));
11648db30ca8Sthorpej	 break;
11658db30ca8Sthorpej       case ClientMessage:
11668db30ca8Sthorpej	 if ((32 == event.xclient.format) &&
11678db30ca8Sthorpej	     (event.xclient.data.l[0] == app.wmDeleteWindowAtom)) {
11688db30ca8Sthorpej	    cancelAction(&app);
11698db30ca8Sthorpej	 }
11708db30ca8Sthorpej	 break;
11718db30ca8Sthorpej       default:
11728db30ca8Sthorpej	 break;
11738db30ca8Sthorpej      }
11748db30ca8Sthorpej   }
11758db30ca8Sthorpej
11768db30ca8Sthorpej   fprintf(stderr, "%s: This should not happen.\n", app.appName);
11778db30ca8Sthorpej   return(EXIT_STATUS_ANOMALY);
11788db30ca8Sthorpej}
11798db30ca8Sthorpej
1180