Login.c revision 5ffd6003
1145b7b3cSmrg/*
2145b7b3cSmrg
3145b7b3cSmrgCopyright 1988, 1998  The Open Group
4145b7b3cSmrg
5145b7b3cSmrgPermission to use, copy, modify, distribute, and sell this software and its
6145b7b3cSmrgdocumentation for any purpose is hereby granted without fee, provided that
7145b7b3cSmrgthe above copyright notice appear in all copies and that both that
8145b7b3cSmrgcopyright notice and this permission notice appear in supporting
9145b7b3cSmrgdocumentation.
10145b7b3cSmrg
11145b7b3cSmrgThe above copyright notice and this permission notice shall be included
12145b7b3cSmrgin all copies or substantial portions of the Software.
13145b7b3cSmrg
14145b7b3cSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15145b7b3cSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16145b7b3cSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17145b7b3cSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18145b7b3cSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19145b7b3cSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20145b7b3cSmrgOTHER DEALINGS IN THE SOFTWARE.
21145b7b3cSmrg
22145b7b3cSmrgExcept as contained in this notice, the name of The Open Group shall
23145b7b3cSmrgnot be used in advertising or otherwise to promote the sale, use or
24145b7b3cSmrgother dealings in this Software without prior written authorization
25145b7b3cSmrgfrom The Open Group.
26145b7b3cSmrg
27145b7b3cSmrg*/
285ffd6003Smrg/*
295ffd6003Smrg * Copyright © 2006 Sun Microsystems, Inc.  All rights reserved.
30145b7b3cSmrg *
31145b7b3cSmrg * Permission is hereby granted, free of charge, to any person obtaining a
325ffd6003Smrg * copy of this software and associated documentation files (the "Software"),
335ffd6003Smrg * to deal in the Software without restriction, including without limitation
345ffd6003Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
355ffd6003Smrg * and/or sell copies of the Software, and to permit persons to whom the
365ffd6003Smrg * Software is furnished to do so, subject to the following conditions:
37145b7b3cSmrg *
385ffd6003Smrg * The above copyright notice and this permission notice (including the next
395ffd6003Smrg * paragraph) shall be included in all copies or substantial portions of the
405ffd6003Smrg * Software.
41145b7b3cSmrg *
425ffd6003Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
435ffd6003Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
445ffd6003Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
455ffd6003Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
465ffd6003Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
475ffd6003Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
485ffd6003Smrg * DEALINGS IN THE SOFTWARE.
49145b7b3cSmrg */
50145b7b3cSmrg
51145b7b3cSmrg
52145b7b3cSmrg/*
53145b7b3cSmrg * xdm - display manager daemon
54145b7b3cSmrg * Author:  Keith Packard, MIT X Consortium
55145b7b3cSmrg *
56145b7b3cSmrg * Login.c
57145b7b3cSmrg */
58145b7b3cSmrg
59578741aaSmrg#include <X11/IntrinsicP.h>
60578741aaSmrg#include <X11/StringDefs.h>
61578741aaSmrg#include <X11/keysym.h>
62578741aaSmrg#include <X11/DECkeysym.h>
63578741aaSmrg#include <X11/Xfuncs.h>
64145b7b3cSmrg
65578741aaSmrg#include <stdio.h>
66578741aaSmrg#include <ctype.h>
67578741aaSmrg#include <time.h>
68578741aaSmrg#include <string.h>
69145b7b3cSmrg
70578741aaSmrg#include "dm.h"
71578741aaSmrg#include "dm_error.h"
72578741aaSmrg#include "greet.h"
73578741aaSmrg#include "LoginP.h"
74145b7b3cSmrg
75145b7b3cSmrg#ifdef XPM
76578741aaSmrg# include <sys/stat.h>
77578741aaSmrg# include <unistd.h>
78578741aaSmrg# include <X11/Xlib.h>
79578741aaSmrg# include <X11/xpm.h>
80578741aaSmrg# include <X11/extensions/shape.h>
81145b7b3cSmrg#endif /* XPM */
82145b7b3cSmrg
83145b7b3cSmrg#include <X11/cursorfont.h>
84145b7b3cSmrg
85145b7b3cSmrg#ifdef USE_XINERAMA
86578741aaSmrg# include <X11/extensions/Xinerama.h>
87145b7b3cSmrg#endif
88145b7b3cSmrg
89145b7b3cSmrg#ifndef DEBUG
90145b7b3cSmrg# define XDM_ASSERT(a)	/* do nothing */
91145b7b3cSmrg#else
92145b7b3cSmrg# if defined(__STDC__) && __STDC_VERSION__ - 0 >= 199901L
93145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
94145b7b3cSmrg	Debug("Assertion failed in %s() at file %s line %d\n", \
95145b7b3cSmrg	      __func__, __FILE__, __LINE__); }
96145b7b3cSmrg# else
97145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
98145b7b3cSmrg	Debug("Assertion failed at file %s line %d\n", __FILE__, __LINE__); }
99145b7b3cSmrg# endif
100145b7b3cSmrg#endif
101145b7b3cSmrg
102145b7b3cSmrgstatic void RedrawFail (LoginWidget w);
103145b7b3cSmrgstatic void ResetLogin (LoginWidget w);
104145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id);
105145b7b3cSmrgstatic void EraseCursor (LoginWidget w);
106145b7b3cSmrgstatic void XorCursor (LoginWidget w);
107145b7b3cSmrg
108145b7b3cSmrg#define offset(field) XtOffsetOf(LoginRec, login.field)
109145b7b3cSmrg#define goffset(field) XtOffsetOf(WidgetRec, core.field)
110145b7b3cSmrg
111145b7b3cSmrg
112145b7b3cSmrgstatic XtResource resources[] = {
113145b7b3cSmrg    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
114145b7b3cSmrg	goffset(width), XtRImmediate,	(XtPointer) 0},
115145b7b3cSmrg    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
116145b7b3cSmrg	goffset(height), XtRImmediate,	(XtPointer) 0},
117145b7b3cSmrg    {XtNx, XtCX, XtRPosition, sizeof (Position),
118145b7b3cSmrg	goffset(x), XtRImmediate,	(XtPointer) -1},
119145b7b3cSmrg    {XtNy, XtCY, XtRPosition, sizeof (Position),
120145b7b3cSmrg	goffset(y), XtRImmediate,	(XtPointer) -1},
121578741aaSmrg#ifndef USE_XFT
122145b7b3cSmrg    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
123145b7b3cSmrg        offset(textpixel), XtRString,	XtDefaultForeground},
124145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel),
125145b7b3cSmrg        offset(promptpixel), XtRString,	XtDefaultForeground},
126145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel),
127145b7b3cSmrg        offset(greetpixel), XtRString,	XtDefaultForeground},
128145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel),
129145b7b3cSmrg	offset(failpixel), XtRString,	XtDefaultForeground},
130145b7b3cSmrg#endif
131145b7b3cSmrg
132145b7b3cSmrg#ifdef DANCING
133145b7b3cSmrg/* added by Caolan McNamara */
134145b7b3cSmrg	{XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int),
135145b7b3cSmrg	offset(lastEventTime), XtRImmediate,	(XtPointer)0},
136145b7b3cSmrg/* end (caolan) */
137145b7b3cSmrg#endif /* DANCING */
138145b7b3cSmrg
139578741aaSmrg#ifdef XPM
140145b7b3cSmrg/* added by Ivan Griffin (ivan.griffin@ul.ie) */
141145b7b3cSmrg        {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*),
142145b7b3cSmrg        offset(logoFileName), XtRImmediate, (XtPointer)0},
143145b7b3cSmrg        {XtNuseShape, XtCUseShape, XtRBoolean, sizeof(Boolean),
144145b7b3cSmrg        offset(useShape), XtRImmediate, (XtPointer) True},
145145b7b3cSmrg        {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int),
146145b7b3cSmrg        offset(logoPadding), XtRImmediate, (XtPointer) 5},
147145b7b3cSmrg/* end (ivan) */
148145b7b3cSmrg#endif /* XPM */
149145b7b3cSmrg
150145b7b3cSmrg/* added by Amit Margalit */
151145b7b3cSmrg    {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel),
152145b7b3cSmrg	offset(hipixel), XtRString,	XtDefaultForeground},
153145b7b3cSmrg    {XtNshdColor, XtCForeground, XtRPixel, sizeof (Pixel),
154145b7b3cSmrg	offset(shdpixel), XtRString,	XtDefaultForeground},
155145b7b3cSmrg    {XtNframeWidth, XtCFrameWidth, XtRInt, sizeof(int),
156145b7b3cSmrg        offset(outframewidth), XtRImmediate, (XtPointer) 1},
157145b7b3cSmrg    {XtNinnerFramesWidth, XtCFrameWidth, XtRInt, sizeof(int),
158145b7b3cSmrg        offset(inframeswidth), XtRImmediate, (XtPointer) 1},
159145b7b3cSmrg    {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int),
160145b7b3cSmrg        offset(sepwidth), XtRImmediate, (XtPointer) 1},
161145b7b3cSmrg/* end (amit) */
162145b7b3cSmrg
163578741aaSmrg#ifndef USE_XFT
164145b7b3cSmrg    {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
165145b7b3cSmrg    	offset (textFont), XtRString,	"*-new century schoolbook-medium-r-normal-*-180-*"},
166145b7b3cSmrg    {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
167145b7b3cSmrg    	offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"},
168145b7b3cSmrg    {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
169145b7b3cSmrg    	offset (greetFont), XtRString,	"*-new century schoolbook-bold-i-normal-*-240-*"},
170145b7b3cSmrg    {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
171145b7b3cSmrg	offset (failFont), XtRString,	"*-new century schoolbook-bold-r-normal-*-180-*"},
172145b7b3cSmrg#else /* USE_XFT */
173145b7b3cSmrg    {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
174145b7b3cSmrg        offset (textFace), XtRString, "Serif-18"},
175145b7b3cSmrg    {XtNpromptFace, XtCFace, XtRXftFont, sizeof (XftFont *),
176145b7b3cSmrg        offset (promptFace), XtRString, "Serif-18:bold"},
177145b7b3cSmrg    {XtNgreetFace, XtCFace, XtRXftFont, sizeof (XftFont *),
178145b7b3cSmrg        offset (greetFace), XtRString, "Serif-24:italic"},
179145b7b3cSmrg    {XtNfailFace, XtCFace, XtRXftFont, sizeof (XftFont *),
180145b7b3cSmrg        offset (failFace), XtRString, "Serif-18:bold"},
181145b7b3cSmrg    {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
182145b7b3cSmrg        offset(textcolor), XtRString,	XtDefaultForeground},
183145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRXftColor, sizeof(XftColor),
184145b7b3cSmrg        offset(promptcolor), XtRString,	XtDefaultForeground},
185145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRXftColor, sizeof(XftColor),
186145b7b3cSmrg        offset(greetcolor), XtRString,	XtDefaultForeground},
187145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRXftColor, sizeof (XftColor),
188145b7b3cSmrg	offset(failcolor), XtRString,	XtDefaultForeground},
189145b7b3cSmrg#endif
190145b7b3cSmrg    {XtNgreeting, XtCGreeting, XtRString, sizeof (char *),
191145b7b3cSmrg    	offset(greeting), XtRString, "X Window System"},
192145b7b3cSmrg    {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *),
193145b7b3cSmrg	offset(unsecure_greet), XtRString, "This is an unsecure session"},
194145b7b3cSmrg    {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *),
195145b7b3cSmrg	offset(namePrompt), XtRString, "Login:  "},
196145b7b3cSmrg    {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *),
197145b7b3cSmrg	offset(passwdPrompt), XtRString, "Password:  "},
198145b7b3cSmrg    {XtNfail, XtCFail, XtRString, sizeof (char *),
199145b7b3cSmrg	offset(failMsg), XtRString,
200145b7b3cSmrg#if defined(sun) && defined(SVR4)
201145b7b3cSmrg     "Login incorrect or not on system console if root"
202145b7b3cSmrg#else
203145b7b3cSmrg     "Login incorrect"
204145b7b3cSmrg#endif
205145b7b3cSmrg    },
206145b7b3cSmrg    {XtNchangePasswdMessage, XtCChangePasswdMessage, XtRString,
207145b7b3cSmrg	sizeof (char *), offset(passwdChangeMsg), XtRString,
208145b7b3cSmrg	(XtPointer) "Password Change Required" },
209145b7b3cSmrg    {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int),
210145b7b3cSmrg	offset(failTimeout), XtRImmediate, (XtPointer) 10},
211145b7b3cSmrg    {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer),
212145b7b3cSmrg	offset(notify_done), XtRFunction, (XtPointer) 0},
213145b7b3cSmrg    {XtNsessionArgument, XtCSessionArgument, XtRString,	sizeof (char *),
214145b7b3cSmrg	offset(sessionArg), XtRString, (XtPointer) 0 },
215145b7b3cSmrg    {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean),
216145b7b3cSmrg	offset(secure_session), XtRImmediate, (XtPointer) False },
217145b7b3cSmrg    {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean),
218145b7b3cSmrg	offset(allow_access), XtRImmediate, (XtPointer) False },
219145b7b3cSmrg    {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean),
220145b7b3cSmrg	offset(allow_null_passwd), XtRImmediate, (XtPointer) False},
221145b7b3cSmrg    {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean),
2225ffd6003Smrg	offset(allow_root_login), XtRImmediate, (XtPointer) True},
2235ffd6003Smrg    {XtNechoPasswd, XtCEchoPasswd, XtRBoolean, sizeof(Boolean),
2245ffd6003Smrg	offset(echo_passwd), XtRImmediate, (XtPointer) False}
225145b7b3cSmrg};
226145b7b3cSmrg
227145b7b3cSmrg#undef offset
228145b7b3cSmrg#undef goffset
229145b7b3cSmrg
230145b7b3cSmrg#ifdef USE_XFT
231145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Face->max_advance_width)
232145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Face->ascent)
233145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Face->descent)
234145b7b3cSmrg#else
235145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Font->max_bounds.width)
236145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Font->max_bounds.ascent)
237145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Font->max_bounds.descent)
238145b7b3cSmrg#endif
239145b7b3cSmrg
240578741aaSmrg#define TEXT_X_INC(w)		F_MAX_WIDTH(text)
241578741aaSmrg#define TEXT_Y_INC(w)		(F_ASCENT(text) + F_DESCENT(text))
242145b7b3cSmrg
243578741aaSmrg#define PROMPT_X_INC(w)	F_MAX_WIDTH(prompt)
244578741aaSmrg#define PROMPT_Y_INC(w)	(F_ASCENT(prompt) + F_DESCENT(prompt))
245145b7b3cSmrg
246578741aaSmrg#define GREET_X_INC(w)		F_MAX_WIDTH(greet)
247578741aaSmrg#define GREET_Y_INC(w)		(F_ASCENT(greet) + F_DESCENT(greet))
248145b7b3cSmrg
249578741aaSmrg#define FAIL_X_INC(w)		F_MAX_WIDTH(fail)
250578741aaSmrg#define FAIL_Y_INC(w)		(F_ASCENT(fail) + F_DESCENT(fail))
251145b7b3cSmrg
252578741aaSmrg#define Y_INC(w)	max (TEXT_Y_INC(w), PROMPT_Y_INC(w))
253145b7b3cSmrg
254145b7b3cSmrg
255578741aaSmrg#define PROMPT_TEXT(w,n) 	((w)->login.prompts[n].promptText)
256578741aaSmrg#define DEF_PROMPT_TEXT(w,n) 	((w)->login.prompts[n].defaultPrompt)
257578741aaSmrg#define VALUE_TEXT(w,n) 	((w)->login.prompts[n].valueText)
258578741aaSmrg#define VALUE_TEXT_MAX(w,n)	((w)->login.prompts[n].valueTextMax)
259578741aaSmrg#define VALUE_SHOW_START(w,n)	((w)->login.prompts[n].valueShownStart)
260578741aaSmrg#define VALUE_SHOW_END(w,n)	((w)->login.prompts[n].valueShownEnd)
261578741aaSmrg#define PROMPT_STATE(w,n) 	((w)->login.prompts[n].state)
262578741aaSmrg#define PROMPT_CURSOR(w,n)	((w)->login.prompts[n].cursor)
263145b7b3cSmrg
264578741aaSmrg#define CUR_PROMPT_CURSOR(w)	PROMPT_CURSOR(w,w->login.activePrompt)
265145b7b3cSmrg
266578741aaSmrg#define CUR_PROMPT_TEXT(w, n)	(PROMPT_TEXT(w,n) != NULL ? \
267145b7b3cSmrg				 PROMPT_TEXT(w,n) : DEF_PROMPT_TEXT(w,n))
268145b7b3cSmrg
269145b7b3cSmrg#ifdef USE_XFT
270145b7b3cSmrg
271145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##color.pixel)
272145b7b3cSmrg
273145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	XmuXftTextWidth(XtDisplay (w), \
274145b7b3cSmrg					w->login.f##Face, (FcChar8 *) m, l)
275145b7b3cSmrgstatic int
276145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len);
277145b7b3cSmrg
278145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
279145b7b3cSmrg	/* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \
280145b7b3cSmrg	XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \
281145b7b3cSmrg			x, y, (FcChar8 *) m, l)
282145b7b3cSmrg
283145b7b3cSmrg#else
284145b7b3cSmrg
285145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##pixel)
286145b7b3cSmrg
287145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	(XTextWidth (w->login.f##Font, m, l))
288145b7b3cSmrg
289145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
290145b7b3cSmrg	XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l)
291145b7b3cSmrg
292145b7b3cSmrg#endif
293145b7b3cSmrg
294145b7b3cSmrg
295578741aaSmrg#define STRING_WIDTH(f, s) 	TEXT_WIDTH (f, s, strlen(s))
296145b7b3cSmrg
297145b7b3cSmrg
298145b7b3cSmrg
299578741aaSmrg#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth)
300145b7b3cSmrg
301578741aaSmrg#define DEF_PROMPT_W(w,n) TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt)
302578741aaSmrg#define CUR_PROMPT_W(w,n)  (max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \
303145b7b3cSmrg		     TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0))
304145b7b3cSmrg
305578741aaSmrg#define MAX_DEF_PROMPT_W(w) (max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1)))
306145b7b3cSmrg
307578741aaSmrg#define GREETING(w)	((w)->login.secure_session  && !(w)->login.allow_access ?\
308145b7b3cSmrg				(w)->login.greeting : (w)->login.unsecure_greet)
309578741aaSmrg#define GREET_X(w)	((int)((w->core.width - \
310145b7b3cSmrg			     	STRING_WIDTH (greet, GREETING(w))) / 2))
311578741aaSmrg#define GREET_Y(w)	(GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
312145b7b3cSmrg#ifndef XPM
313145b7b3cSmrg# define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
314145b7b3cSmrg			      STRING_WIDTH (greet, w->login.unsecure_greet)))
315145b7b3cSmrg#else
316145b7b3cSmrg# define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
317145b7b3cSmrg			      STRING_WIDTH (greet, w->login.unsecure_greet)) \
318145b7b3cSmrg			 + w->login.logoWidth + (2*w->login.logoPadding))
319145b7b3cSmrg#endif /* XPM */
320578741aaSmrg#define PROMPT_X(w)	(2 * PROMPT_X_INC(w))
321578741aaSmrg#define PROMPT_Y(w,n)	((GREET_Y(w) + GREET_Y_INC(w) +\
322145b7b3cSmrg			  F_ASCENT(greet) + Y_INC(w)) + \
323145b7b3cSmrg			 (n * PROMPT_SPACE_Y(w)))
324578741aaSmrg#define PROMPT_W(w)	(w->core.width - (2 * TEXT_X_INC(w)))
325578741aaSmrg#define PROMPT_H(w)	(3 * Y_INC(w) / 2)
326578741aaSmrg#define VALUE_X(w,n)	(PROMPT_X(w) + CUR_PROMPT_W(w,n))
327578741aaSmrg#define PROMPT_SPACE_Y(w)	(10 * Y_INC(w) / 5)
328145b7b3cSmrg
329578741aaSmrg#define ERROR_X(w,m)	((int)(w->core.width - STRING_WIDTH (fail, m)) / 2)
330578741aaSmrg#define FAIL_X(w)	ERROR_X(w, w->login.fail)
331578741aaSmrg#define FAIL_Y(w)	(PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail))
332145b7b3cSmrg
333145b7b3cSmrg#ifndef XPM
334145b7b3cSmrg# define ERROR_W(w,m)	STRING_WIDTH (fail, m)
335145b7b3cSmrg#else
336145b7b3cSmrg# define ERROR_W(w,m)	(STRING_WIDTH (fail, m) \
337145b7b3cSmrg			 + w->login.logoWidth + (2*w->login.logoPadding))
338145b7b3cSmrg#endif /* XPM */
339145b7b3cSmrg
340578741aaSmrg#define FAIL_W(w)	max(ERROR_W(w, w->login.failMsg), \
341145b7b3cSmrg			    ERROR_W(w, w->login.passwdChangeMsg))
342145b7b3cSmrg
343578741aaSmrg#define PAD_X(w)	(2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w))))
344145b7b3cSmrg
345578741aaSmrg#define PAD_Y(w)	(max (max (Y_INC(w), GREET_Y_INC(w)),\
346145b7b3cSmrg			     FAIL_Y_INC(w)))
347578741aaSmrg
348145b7b3cSmrg#ifndef max
349145b7b3cSmrgstatic inline int max (int a, int b) { return a > b ? a : b; }
350145b7b3cSmrg#endif
351145b7b3cSmrg
352145b7b3cSmrgstatic void
353145b7b3cSmrgrealizeValue (LoginWidget w, int cursor, int promptNum, GC gc)
354145b7b3cSmrg{
3555ffd6003Smrg    loginPromptState state = PROMPT_STATE(w, promptNum);
356145b7b3cSmrg    char *text = VALUE_TEXT(w, promptNum);
357145b7b3cSmrg    int	x, y, height, width, curoff;
358145b7b3cSmrg
359145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
360145b7b3cSmrg
3615ffd6003Smrg    /* replace all password characters with asterisks */
3625ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
3635ffd6003Smrg    {
3645ffd6003Smrg	Cardinal length = strlen(text);
3655ffd6003Smrg	Cardinal i = 0;
3665ffd6003Smrg
3675ffd6003Smrg	text = XtMalloc(length + 1);
3685ffd6003Smrg
3695ffd6003Smrg	if (text == NULL)
3705ffd6003Smrg	{
3715ffd6003Smrg	    LogOutOfMem("realizeValue");
3725ffd6003Smrg	    return;
3735ffd6003Smrg	}
3745ffd6003Smrg
3755ffd6003Smrg	while (i < length)
3765ffd6003Smrg	{
3775ffd6003Smrg	    text[i++] = '*';
3785ffd6003Smrg	}
3795ffd6003Smrg
3805ffd6003Smrg	text[i] = 0;
3815ffd6003Smrg    }
3825ffd6003Smrg
383145b7b3cSmrg    x = VALUE_X (w,promptNum);
384145b7b3cSmrg    y = PROMPT_Y (w,promptNum);
385145b7b3cSmrg
386145b7b3cSmrg    height = PROMPT_H(w);
387145b7b3cSmrg    width = PROMPT_W(w) - x - 3;
388145b7b3cSmrg
389145b7b3cSmrg    height -= (w->login.inframeswidth * 2);
390145b7b3cSmrg    width -= (w->login.inframeswidth * 2);
391145b7b3cSmrg#ifdef XPM
3925ffd6003Smrg    width -= (w->login.logoWidth + (w->login.logoPadding * 2));
393145b7b3cSmrg#endif
394145b7b3cSmrg    if (cursor > VALUE_SHOW_START(w, promptNum))
395145b7b3cSmrg	curoff = TEXT_WIDTH (text, text, cursor);
396145b7b3cSmrg    else
397145b7b3cSmrg	curoff = 0;
398145b7b3cSmrg
399145b7b3cSmrg
400145b7b3cSmrg    if (gc == w->login.bgGC) {
401145b7b3cSmrg	if (curoff < width) {
402145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
403145b7b3cSmrg			    x + curoff, y - TEXT_Y_INC(w),
404145b7b3cSmrg			    width - curoff, height);
405145b7b3cSmrg	}
4065ffd6003Smrg    } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) ||
4075ffd6003Smrg	       ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)))
4085ffd6003Smrg    {
409145b7b3cSmrg	int textwidth;
410145b7b3cSmrg	int offset = max(cursor, VALUE_SHOW_START(w, promptNum));
411145b7b3cSmrg	int textlen = strlen (text + offset);
412578741aaSmrg
413145b7b3cSmrg	textwidth = TEXT_WIDTH (text, text + offset, textlen);
414145b7b3cSmrg
415145b7b3cSmrg	if (textwidth > (width - curoff)) {
416145b7b3cSmrg	    /* Recalculate amount of text that can fit in field */
417145b7b3cSmrg	    offset = VALUE_SHOW_START(w, promptNum);
418145b7b3cSmrg	    textlen = strlen (text + offset);
419145b7b3cSmrg
420145b7b3cSmrg	    while ((textlen > 0) && (textwidth > width))
421145b7b3cSmrg	    {
422145b7b3cSmrg		if (offset < PROMPT_CURSOR(w, promptNum)) {
423145b7b3cSmrg		    offset++;
424145b7b3cSmrg		}
425145b7b3cSmrg		textlen--;
426145b7b3cSmrg		textwidth = TEXT_WIDTH (text, text + offset, textlen);
427578741aaSmrg	    }
428145b7b3cSmrg
429145b7b3cSmrg	    VALUE_SHOW_START(w, promptNum) = offset;
430145b7b3cSmrg	    VALUE_SHOW_END(w, promptNum) = offset + textlen;
431145b7b3cSmrg
432145b7b3cSmrg	    /* Erase old string */
433145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC,
434145b7b3cSmrg			    x, y - TEXT_Y_INC(w), width, height);
435145b7b3cSmrg
436145b7b3cSmrg	    DRAW_STRING(text, x, y, text + offset, textlen);
437145b7b3cSmrg	} else {
438145b7b3cSmrg	    DRAW_STRING(text, x + curoff, y, text + offset, textlen);
439145b7b3cSmrg	}
440145b7b3cSmrg    }
4415ffd6003Smrg    /* free memory */
4425ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
4435ffd6003Smrg    {
4445ffd6003Smrg	XtFree(text);
4455ffd6003Smrg    }
446145b7b3cSmrg}
447145b7b3cSmrg
448145b7b3cSmrgstatic void
449145b7b3cSmrgEraseValue (LoginWidget w, int cursor, int promptNum)
450145b7b3cSmrg{
451145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.bgGC);
452145b7b3cSmrg}
453145b7b3cSmrg
454145b7b3cSmrgstatic void
455145b7b3cSmrgDrawValue (LoginWidget w, int cursor, int promptNum)
456145b7b3cSmrg{
457145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.textGC);
458145b7b3cSmrg#ifdef DANCING
459145b7b3cSmrg    /*as good a place as any Caolan begin*/
460145b7b3cSmrg    w->login.lastEventTime = time(NULL);
461145b7b3cSmrg    /*as good a place as any Caolan end*/
462145b7b3cSmrg#endif /* DANCING */
463145b7b3cSmrg}
464145b7b3cSmrg
465145b7b3cSmrgstatic void
466145b7b3cSmrgrealizeCursor (LoginWidget w, GC gc)
467145b7b3cSmrg{
468145b7b3cSmrg    int	x, y;
469145b7b3cSmrg    int height, width;
470145b7b3cSmrg
471145b7b3cSmrg    if (w->login.state != PROMPTING) {
472145b7b3cSmrg	return;
473145b7b3cSmrg    }
474578741aaSmrg
475145b7b3cSmrg    x = VALUE_X (w, w->login.activePrompt);
476145b7b3cSmrg    y = PROMPT_Y (w, w->login.activePrompt);
477145b7b3cSmrg    height = (F_ASCENT(text) + F_DESCENT(text));
478145b7b3cSmrg    width = 1;
479145b7b3cSmrg
480145b7b3cSmrg    switch (PROMPT_STATE(w, w->login.activePrompt)) {
481145b7b3cSmrg    case LOGIN_PROMPT_NOT_SHOWN:
482145b7b3cSmrg    case LOGIN_TEXT_INFO:
483145b7b3cSmrg	return;
484145b7b3cSmrg    case LOGIN_PROMPT_ECHO_ON:
485145b7b3cSmrg	if (CUR_PROMPT_CURSOR(w) > 0) {
486145b7b3cSmrg	    x += TEXT_WIDTH (text,
487145b7b3cSmrg			     VALUE_TEXT(w, w->login.activePrompt)
488145b7b3cSmrg			     + VALUE_SHOW_START(w, w->login.activePrompt),
489145b7b3cSmrg			     PROMPT_CURSOR(w, w->login.activePrompt)
490145b7b3cSmrg			     - VALUE_SHOW_START(w, w->login.activePrompt) );
491145b7b3cSmrg	}
492145b7b3cSmrg	break;
493145b7b3cSmrg    case LOGIN_PROMPT_ECHO_OFF:
4945ffd6003Smrg	if (w->login.echo_passwd == True) {
4955ffd6003Smrg	    int len = PROMPT_CURSOR(w, w->login.activePrompt) -
4965ffd6003Smrg		VALUE_SHOW_START(w, w->login.activePrompt);
4975ffd6003Smrg
4985ffd6003Smrg	    x += len*TEXT_WIDTH(text, "*", 1);
4995ffd6003Smrg	}
5005ffd6003Smrg	else
5015ffd6003Smrg	{
5025ffd6003Smrg	    /* Move cursor one pixel per character to give some feedback
5035ffd6003Smrg	       without giving away the password length */
5045ffd6003Smrg	    x += PROMPT_CURSOR(w, w->login.activePrompt);
5055ffd6003Smrg	}
506145b7b3cSmrg	break;
507145b7b3cSmrg    }
508578741aaSmrg
509145b7b3cSmrg    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
510145b7b3cSmrg		    x, y+1 - F_ASCENT(text), width, height-1);
511145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
512145b7b3cSmrg    		    x-1 , y - F_ASCENT(text));
513145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
514145b7b3cSmrg    		    x+1 , y - F_ASCENT(text));
515145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
516145b7b3cSmrg    		    x-1 , y - F_ASCENT(text)+height);
517145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
518145b7b3cSmrg    		    x+1 , y - F_ASCENT(text)+height);
519145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
520145b7b3cSmrg    		    x-2 , y - F_ASCENT(text));
521145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
522145b7b3cSmrg    		    x+2 , y - F_ASCENT(text));
523145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
524145b7b3cSmrg    		    x-2 , y - F_ASCENT(text)+height);
525145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
526145b7b3cSmrg    		    x+2 , y - F_ASCENT(text)+height);
527145b7b3cSmrg
528578741aaSmrg    XFlush (XtDisplay(w));
529145b7b3cSmrg}
530145b7b3cSmrg
531145b7b3cSmrgstatic void
532145b7b3cSmrgEraseFail (LoginWidget w)
533145b7b3cSmrg{
534578741aaSmrg#ifdef USE_XFT
535145b7b3cSmrg    w->login.failUp = 0;
536145b7b3cSmrg    RedrawFail(w);
537578741aaSmrg#else
538145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
539145b7b3cSmrg			w->core.background_pixel);
540145b7b3cSmrg    RedrawFail(w);
541145b7b3cSmrg    w->login.failUp = 0;
542145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
543145b7b3cSmrg			TEXT_COLOR(fail));
544578741aaSmrg#endif
545145b7b3cSmrg}
546145b7b3cSmrg
547145b7b3cSmrgstatic void
548145b7b3cSmrgXorCursor (LoginWidget w)
549145b7b3cSmrg{
550145b7b3cSmrg    realizeCursor (w, w->login.xorGC);
551145b7b3cSmrg}
552145b7b3cSmrg
553145b7b3cSmrgstatic void
554145b7b3cSmrgRemoveFail (LoginWidget w)
555145b7b3cSmrg{
556145b7b3cSmrg    if (w->login.failUp)
557145b7b3cSmrg	EraseFail (w);
558145b7b3cSmrg}
559145b7b3cSmrg
560145b7b3cSmrgstatic void
561145b7b3cSmrgEraseCursor (LoginWidget w)
562145b7b3cSmrg{
563145b7b3cSmrg    realizeCursor (w, w->login.bgGC);
564145b7b3cSmrg}
565145b7b3cSmrg
566145b7b3cSmrg/*ARGSUSED*/
567145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id)
568145b7b3cSmrg{
569145b7b3cSmrg    LoginWidget	w = (LoginWidget)client_data;
570145b7b3cSmrg
571145b7b3cSmrg    Debug ("failTimeout\n");
572145b7b3cSmrg    w->login.interval_id = 0;
573145b7b3cSmrg    EraseFail (w);
574145b7b3cSmrg}
575145b7b3cSmrg
576145b7b3cSmrg_X_INTERNAL
577145b7b3cSmrgvoid
578145b7b3cSmrgDrawFail (Widget ctx)
579145b7b3cSmrg{
580145b7b3cSmrg    LoginWidget	w;
581145b7b3cSmrg
582145b7b3cSmrg    w = (LoginWidget) ctx;
583145b7b3cSmrg    XorCursor (w);
584145b7b3cSmrg    ResetLogin (w);
585145b7b3cSmrg    XorCursor (w);
586145b7b3cSmrg    ErrorMessage(ctx, w->login.failMsg, True);
587145b7b3cSmrg}
588145b7b3cSmrg
589145b7b3cSmrgstatic void
590145b7b3cSmrgRedrawFail (LoginWidget w)
591145b7b3cSmrg{
592145b7b3cSmrg    int x = FAIL_X(w);
593145b7b3cSmrg    int y = FAIL_Y(w);
594145b7b3cSmrg    int maxw = w->core.width - PAD_X(w);
595145b7b3cSmrg
596578741aaSmrg#ifndef USE_XFT
597145b7b3cSmrg    if (w->login.failUp)
598578741aaSmrg#endif
599145b7b3cSmrg    {
600145b7b3cSmrg	Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp);
601145b7b3cSmrg	if (ERROR_W(w, w->login.fail) > maxw) {
602145b7b3cSmrg	    /* Too long to fit on one line, break into multiple lines */
603145b7b3cSmrg	    char *tempCopy = strdup(w->login.fail);
604145b7b3cSmrg	    if (tempCopy != NULL) {
605145b7b3cSmrg		char *start, *next;
606578741aaSmrg		char lastspace = ' ';
607145b7b3cSmrg
608145b7b3cSmrg		y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w));
609578741aaSmrg
610145b7b3cSmrg		for (start = next = tempCopy; start != NULL ; start = next) {
611145b7b3cSmrg		    /* search for longest string broken by whitespace that
612145b7b3cSmrg		       will fit on a single line */
613145b7b3cSmrg		    do {
614145b7b3cSmrg			if (next != start) {
615145b7b3cSmrg			    *next = lastspace;
616145b7b3cSmrg			}
617145b7b3cSmrg			for (next = next + 1;
618145b7b3cSmrg			     (*next != '\0') && !isspace(*next) ; next++)
619145b7b3cSmrg			{
620145b7b3cSmrg			    /* this loop intentionally left blank */
621145b7b3cSmrg			}
622145b7b3cSmrg			if (*next != '\0') {
623145b7b3cSmrg			    lastspace = *next;
624145b7b3cSmrg			    *next = '\0';
625145b7b3cSmrg			} else {
626145b7b3cSmrg			    next = NULL;
627145b7b3cSmrg			}
628145b7b3cSmrg		    } while ((next != NULL) && ERROR_W(w, start) < maxw);
629578741aaSmrg
630145b7b3cSmrg		    x = ERROR_X(w, start);
631145b7b3cSmrg#ifdef USE_XFT
632145b7b3cSmrg		    if (w->login.failUp == 0) {
6335ffd6003Smrg			XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
634145b7b3cSmrg				   ERROR_W(w, start), FAIL_Y_INC(w), False);
635145b7b3cSmrg		    } else
636578741aaSmrg#endif
637145b7b3cSmrg			DRAW_STRING (fail, x, y, start, strlen(start));
638145b7b3cSmrg
639145b7b3cSmrg		    if (next != NULL) {
640145b7b3cSmrg			next++;
641145b7b3cSmrg			y += FAIL_Y_INC(w);
642145b7b3cSmrg		    }
643145b7b3cSmrg		}
644145b7b3cSmrg		free(tempCopy);
645145b7b3cSmrg		return;
646145b7b3cSmrg	    }
647145b7b3cSmrg	    /* if strdup failed, fall through to draw all at once, even
648145b7b3cSmrg	       though we know it can't all fit */
649145b7b3cSmrg	    LogOutOfMem("RedrawFail");
650145b7b3cSmrg	}
651145b7b3cSmrg
652145b7b3cSmrg#ifdef USE_XFT
653145b7b3cSmrg	if (w->login.failUp == 0) {
6545ffd6003Smrg	    XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
655145b7b3cSmrg		       ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False);
656145b7b3cSmrg	} else
657578741aaSmrg#endif
658145b7b3cSmrg	    DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail));
659145b7b3cSmrg    }
660145b7b3cSmrg}
661145b7b3cSmrg
662145b7b3cSmrg_X_INTERNAL
663145b7b3cSmrgvoid
664145b7b3cSmrgErrorMessage(Widget ctx, const char *message, Bool timeout)
665145b7b3cSmrg{
666145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
667145b7b3cSmrg
668145b7b3cSmrg/*  Debug("ErrorMessage: %s\n", message);   */
669145b7b3cSmrg    if (w->login.interval_id != 0) {
670145b7b3cSmrg	XtRemoveTimeOut(w->login.interval_id);
671145b7b3cSmrg	w->login.interval_id = 0;
672145b7b3cSmrg    }
673145b7b3cSmrg    RemoveFail(w);
674145b7b3cSmrg    if (w->login.fail != w->login.failMsg)
675145b7b3cSmrg	free(w->login.fail);
676145b7b3cSmrg    w->login.fail = strdup(message);
677145b7b3cSmrg    if (w->login.fail == NULL)
678145b7b3cSmrg	w->login.fail = (char *) w->login.failMsg;
679145b7b3cSmrg    w->login.failUp = 1;
680145b7b3cSmrg    RedrawFail (w);
681145b7b3cSmrg    if (timeout && (w->login.failTimeout > 0)) {
682145b7b3cSmrg	Debug ("failTimeout: %d\n", w->login.failTimeout);
683145b7b3cSmrg	w->login.interval_id =
684145b7b3cSmrg	    XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w),
685145b7b3cSmrg			    w->login.failTimeout * 1000,
686145b7b3cSmrg			    failTimeout, (XtPointer) w);
687145b7b3cSmrg    }
688145b7b3cSmrg}
689145b7b3cSmrg
690145b7b3cSmrg_X_INTERNAL
691145b7b3cSmrgvoid
692145b7b3cSmrgShowChangePasswdMessage(Widget ctx)
693145b7b3cSmrg{
694145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
695145b7b3cSmrg
696145b7b3cSmrg    ErrorMessage(ctx, w->login.passwdChangeMsg, False);
697145b7b3cSmrg}
698145b7b3cSmrg
699145b7b3cSmrgstatic void
700145b7b3cSmrgdraw_it (LoginWidget w)
701145b7b3cSmrg{
702145b7b3cSmrg    int p;
703145b7b3cSmrg    int i;
704145b7b3cSmrg    int gr_line_x, gr_line_y, gr_line_w;
705145b7b3cSmrg
706145b7b3cSmrg    EraseCursor (w);
707145b7b3cSmrg
7085ffd6003Smrg    /* draw window borders */
709145b7b3cSmrg    for(i=1;i<=(w->login.outframewidth);i++)
710145b7b3cSmrg    {
711145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
712145b7b3cSmrg    		i-1,i-1,w->core.width-i,i-1);
713145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
714145b7b3cSmrg    		i-1,i-1,i-1,w->core.height-i);
715145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
716145b7b3cSmrg    		w->core.width-i,i-1,w->core.width-i,w->core.height-i);
717145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
718145b7b3cSmrg    		i-1,w->core.height-i,w->core.width-i,w->core.height-i);
719145b7b3cSmrg    }
720578741aaSmrg
721145b7b3cSmrg    /* make separator line */
722145b7b3cSmrg    gr_line_x = w->login.outframewidth;
723145b7b3cSmrg    gr_line_y = GREET_Y(w) + GREET_Y_INC(w);
724145b7b3cSmrg    gr_line_w = w->core.width - 2*(w->login.outframewidth);
725145b7b3cSmrg
726145b7b3cSmrg#ifdef XPM
727145b7b3cSmrg    gr_line_x += w->login.logoPadding;
728145b7b3cSmrg    gr_line_w -= w->login.logoWidth + (3 * (w->login.logoPadding));
729145b7b3cSmrg#endif /* XPM */
730145b7b3cSmrg
731145b7b3cSmrg    for(i=1;i<=(w->login.sepwidth);i++)
732145b7b3cSmrg    {
733145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
734145b7b3cSmrg        gr_line_x,           gr_line_y + i-1,
735145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + i-1);
736145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
737145b7b3cSmrg        gr_line_x,           gr_line_y + 2*(w->login.inframeswidth) -i,
738145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + 2*(w->login.inframeswidth) -i);
739145b7b3cSmrg    }
740145b7b3cSmrg
741145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++)
742145b7b3cSmrg    {
743145b7b3cSmrg	int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth - 3;
744145b7b3cSmrg	int in_frame_y
745145b7b3cSmrg	    = PROMPT_Y(w,p) - w->login.inframeswidth - 1 - TEXT_Y_INC(w);
746578741aaSmrg
747145b7b3cSmrg	int in_width = PROMPT_W(w) - VALUE_X(w,p);
748145b7b3cSmrg	int in_height = PROMPT_H(w) + w->login.inframeswidth + 2;
749578741aaSmrg
750145b7b3cSmrg	GC topLeftGC, botRightGC;
751145b7b3cSmrg
752578741aaSmrg#ifdef XPM
753145b7b3cSmrg	in_width -= (w->login.logoWidth + 2*(w->login.logoPadding));
754145b7b3cSmrg#endif /* XPM */
755578741aaSmrg
756145b7b3cSmrg	if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) ||
757145b7b3cSmrg	    (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) {
758145b7b3cSmrg	    topLeftGC = w->login.shdGC;
759145b7b3cSmrg	    botRightGC = w->login.hiGC;
760145b7b3cSmrg	} else {
761145b7b3cSmrg	    topLeftGC = botRightGC = w->login.bgGC;
762145b7b3cSmrg	}
763145b7b3cSmrg
7645ffd6003Smrg	/* draw borders of editboxes */
765145b7b3cSmrg	for (i=1; i<=(w->login.inframeswidth); i++)
766145b7b3cSmrg	{
767145b7b3cSmrg	    /* Make top/left sides */
768145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
769145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
770578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1);
771145b7b3cSmrg
772145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
773145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
774578741aaSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i);
775145b7b3cSmrg
776145b7b3cSmrg	    /* Make bottom/right sides */
777145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
778145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1,
779578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
780145b7b3cSmrg
781145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
782145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i,
783145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
784145b7b3cSmrg	}
785145b7b3cSmrg    }
786145b7b3cSmrg
787145b7b3cSmrg    if (GREETING(w)[0]) {
788145b7b3cSmrg	int gx = GREET_X(w);
789145b7b3cSmrg
790145b7b3cSmrg#ifdef XPM
791145b7b3cSmrg	gx -= ((w->login.logoWidth/2) + w->login.logoPadding);
792578741aaSmrg#endif
793145b7b3cSmrg	DRAW_STRING (greet, gx, GREET_Y(w), GREETING(w), strlen (GREETING(w)));
794145b7b3cSmrg    }
795145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++) {
796145b7b3cSmrg	if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) {
797145b7b3cSmrg	    DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p),
798145b7b3cSmrg			 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p)));
799145b7b3cSmrg	    DrawValue (w, 0, p);
800145b7b3cSmrg	}
801145b7b3cSmrg    }
802145b7b3cSmrg    RedrawFail (w);
803145b7b3cSmrg    XorCursor (w);
8045ffd6003Smrg    XSetInputFocus (XtDisplay (w), XtWindow (w),
8055ffd6003Smrg		    RevertToPointerRoot, CurrentTime);
806145b7b3cSmrg}
807145b7b3cSmrg
808145b7b3cSmrg/* Returns 0 on success, -1 on failure */
809145b7b3cSmrg_X_INTERNAL
810145b7b3cSmrgint
811145b7b3cSmrgSetPrompt (Widget ctx, int promptNum, const char *message,
812145b7b3cSmrg	   loginPromptState state, Boolean minimumTime)
813145b7b3cSmrg{
814145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
815145b7b3cSmrg    char *prompt;
816145b7b3cSmrg    int messageLen, e;
817145b7b3cSmrg    const char *stateNames[4] = {
818145b7b3cSmrg	"LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON",
819145b7b3cSmrg	"LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" };
820145b7b3cSmrg    loginPromptState priorState;
821578741aaSmrg
822145b7b3cSmrg    Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum,
823145b7b3cSmrg	  message ? message : "<NULL>", stateNames[state], state);
824145b7b3cSmrg
825145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
826578741aaSmrg
827145b7b3cSmrg    if (PROMPT_TEXT(w, promptNum) != NULL) {
828145b7b3cSmrg	XtFree(PROMPT_TEXT(w, promptNum));
829145b7b3cSmrg	PROMPT_TEXT(w, promptNum) = NULL;
830145b7b3cSmrg    }
831145b7b3cSmrg
832145b7b3cSmrg    priorState = PROMPT_STATE(w, promptNum);
833145b7b3cSmrg    PROMPT_STATE(w, promptNum) = state;
834145b7b3cSmrg
835145b7b3cSmrg    if (state == LOGIN_PROMPT_NOT_SHOWN) {
836145b7b3cSmrg	return 0;
837145b7b3cSmrg    }
838145b7b3cSmrg
839145b7b3cSmrg    if (message == NULL) {
840145b7b3cSmrg	message = DEF_PROMPT_TEXT(w, promptNum);
841145b7b3cSmrg    }
842145b7b3cSmrg
843145b7b3cSmrg    messageLen = strlen(message);
844578741aaSmrg
845145b7b3cSmrg    prompt = XtMalloc(messageLen + 3);
846145b7b3cSmrg    if (prompt == NULL) {
847145b7b3cSmrg	LogOutOfMem ("SetPrompt");
848145b7b3cSmrg	return -1;
849145b7b3cSmrg    }
850578741aaSmrg
851145b7b3cSmrg    strncpy(prompt, message, messageLen);
852578741aaSmrg
853145b7b3cSmrg    /* Make sure text prompts have at least two spaces at end */
854145b7b3cSmrg    e = messageLen;
855578741aaSmrg
856145b7b3cSmrg    if (!isspace(message[messageLen - 2])) {
857145b7b3cSmrg	prompt[e] = ' ';
858145b7b3cSmrg	e++;
859145b7b3cSmrg    }
860145b7b3cSmrg    if (!isspace(message[messageLen - 1])) {
861145b7b3cSmrg	prompt[e] = ' ';
862145b7b3cSmrg	e++;
863145b7b3cSmrg    }
864145b7b3cSmrg    prompt[e] = '\0';
865145b7b3cSmrg
866145b7b3cSmrg    PROMPT_TEXT(w, promptNum) = prompt;
867145b7b3cSmrg
868145b7b3cSmrg    if (w->login.state == INITIALIZING) {
869145b7b3cSmrg	return 0;
870145b7b3cSmrg    }
871578741aaSmrg
872145b7b3cSmrg    if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) {
873145b7b3cSmrg	time_t now = time(NULL);
874145b7b3cSmrg	int timeleft = w->login.msgTimeout - now;
875578741aaSmrg
876145b7b3cSmrg	if (timeleft > 0) {
877145b7b3cSmrg	    sleep(timeleft);
878145b7b3cSmrg	}
879145b7b3cSmrg	w->login.msgTimeout = 0;
880145b7b3cSmrg    }
881145b7b3cSmrg
882145b7b3cSmrg    if (state == LOGIN_TEXT_INFO) {
883145b7b3cSmrg	if (minimumTime) {
884145b7b3cSmrg	    time_t now = time(NULL);
885145b7b3cSmrg	    w->login.msgTimeout = now + w->login.failTimeout;
886145b7b3cSmrg	}
887145b7b3cSmrg	w->login.state = SHOW_MESSAGE;
888145b7b3cSmrg    } else {
889145b7b3cSmrg	w->login.activePrompt = promptNum;
890145b7b3cSmrg	w->login.state = PROMPTING;
891145b7b3cSmrg    }
892578741aaSmrg
893145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
894145b7b3cSmrg    XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE);
895145b7b3cSmrg    draw_it(w);
896145b7b3cSmrg    return 0;
897145b7b3cSmrg}
898145b7b3cSmrg
899145b7b3cSmrg_X_INTERNAL
900145b7b3cSmrgconst char *
901145b7b3cSmrgGetPrompt(Widget ctx, int promptNum)
902145b7b3cSmrg{
903145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
904145b7b3cSmrg
905145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
906578741aaSmrg
907145b7b3cSmrg    return CUR_PROMPT_TEXT(w,promptNum);
908145b7b3cSmrg}
909145b7b3cSmrg
910145b7b3cSmrg_X_INTERNAL
911145b7b3cSmrgint
912145b7b3cSmrgSetValue(Widget ctx, int promptNum, char *value)
913145b7b3cSmrg{
914145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
915145b7b3cSmrg
916145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
917578741aaSmrg
918145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
919145b7b3cSmrg	return -1;
920145b7b3cSmrg
921145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
922578741aaSmrg
923145b7b3cSmrg    if (VALUE_TEXT(w, promptNum) == NULL)
924145b7b3cSmrg	return -1;
925145b7b3cSmrg
926145b7b3cSmrg    if (value == NULL) {
927145b7b3cSmrg	bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum));
928145b7b3cSmrg    } else {
929145b7b3cSmrg	strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum));
930145b7b3cSmrg	VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0';
931145b7b3cSmrg    }
932145b7b3cSmrg
933145b7b3cSmrg    VALUE_SHOW_START(w, promptNum) = 0;
934145b7b3cSmrg    VALUE_SHOW_END(w, promptNum) = 0;
935145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
936578741aaSmrg
937145b7b3cSmrg    return 0;
938145b7b3cSmrg}
939145b7b3cSmrg
940145b7b3cSmrg_X_INTERNAL
941145b7b3cSmrgconst char *
942145b7b3cSmrgGetValue(Widget ctx, int promptNum)
943145b7b3cSmrg{
944145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
945145b7b3cSmrg
946145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
947578741aaSmrg
948145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
949145b7b3cSmrg	return NULL;
950145b7b3cSmrg
951145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
952145b7b3cSmrg
953145b7b3cSmrg    return VALUE_TEXT(w, promptNum);
954145b7b3cSmrg}
955145b7b3cSmrg
956145b7b3cSmrg
957145b7b3cSmrgstatic void
958145b7b3cSmrgrealizeDeleteChar (LoginWidget ctx)
959145b7b3cSmrg{
960145b7b3cSmrg    if (ctx->login.state == PROMPTING) {
961145b7b3cSmrg	int promptNum = ctx->login.activePrompt;
962145b7b3cSmrg	int redrawFrom = PROMPT_CURSOR(ctx, promptNum);
963578741aaSmrg
964145b7b3cSmrg	if (PROMPT_CURSOR(ctx,promptNum) <  (int)strlen(VALUE_TEXT(ctx,promptNum))) {
965145b7b3cSmrg	    if (redrawFrom < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
966145b7b3cSmrg		redrawFrom = 0;
967145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
968145b7b3cSmrg		VALUE_SHOW_START(ctx, ctx->login.activePrompt)
969145b7b3cSmrg		    = PROMPT_CURSOR(ctx,promptNum);
970145b7b3cSmrg	    } else {
971145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
972145b7b3cSmrg	    }
973145b7b3cSmrg	    strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
974145b7b3cSmrg		   VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1);
975145b7b3cSmrg	    DrawValue (ctx, redrawFrom, promptNum);
976145b7b3cSmrg	}
977145b7b3cSmrg    }
978145b7b3cSmrg}
979145b7b3cSmrg
980145b7b3cSmrg/*ARGSUSED*/
981145b7b3cSmrgstatic void
982145b7b3cSmrgDeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
983145b7b3cSmrg{
984145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
985145b7b3cSmrg
986145b7b3cSmrg    RemoveFail (ctx);
987145b7b3cSmrg
988145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
989145b7b3cSmrg	return;
990145b7b3cSmrg    }
991145b7b3cSmrg
992145b7b3cSmrg    XorCursor (ctx);
993145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0) {
994145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
995145b7b3cSmrg	realizeDeleteChar(ctx);
996145b7b3cSmrg    }
997578741aaSmrg    XorCursor (ctx);
998145b7b3cSmrg}
999145b7b3cSmrg
1000145b7b3cSmrg/*ARGSUSED*/
1001145b7b3cSmrgstatic void
1002145b7b3cSmrgDeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1003145b7b3cSmrg{
1004145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1005145b7b3cSmrg
1006145b7b3cSmrg    RemoveFail (ctx);
1007145b7b3cSmrg
1008145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1009145b7b3cSmrg	return;
1010145b7b3cSmrg    }
1011145b7b3cSmrg
1012145b7b3cSmrg    XorCursor (ctx);
1013145b7b3cSmrg    realizeDeleteChar(ctx);
1014578741aaSmrg    XorCursor (ctx);
1015145b7b3cSmrg}
1016145b7b3cSmrg
1017145b7b3cSmrg/*ARGSUSED*/
1018145b7b3cSmrgstatic void
1019145b7b3cSmrgMoveBackwardChar (
1020145b7b3cSmrg    Widget	ctxw,
1021145b7b3cSmrg    XEvent	*event,
1022145b7b3cSmrg    String	*params,
1023145b7b3cSmrg    Cardinal	*num_params)
1024145b7b3cSmrg{
1025145b7b3cSmrg    LoginWidget	ctx = (LoginWidget)ctxw;
1026145b7b3cSmrg
1027145b7b3cSmrg    RemoveFail (ctx);
1028145b7b3cSmrg
1029145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1030145b7b3cSmrg	return;
1031145b7b3cSmrg    }
1032145b7b3cSmrg
1033145b7b3cSmrg    XorCursor (ctx);
1034145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0)
1035145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
1036145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
1037145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1038145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt)
1039145b7b3cSmrg	    = CUR_PROMPT_CURSOR(ctx);
1040145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1041145b7b3cSmrg    }
1042145b7b3cSmrg    XorCursor (ctx);
1043145b7b3cSmrg}
1044145b7b3cSmrg
1045145b7b3cSmrg/*ARGSUSED*/
1046145b7b3cSmrgstatic void
1047145b7b3cSmrgMoveForwardChar (
1048145b7b3cSmrg    Widget	ctxw,
1049145b7b3cSmrg    XEvent	*event,
1050145b7b3cSmrg    String	*params,
1051145b7b3cSmrg    Cardinal	*num_params)
1052145b7b3cSmrg{
1053145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1054145b7b3cSmrg
1055145b7b3cSmrg    RemoveFail (ctx);
1056145b7b3cSmrg
1057145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1058145b7b3cSmrg	return;
1059145b7b3cSmrg    }
1060145b7b3cSmrg
1061145b7b3cSmrg    XorCursor (ctx);
1062145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) <
1063145b7b3cSmrg	(int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) {
1064145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) += 1;
1065145b7b3cSmrg	if (VALUE_SHOW_END(ctx, ctx->login.activePrompt)
1066145b7b3cSmrg	    < CUR_PROMPT_CURSOR(ctx)) {
1067145b7b3cSmrg	    EraseValue(ctx, 0, ctx->login.activePrompt);
1068145b7b3cSmrg	    DrawValue(ctx, 0, ctx->login.activePrompt);
1069145b7b3cSmrg	}
1070145b7b3cSmrg    }
1071145b7b3cSmrg    XorCursor (ctx);
1072145b7b3cSmrg}
1073145b7b3cSmrg
1074145b7b3cSmrg/*ARGSUSED*/
1075145b7b3cSmrgstatic void
1076145b7b3cSmrgMoveToBegining (
1077145b7b3cSmrg    Widget	ctxw,
1078145b7b3cSmrg    XEvent	*event,
1079145b7b3cSmrg    String	*params,
1080145b7b3cSmrg    Cardinal	*num_params)
1081145b7b3cSmrg{
1082145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1083145b7b3cSmrg
1084145b7b3cSmrg    RemoveFail (ctx);
1085145b7b3cSmrg
1086145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1087145b7b3cSmrg	return;
1088145b7b3cSmrg    }
1089145b7b3cSmrg
1090145b7b3cSmrg    XorCursor (ctx);
1091145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = 0;
1092145b7b3cSmrg    if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) {
1093145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1094145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0;
1095145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1096145b7b3cSmrg    }
1097145b7b3cSmrg    XorCursor (ctx);
1098145b7b3cSmrg}
1099145b7b3cSmrg
1100145b7b3cSmrg/*ARGSUSED*/
1101145b7b3cSmrgstatic void
1102145b7b3cSmrgMoveToEnd (
1103145b7b3cSmrg    Widget	ctxw,
1104145b7b3cSmrg    XEvent	*event,
1105145b7b3cSmrg    String	*params,
1106145b7b3cSmrg    Cardinal	*num_params)
1107145b7b3cSmrg{
1108145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1109145b7b3cSmrg
1110145b7b3cSmrg    RemoveFail (ctx);
1111145b7b3cSmrg
1112145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1113145b7b3cSmrg	return;
1114145b7b3cSmrg    }
1115145b7b3cSmrg
1116145b7b3cSmrg    XorCursor (ctx);
1117145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt));
1118145b7b3cSmrg    if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) {
1119145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1120145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1121145b7b3cSmrg    }
1122145b7b3cSmrg    XorCursor (ctx);
1123145b7b3cSmrg}
1124145b7b3cSmrg
1125145b7b3cSmrg/*ARGSUSED*/
1126145b7b3cSmrgstatic void
1127145b7b3cSmrgEraseToEndOfLine (
1128145b7b3cSmrg    Widget	ctxw,
1129145b7b3cSmrg    XEvent	*event,
1130145b7b3cSmrg    String	*params,
1131145b7b3cSmrg    Cardinal	*num_params)
1132145b7b3cSmrg{
1133145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1134145b7b3cSmrg
1135145b7b3cSmrg    RemoveFail (ctx);
1136145b7b3cSmrg
1137145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1138145b7b3cSmrg	return;
1139145b7b3cSmrg    }
1140145b7b3cSmrg
1141145b7b3cSmrg    XorCursor (ctx);
1142145b7b3cSmrg    EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt);
1143145b7b3cSmrg    bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) +
1144145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx),
1145145b7b3cSmrg	  VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) -
1146145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx));
1147145b7b3cSmrg    XorCursor (ctx);
1148145b7b3cSmrg}
1149145b7b3cSmrg
1150145b7b3cSmrg/*ARGSUSED*/
1151145b7b3cSmrgstatic void
1152145b7b3cSmrgEraseLine (
1153145b7b3cSmrg    Widget	ctxw,
1154145b7b3cSmrg    XEvent	*event,
1155145b7b3cSmrg    String	*params,
1156145b7b3cSmrg    Cardinal	*num_params)
1157145b7b3cSmrg{
1158145b7b3cSmrg    MoveToBegining (ctxw, event, params, num_params);
1159145b7b3cSmrg    EraseToEndOfLine (ctxw, event, params, num_params);
1160145b7b3cSmrg}
1161145b7b3cSmrg
1162145b7b3cSmrg/*ARGSUSED*/
1163145b7b3cSmrgstatic void
1164145b7b3cSmrgFinishField (
1165145b7b3cSmrg    Widget	ctxw,
1166145b7b3cSmrg    XEvent	*event,
1167145b7b3cSmrg    String	*params,
1168145b7b3cSmrg    Cardinal	*num_params)
1169145b7b3cSmrg{
1170145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1171145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1172145b7b3cSmrg    int nextPrompt;
1173145b7b3cSmrg
1174145b7b3cSmrg    RemoveFail (ctx);
1175145b7b3cSmrg
1176145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1177145b7b3cSmrg	return;
1178145b7b3cSmrg    }
1179145b7b3cSmrg
1180145b7b3cSmrg    XorCursor (ctx);
1181145b7b3cSmrg
1182145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) {
1183145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1184145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1185145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1186145b7b3cSmrg	    break;
1187145b7b3cSmrg	}
1188145b7b3cSmrg    }
1189145b7b3cSmrg    if (nextPrompt > LAST_PROMPT) {
1190145b7b3cSmrg	ctx->login.state = DONE;
1191145b7b3cSmrg	(*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
1192145b7b3cSmrg	Debug("FinishField #%d: now DONE\n", promptNum);
1193145b7b3cSmrg    } else {
1194145b7b3cSmrg	Debug("FinishField #%d: %d next\n", promptNum, nextPrompt);
1195145b7b3cSmrg    }
1196145b7b3cSmrg
1197145b7b3cSmrg    XorCursor (ctx);
1198145b7b3cSmrg}
1199145b7b3cSmrg
1200145b7b3cSmrg/*ARGSUSED*/
1201145b7b3cSmrgstatic void
1202145b7b3cSmrgTabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1203145b7b3cSmrg{
1204145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1205145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1206145b7b3cSmrg    int nextPrompt;
1207145b7b3cSmrg
1208145b7b3cSmrg    RemoveFail (ctx);
1209145b7b3cSmrg
1210145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1211145b7b3cSmrg	return;
1212145b7b3cSmrg    }
1213145b7b3cSmrg
1214145b7b3cSmrg    XorCursor (ctx);
1215145b7b3cSmrg
1216145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) {
1217145b7b3cSmrg	if (nextPrompt > LAST_PROMPT) {
1218145b7b3cSmrg	    nextPrompt = 0;
1219145b7b3cSmrg	}
1220578741aaSmrg
1221145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1222145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1223145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1224145b7b3cSmrg	    break;
1225145b7b3cSmrg	}
1226145b7b3cSmrg    }
1227145b7b3cSmrg    XorCursor (ctx);
1228145b7b3cSmrg}
1229145b7b3cSmrg
1230145b7b3cSmrg/*ARGSUSED*/
1231145b7b3cSmrgstatic void
1232145b7b3cSmrgAllowAccess (
1233145b7b3cSmrg    Widget	ctxw,
1234145b7b3cSmrg    XEvent	*event,
1235145b7b3cSmrg    String	*params,
1236145b7b3cSmrg    Cardinal	*num_params)
1237145b7b3cSmrg{
1238145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1239145b7b3cSmrg    Arg	arglist[1];
1240145b7b3cSmrg    Boolean allow;
1241145b7b3cSmrg
1242145b7b3cSmrg    RemoveFail (ctx);
1243145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
1244145b7b3cSmrg    XtGetValues ((Widget) ctx, arglist, 1);
1245145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, !allow);
1246145b7b3cSmrg    XtSetValues ((Widget) ctx, arglist, 1);
1247145b7b3cSmrg}
1248145b7b3cSmrg
1249145b7b3cSmrg/*ARGSUSED*/
1250145b7b3cSmrgstatic void
1251145b7b3cSmrgSetSessionArgument (
1252145b7b3cSmrg    Widget	ctxw,
1253145b7b3cSmrg    XEvent	*event,
1254145b7b3cSmrg    String	*params,
1255145b7b3cSmrg    Cardinal	*num_params)
1256145b7b3cSmrg{
1257145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1258145b7b3cSmrg
1259145b7b3cSmrg    RemoveFail (ctx);
1260145b7b3cSmrg    if (ctx->login.sessionArg)
1261145b7b3cSmrg	XtFree (ctx->login.sessionArg);
1262145b7b3cSmrg    ctx->login.sessionArg = NULL;
1263145b7b3cSmrg    if (*num_params > 0) {
1264145b7b3cSmrg	ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
1265145b7b3cSmrg	if (ctx->login.sessionArg)
1266145b7b3cSmrg	    strcpy (ctx->login.sessionArg, params[0]);
1267145b7b3cSmrg	else
1268145b7b3cSmrg	    LogOutOfMem ("set session argument");
1269145b7b3cSmrg    }
1270145b7b3cSmrg}
1271145b7b3cSmrg
1272145b7b3cSmrg/*ARGSUSED*/
1273145b7b3cSmrgstatic void
1274145b7b3cSmrgRestartSession (
1275145b7b3cSmrg    Widget	ctxw,
1276145b7b3cSmrg    XEvent	*event,
1277145b7b3cSmrg    String	*params,
1278145b7b3cSmrg    Cardinal	*num_params)
1279145b7b3cSmrg{
1280145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1281145b7b3cSmrg
1282145b7b3cSmrg    XorCursor (ctx);
1283145b7b3cSmrg    RemoveFail (ctx);
1284145b7b3cSmrg    ctx->login.state = DONE;
1285145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
1286145b7b3cSmrg    XorCursor (ctx);
1287145b7b3cSmrg}
1288145b7b3cSmrg
1289145b7b3cSmrg/*ARGSUSED*/
1290145b7b3cSmrgstatic void
1291145b7b3cSmrgAbortSession (
1292145b7b3cSmrg    Widget	ctxw,
1293145b7b3cSmrg    XEvent	*event,
1294145b7b3cSmrg    String	*params,
1295145b7b3cSmrg    Cardinal	*num_params)
1296145b7b3cSmrg{
1297145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1298145b7b3cSmrg
1299145b7b3cSmrg    XorCursor (ctx);
1300145b7b3cSmrg    RemoveFail (ctx);
1301145b7b3cSmrg    ctx->login.state = DONE;
1302145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
1303145b7b3cSmrg    XorCursor (ctx);
1304145b7b3cSmrg}
1305145b7b3cSmrg
1306145b7b3cSmrg/*ARGSUSED*/
1307145b7b3cSmrgstatic void
1308145b7b3cSmrgAbortDisplay (
1309145b7b3cSmrg    Widget	ctxw,
1310145b7b3cSmrg    XEvent	*event,
1311145b7b3cSmrg    String	*params,
1312145b7b3cSmrg    Cardinal	*num_params)
1313145b7b3cSmrg{
1314145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1315145b7b3cSmrg
1316145b7b3cSmrg    XorCursor (ctx);
1317145b7b3cSmrg    RemoveFail (ctx);
1318145b7b3cSmrg    ctx->login.state = DONE;
1319145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
1320145b7b3cSmrg    XorCursor (ctx);
1321145b7b3cSmrg}
1322145b7b3cSmrg
1323145b7b3cSmrgstatic void
1324145b7b3cSmrgResetLogin (LoginWidget w)
1325145b7b3cSmrg{
1326145b7b3cSmrg    int i;
1327145b7b3cSmrg
1328145b7b3cSmrg    for (i = 0; i < NUM_PROMPTS ; i++) {
1329145b7b3cSmrg	EraseValue(w, 0, i);
1330145b7b3cSmrg	bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i));
1331145b7b3cSmrg	VALUE_SHOW_START(w, i) = 0;
1332145b7b3cSmrg	PROMPT_CURSOR(w, i) = 0;
1333145b7b3cSmrg    }
1334145b7b3cSmrg    w->login.state = PROMPTING;
1335145b7b3cSmrg    w->login.activePrompt = 0;
1336145b7b3cSmrg}
1337145b7b3cSmrg
1338145b7b3cSmrgstatic void
1339145b7b3cSmrgInitI18N(Widget ctxw)
1340145b7b3cSmrg{
1341145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1342145b7b3cSmrg    XIM         xim = (XIM) NULL;
1343145b7b3cSmrg    char *p;
1344145b7b3cSmrg
1345145b7b3cSmrg    ctx->login.xic = (XIC) NULL;
1346145b7b3cSmrg
1347145b7b3cSmrg    if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
1348145b7b3cSmrg	xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL);
1349145b7b3cSmrg
1350145b7b3cSmrg    if (!xim) {
1351145b7b3cSmrg	LogError("Failed to open input method\n");
1352145b7b3cSmrg	return;
1353145b7b3cSmrg    }
1354145b7b3cSmrg
1355145b7b3cSmrg    ctx->login.xic = XCreateIC(xim,
1356145b7b3cSmrg	XNInputStyle, (XIMPreeditNothing|XIMStatusNothing),
1357145b7b3cSmrg	XNClientWindow, ctx->core.window,
1358145b7b3cSmrg	XNFocusWindow,  ctx->core.window, NULL);
1359145b7b3cSmrg
1360145b7b3cSmrg    if (!ctx->login.xic) {
1361145b7b3cSmrg	LogError("Failed to create input context\n");
1362145b7b3cSmrg	XCloseIM(xim);
1363145b7b3cSmrg    }
1364145b7b3cSmrg    return;
1365145b7b3cSmrg}
1366145b7b3cSmrg
1367145b7b3cSmrg/* ARGSUSED */
1368145b7b3cSmrgstatic void
1369145b7b3cSmrgInsertChar (
1370145b7b3cSmrg    Widget	ctxw,
1371145b7b3cSmrg    XEvent	*event,
1372145b7b3cSmrg    String	*params,
1373145b7b3cSmrg    Cardinal	*num_params)
1374145b7b3cSmrg{
1375145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1376145b7b3cSmrg
1377145b7b3cSmrg    char strbuf[128];
1378145b7b3cSmrg    int  len, promptNum = ctx->login.activePrompt;
1379145b7b3cSmrg    KeySym  keysym = 0;
1380145b7b3cSmrg
1381145b7b3cSmrg    if (ctx->login.xic) {
1382145b7b3cSmrg	static Status status;
1383145b7b3cSmrg	len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf,
1384145b7b3cSmrg			      sizeof (strbuf), &keysym, &status);
1385145b7b3cSmrg    } else {
1386145b7b3cSmrg	static XComposeStatus compose_status = {NULL, 0};
1387145b7b3cSmrg	len = XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1388145b7b3cSmrg			     &keysym, &compose_status);
1389145b7b3cSmrg    }
1390145b7b3cSmrg    strbuf[len] = '\0';
1391145b7b3cSmrg
1392145b7b3cSmrg    /*
1393145b7b3cSmrg     * Note: You can override this default key handling
1394145b7b3cSmrg     * by the settings in the translation table
1395145b7b3cSmrg     * loginActionsTable at the end of this file.
1396145b7b3cSmrg     */
1397145b7b3cSmrg    switch (keysym) {
1398145b7b3cSmrg    case XK_Return:
1399145b7b3cSmrg    case XK_KP_Enter:
1400145b7b3cSmrg    case XK_Linefeed:
1401145b7b3cSmrg    case XK_Execute:
1402145b7b3cSmrg	FinishField(ctxw, event, params, num_params);
1403145b7b3cSmrg	return;
1404145b7b3cSmrg    case XK_BackSpace:
1405145b7b3cSmrg	DeleteBackwardChar(ctxw, event, params, num_params);
1406145b7b3cSmrg	return;
1407145b7b3cSmrg    case XK_Delete:
1408145b7b3cSmrg    case XK_KP_Delete:
1409145b7b3cSmrg    case DXK_Remove:
1410145b7b3cSmrg	/* Sorry, it's not a telex machine, it's a terminal */
1411145b7b3cSmrg	DeleteForwardChar(ctxw, event, params, num_params);
1412145b7b3cSmrg	return;
1413145b7b3cSmrg    case XK_Left:
1414145b7b3cSmrg    case XK_KP_Left:
1415145b7b3cSmrg	MoveBackwardChar(ctxw, event, params, num_params);
1416145b7b3cSmrg	return;
1417145b7b3cSmrg    case XK_Right:
1418145b7b3cSmrg    case XK_KP_Right:
1419145b7b3cSmrg	MoveForwardChar(ctxw, event, params, num_params);
1420145b7b3cSmrg	return;
1421145b7b3cSmrg    case XK_End:
1422145b7b3cSmrg    case XK_KP_End:
1423145b7b3cSmrg	MoveToEnd(ctxw, event, params, num_params);
1424145b7b3cSmrg	return;
1425145b7b3cSmrg    case XK_Home:
1426145b7b3cSmrg    case XK_KP_Home:
1427145b7b3cSmrg	MoveToBegining(ctxw, event, params, num_params);
1428145b7b3cSmrg	return;
1429145b7b3cSmrg    default:
1430145b7b3cSmrg	if (len == 0) {
1431145b7b3cSmrg	    if (!IsModifierKey(keysym))  /* it's not a modifier */
1432145b7b3cSmrg		XBell(XtDisplay(ctxw), 60);
1433145b7b3cSmrg	    return;
1434145b7b3cSmrg	} else
1435145b7b3cSmrg	    break;
1436145b7b3cSmrg    }
1437145b7b3cSmrg
1438578741aaSmrg    if (ctx->login.state == PROMPTING) {
1439145b7b3cSmrg	if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >=
1440145b7b3cSmrg	     (VALUE_TEXT_MAX(ctx,promptNum) - 1))) {
1441145b7b3cSmrg	    len = VALUE_TEXT_MAX(ctx,promptNum) -
1442145b7b3cSmrg		strlen(VALUE_TEXT(ctx, promptNum)) - 2;
1443145b7b3cSmrg	}
1444145b7b3cSmrg    }
1445145b7b3cSmrg    EraseCursor (ctx);
1446145b7b3cSmrg    RemoveFail (ctx);
1447145b7b3cSmrg    if (len != 0)
1448145b7b3cSmrg    {
1449145b7b3cSmrg	if (ctx->login.state == PROMPTING) {
1450145b7b3cSmrg	    EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1451145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len,
1452145b7b3cSmrg		    VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1453145b7b3cSmrg		    strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1);
1454145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1455145b7b3cSmrg		     strbuf, len);
1456145b7b3cSmrg	    DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1457145b7b3cSmrg	    PROMPT_CURSOR(ctx, promptNum) += len;
1458145b7b3cSmrg	}
1459145b7b3cSmrg    }
1460145b7b3cSmrg    XorCursor (ctx);
1461145b7b3cSmrg}
1462145b7b3cSmrg
1463145b7b3cSmrg
1464145b7b3cSmrg/**** Copied from xclock.c - original author: Keith Packard ****/
1465145b7b3cSmrg#ifdef USE_XFT
1466145b7b3cSmrgstatic XtConvertArgRec xftColorConvertArgs[] = {
1467145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1468145b7b3cSmrg     sizeof(Screen *)},
1469145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
1470145b7b3cSmrg     sizeof(Colormap)}
1471145b7b3cSmrg};
1472145b7b3cSmrg
1473578741aaSmrg# define	donestr(type, value, tstr) \
1474145b7b3cSmrg	{							\
1475145b7b3cSmrg	    if (toVal->addr != NULL) {				\
1476145b7b3cSmrg		if (toVal->size < sizeof(type)) {		\
1477145b7b3cSmrg		    toVal->size = sizeof(type);			\
1478145b7b3cSmrg		    XtDisplayStringConversionWarning(dpy, 	\
1479145b7b3cSmrg			(char*) fromVal->addr, tstr);		\
1480145b7b3cSmrg		    return False;				\
1481145b7b3cSmrg		}						\
1482145b7b3cSmrg		*(type*)(toVal->addr) = (value);		\
1483145b7b3cSmrg	    }							\
1484145b7b3cSmrg	    else {						\
1485145b7b3cSmrg		static type static_val;				\
1486145b7b3cSmrg		static_val = (value);				\
1487145b7b3cSmrg		toVal->addr = (XPointer)&static_val;		\
1488145b7b3cSmrg	    }							\
1489145b7b3cSmrg	    toVal->size = sizeof(type);				\
1490145b7b3cSmrg	    return True;					\
1491145b7b3cSmrg	}
1492145b7b3cSmrg
1493145b7b3cSmrgstatic void
1494145b7b3cSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1495145b7b3cSmrg		 XrmValuePtr args, Cardinal *num_args)
1496145b7b3cSmrg{
1497145b7b3cSmrg    Screen	*screen;
1498145b7b3cSmrg    Colormap	colormap;
1499145b7b3cSmrg    XftColor	*color;
1500578741aaSmrg
1501145b7b3cSmrg    if (*num_args != 2)
1502145b7b3cSmrg    {
1503145b7b3cSmrg	XtAppErrorMsg (app,
1504145b7b3cSmrg		       "freeXftColor", "wrongParameters",
1505145b7b3cSmrg		       "XtToolkitError",
1506145b7b3cSmrg		       "Freeing an XftColor requires screen and colormap arguments",
1507145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1508145b7b3cSmrg	return;
1509145b7b3cSmrg    }
1510145b7b3cSmrg
1511145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1512145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1513145b7b3cSmrg    color = (XftColor *) toVal->addr;
1514145b7b3cSmrg    XftColorFree (DisplayOfScreen (screen),
1515145b7b3cSmrg		  DefaultVisual (DisplayOfScreen (screen),
1516145b7b3cSmrg				 XScreenNumberOfScreen (screen)),
1517145b7b3cSmrg		  colormap, color);
1518145b7b3cSmrg}
1519578741aaSmrg
1520145b7b3cSmrgstatic Boolean
1521145b7b3cSmrgXmuCvtStringToXftColor(Display *dpy,
1522145b7b3cSmrg		       XrmValue *args, Cardinal *num_args,
1523145b7b3cSmrg		       XrmValue *fromVal, XrmValue *toVal,
1524145b7b3cSmrg		       XtPointer *converter_data)
1525145b7b3cSmrg{
1526145b7b3cSmrg    char	    *spec;
1527145b7b3cSmrg    XRenderColor    renderColor;
1528145b7b3cSmrg    XftColor	    xftColor;
1529145b7b3cSmrg    Screen	    *screen;
1530145b7b3cSmrg    Colormap	    colormap;
1531578741aaSmrg
1532145b7b3cSmrg    if (*num_args != 2)
1533145b7b3cSmrg    {
1534145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1535145b7b3cSmrg		       "cvtStringToXftColor", "wrongParameters",
1536145b7b3cSmrg		       "XtToolkitError",
1537145b7b3cSmrg		       "String to render color conversion needs screen and colormap arguments",
1538145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1539145b7b3cSmrg	return False;
1540145b7b3cSmrg    }
1541145b7b3cSmrg
1542145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1543145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1544145b7b3cSmrg
1545145b7b3cSmrg    spec = (char *) fromVal->addr;
1546145b7b3cSmrg    if (strcasecmp (spec, XtDefaultForeground) == 0)
1547145b7b3cSmrg    {
1548145b7b3cSmrg	renderColor.red = 0;
1549145b7b3cSmrg	renderColor.green = 0;
1550145b7b3cSmrg	renderColor.blue = 0;
1551145b7b3cSmrg	renderColor.alpha = 0xffff;
1552145b7b3cSmrg    }
1553145b7b3cSmrg    else if (strcasecmp (spec, XtDefaultBackground) == 0)
1554145b7b3cSmrg    {
1555145b7b3cSmrg	renderColor.red = 0xffff;
1556145b7b3cSmrg	renderColor.green = 0xffff;
1557145b7b3cSmrg	renderColor.blue = 0xffff;
1558145b7b3cSmrg	renderColor.alpha = 0xffff;
1559145b7b3cSmrg    }
1560145b7b3cSmrg    else if (!XRenderParseColor (dpy, spec, &renderColor))
1561145b7b3cSmrg	return False;
1562578741aaSmrg    if (!XftColorAllocValue (dpy,
1563145b7b3cSmrg			     DefaultVisual (dpy,
1564145b7b3cSmrg					    XScreenNumberOfScreen (screen)),
1565145b7b3cSmrg			     colormap,
1566145b7b3cSmrg			     &renderColor,
1567145b7b3cSmrg			     &xftColor))
1568145b7b3cSmrg	return False;
1569578741aaSmrg
1570145b7b3cSmrg    donestr (XftColor, xftColor, XtRXftColor);
1571145b7b3cSmrg}
1572145b7b3cSmrg
1573145b7b3cSmrgstatic void
1574145b7b3cSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1575145b7b3cSmrg		XrmValuePtr args, Cardinal *num_args)
1576145b7b3cSmrg{
1577145b7b3cSmrg    Screen  *screen;
1578145b7b3cSmrg    XftFont *font;
1579578741aaSmrg
1580145b7b3cSmrg    if (*num_args != 1)
1581145b7b3cSmrg    {
1582145b7b3cSmrg	XtAppErrorMsg (app,
1583145b7b3cSmrg		       "freeXftFont", "wrongParameters",
1584145b7b3cSmrg		       "XtToolkitError",
1585145b7b3cSmrg		       "Freeing an XftFont requires screen argument",
1586145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1587145b7b3cSmrg	return;
1588145b7b3cSmrg    }
1589145b7b3cSmrg
1590145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1591145b7b3cSmrg    font = *((XftFont **) toVal->addr);
1592145b7b3cSmrg    if (font)
1593145b7b3cSmrg	XftFontClose (DisplayOfScreen (screen), font);
1594145b7b3cSmrg}
1595145b7b3cSmrg
1596145b7b3cSmrgstatic Boolean
1597145b7b3cSmrgXmuCvtStringToXftFont(Display *dpy,
1598145b7b3cSmrg		      XrmValue *args, Cardinal *num_args,
1599145b7b3cSmrg		      XrmValue *fromVal, XrmValue *toVal,
1600145b7b3cSmrg		      XtPointer *converter_data)
1601145b7b3cSmrg{
1602145b7b3cSmrg    char    *name;
1603145b7b3cSmrg    XftFont *font;
1604145b7b3cSmrg    Screen  *screen;
1605578741aaSmrg
1606145b7b3cSmrg    if (*num_args != 1)
1607145b7b3cSmrg    {
1608145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1609145b7b3cSmrg		       "cvtStringToXftFont", "wrongParameters",
1610145b7b3cSmrg		       "XtToolkitError",
1611145b7b3cSmrg		       "String to XftFont conversion needs screen argument",
1612145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1613145b7b3cSmrg	return False;
1614145b7b3cSmrg    }
1615145b7b3cSmrg
1616145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1617145b7b3cSmrg    name = (char *) fromVal->addr;
1618578741aaSmrg
1619145b7b3cSmrg    font = XftFontOpenName (dpy,
1620145b7b3cSmrg			    XScreenNumberOfScreen (screen),
1621145b7b3cSmrg			    name);
1622145b7b3cSmrg    if (font)
1623145b7b3cSmrg    {
1624145b7b3cSmrg	donestr (XftFont *, font, XtRXftFont);
1625145b7b3cSmrg    }
1626145b7b3cSmrg    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
1627145b7b3cSmrg    return False;
1628145b7b3cSmrg}
1629145b7b3cSmrg
1630145b7b3cSmrgstatic XtConvertArgRec xftFontConvertArgs[] = {
1631145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1632145b7b3cSmrg     sizeof(Screen *)},
1633145b7b3cSmrg};
1634145b7b3cSmrg
1635145b7b3cSmrg
1636145b7b3cSmrgstatic int
1637145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len)
1638145b7b3cSmrg{
1639145b7b3cSmrg    XGlyphInfo  extents;
1640145b7b3cSmrg
1641145b7b3cSmrg    XftTextExtents8 (dpy, font, string, len, &extents);
1642145b7b3cSmrg
1643145b7b3cSmrg    return extents.xOff;
1644145b7b3cSmrg}
1645145b7b3cSmrg
1646145b7b3cSmrg#endif /* USE_XFT */
1647145b7b3cSmrg
1648578741aaSmrgstatic void
1649145b7b3cSmrgClassInitialize(void)
1650145b7b3cSmrg{
1651145b7b3cSmrg#ifdef USE_XFT
1652578741aaSmrg    XtSetTypeConverter (XtRString, XtRXftColor,
1653578741aaSmrg			XmuCvtStringToXftColor,
1654145b7b3cSmrg			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
1655145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftColor);
1656145b7b3cSmrg    XtSetTypeConverter (XtRString, XtRXftFont,
1657145b7b3cSmrg			XmuCvtStringToXftFont,
1658145b7b3cSmrg			xftFontConvertArgs, XtNumber(xftFontConvertArgs),
1659145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftFont);
1660145b7b3cSmrg#endif /* USE_XFT */
1661145b7b3cSmrg}
1662145b7b3cSmrg/**** End of portion borrowed from xclock ****/
1663145b7b3cSmrg
1664145b7b3cSmrg/* ARGSUSED */
1665145b7b3cSmrgstatic void Initialize (
1666145b7b3cSmrg    Widget greq,
1667145b7b3cSmrg    Widget gnew,
1668145b7b3cSmrg    ArgList args,
1669145b7b3cSmrg    Cardinal *num_args)
1670145b7b3cSmrg{
1671145b7b3cSmrg    LoginWidget w = (LoginWidget)gnew;
1672145b7b3cSmrg    XtGCMask	valuemask, xvaluemask;
1673145b7b3cSmrg    XGCValues	myXGCV;
1674145b7b3cSmrg    Arg		position[2];
1675145b7b3cSmrg    Position	x, y;
1676145b7b3cSmrg#ifdef USE_XINERAMA
1677145b7b3cSmrg    XineramaScreenInfo *screens;
1678145b7b3cSmrg    int                 s_num;
1679145b7b3cSmrg#endif
1680145b7b3cSmrg    int 	rv = 0;
1681578741aaSmrg
1682145b7b3cSmrg    myXGCV.foreground = w->login.hipixel;
1683145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1684145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1685145b7b3cSmrg    w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV);
1686145b7b3cSmrg
1687145b7b3cSmrg    myXGCV.foreground = w->login.shdpixel;
1688145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1689145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1690145b7b3cSmrg    w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV);
1691145b7b3cSmrg
1692145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text);
1693145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1694145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1695145b7b3cSmrg#ifndef USE_XFT
1696145b7b3cSmrg    if (w->login.textFont) {
1697145b7b3cSmrg	myXGCV.font = w->login.textFont->fid;
1698145b7b3cSmrg	valuemask |= GCFont;
1699145b7b3cSmrg    }
1700578741aaSmrg#endif
1701145b7b3cSmrg    w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
1702145b7b3cSmrg    myXGCV.foreground = w->core.background_pixel;
1703145b7b3cSmrg    w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
1704145b7b3cSmrg
1705145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text) ^ w->core.background_pixel;
1706145b7b3cSmrg    myXGCV.function = GXxor;
1707145b7b3cSmrg    xvaluemask = valuemask | GCFunction;
1708145b7b3cSmrg    w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1709145b7b3cSmrg
1710145b7b3cSmrg#ifndef USE_XFT
1711145b7b3cSmrg    /*
1712145b7b3cSmrg     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
1713145b7b3cSmrg     * returns the curently contained font.
1714145b7b3cSmrg     */
1715145b7b3cSmrg
1716145b7b3cSmrg    if (w->login.textFont == NULL)
1717145b7b3cSmrg	w->login.textFont = XQueryFont (XtDisplay (w),
1718145b7b3cSmrg		XGContextFromGC (XDefaultGCOfScreen (XtScreen (w))));
1719145b7b3cSmrg
1720145b7b3cSmrg    xvaluemask = valuemask;
1721145b7b3cSmrg    if (w->login.promptFont == NULL)
1722145b7b3cSmrg        w->login.promptFont = w->login.textFont;
1723145b7b3cSmrg    else
1724145b7b3cSmrg	xvaluemask |= GCFont;
1725145b7b3cSmrg
1726145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(prompt);
1727145b7b3cSmrg    myXGCV.font = w->login.promptFont->fid;
1728145b7b3cSmrg    w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1729145b7b3cSmrg
1730145b7b3cSmrg    xvaluemask = valuemask;
1731145b7b3cSmrg    if (w->login.greetFont == NULL)
1732145b7b3cSmrg    	w->login.greetFont = w->login.textFont;
1733145b7b3cSmrg    else
1734145b7b3cSmrg	xvaluemask |= GCFont;
1735145b7b3cSmrg
1736145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(greet);
1737145b7b3cSmrg    myXGCV.font = w->login.greetFont->fid;
1738145b7b3cSmrg    w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1739145b7b3cSmrg
1740145b7b3cSmrg    xvaluemask = valuemask;
1741145b7b3cSmrg    if (w->login.failFont == NULL)
1742145b7b3cSmrg	w->login.failFont = w->login.textFont;
1743145b7b3cSmrg    else
1744145b7b3cSmrg	xvaluemask |= GCFont;
1745145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(fail);
1746145b7b3cSmrg    myXGCV.font = w->login.failFont->fid;
1747145b7b3cSmrg    w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1748145b7b3cSmrg#endif /* USE_XFT */
1749145b7b3cSmrg
1750145b7b3cSmrg#ifdef XPM
1751145b7b3cSmrg    w->login.logoValid = False;
1752145b7b3cSmrg
1753145b7b3cSmrg    if (NULL != w->login.logoFileName)
1754145b7b3cSmrg    {
1755145b7b3cSmrg        XpmAttributes myAttributes = { 0 };
1756145b7b3cSmrg        Window tmpWindow = { 0 };
1757145b7b3cSmrg        struct stat myBuffer = { 0 };
1758145b7b3cSmrg        unsigned int myPixmapDepth = 0;
1759145b7b3cSmrg
1760145b7b3cSmrg        if (0 != stat(w->login.logoFileName, &myBuffer))
1761145b7b3cSmrg        {
1762145b7b3cSmrg            LogError("Unable to stat() pixmap file %s\n",
1763145b7b3cSmrg                w->login.logoFileName);
1764145b7b3cSmrg            w->login.logoValid = False;
1765145b7b3cSmrg            goto SkipXpmLoad;
1766145b7b3cSmrg        }
1767145b7b3cSmrg
1768145b7b3cSmrg        myAttributes.valuemask |= XpmReturnPixels;
1769145b7b3cSmrg        myAttributes.valuemask |= XpmReturnExtensions;
1770145b7b3cSmrg
1771145b7b3cSmrg        rv = XpmReadFileToPixmap(XtDisplay(w),		/* display */
1772145b7b3cSmrg	     RootWindowOfScreen(XtScreen(w)),		/* window */
1773145b7b3cSmrg	     w->login.logoFileName,			/* XPM filename */
1774145b7b3cSmrg	     &(w->login.logoPixmap),			/* pixmap */
1775145b7b3cSmrg	     &(w->login.logoMask),			/* pixmap mask */
1776145b7b3cSmrg	     &myAttributes);				/* XPM attributes */
1777578741aaSmrg
1778145b7b3cSmrg	if ( rv < 0 )
1779145b7b3cSmrg	{
1780145b7b3cSmrg	    LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName,
1781145b7b3cSmrg		     XpmGetErrorString(rv));
1782145b7b3cSmrg	    goto SkipXpmLoad;
1783145b7b3cSmrg	}
1784145b7b3cSmrg
1785145b7b3cSmrg	w->login.logoValid = True;
1786145b7b3cSmrg
1787145b7b3cSmrg        XGetGeometry(XtDisplay(w), w->login.logoPixmap,
1788145b7b3cSmrg            &tmpWindow,
1789145b7b3cSmrg            &(w->login.logoX),
1790145b7b3cSmrg            &(w->login.logoY),
1791145b7b3cSmrg            &(w->login.logoWidth),
1792145b7b3cSmrg            &(w->login.logoHeight),
1793145b7b3cSmrg            &(w->login.logoBorderWidth),
1794145b7b3cSmrg            &myPixmapDepth);
1795145b7b3cSmrg    } else {
1796145b7b3cSmrg	w->login.logoX = 0;
1797145b7b3cSmrg	w->login.logoY = 0;
1798145b7b3cSmrg	w->login.logoWidth = 0;
1799145b7b3cSmrg	w->login.logoHeight = 0;
1800145b7b3cSmrg	w->login.logoBorderWidth = 0;
1801145b7b3cSmrg    }
1802145b7b3cSmrg
1803145b7b3cSmrg
1804145b7b3cSmrgSkipXpmLoad:
1805145b7b3cSmrg#endif /* XPM */
1806145b7b3cSmrg    w->login.data.name[0] = '\0';
1807145b7b3cSmrg    w->login.data.passwd[0] = '\0';
1808145b7b3cSmrg    w->login.state = INITIALIZING;
1809145b7b3cSmrg    w->login.activePrompt = LOGIN_PROMPT_USERNAME;
1810145b7b3cSmrg    w->login.failUp = 0;
1811145b7b3cSmrg    w->login.fail = (char *) w->login.failMsg;
1812145b7b3cSmrg
1813145b7b3cSmrg    /* Set prompt defaults */
1814145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= NULL;
1815145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.namePrompt;
1816145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.data.name;
1817145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME)	= sizeof(w->login.data.name);
1818145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME)	= 0;
1819578741aaSmrg
1820145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= NULL;
1821145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.passwdPrompt;
1822145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.data.passwd;
1823145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD)	= sizeof(w->login.data.passwd);
1824145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD)	= 0;
1825145b7b3cSmrg
1826145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False);
1827145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False);
1828578741aaSmrg
1829145b7b3cSmrg    if (w->core.width == 0)
1830145b7b3cSmrg	w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
1831145b7b3cSmrg    if (w->core.height == 0) {
1832145b7b3cSmrg	int fy = FAIL_Y(w);
1833145b7b3cSmrg	int pady = PAD_Y(w);
1834145b7b3cSmrg
1835145b7b3cSmrg#ifndef XPM
1836145b7b3cSmrg	w->core.height = fy + pady;	/* for stupid compilers */
1837145b7b3cSmrg#else
1838145b7b3cSmrg/*	w->core.height = fy + pady;	* for stupid compilers */
1839145b7b3cSmrg
1840145b7b3cSmrg        w->core.height = max(fy + pady,
1841145b7b3cSmrg            (w->login.logoHeight + (2*w->login.logoPadding)) + pady);
1842578741aaSmrg
1843145b7b3cSmrg#endif /* XPM */
1844145b7b3cSmrg    }
1845145b7b3cSmrg#ifdef USE_XINERAMA
1846145b7b3cSmrg    if (
1847145b7b3cSmrg	XineramaIsActive(XtDisplay(w)) &&
1848145b7b3cSmrg	(screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL
1849145b7b3cSmrg       )
1850145b7b3cSmrg    {
1851145b7b3cSmrg	if ((x = w->core.x) == -1)
1852145b7b3cSmrg	    x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2;
1853145b7b3cSmrg	if ((y = w->core.y) == -1)
1854145b7b3cSmrg	    y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3;
1855578741aaSmrg
1856145b7b3cSmrg	XFree(screens);
1857145b7b3cSmrg    }
1858145b7b3cSmrg    else
1859145b7b3cSmrg#endif
1860145b7b3cSmrg    {
1861145b7b3cSmrg	if ((x = w->core.x) == -1)
1862145b7b3cSmrg	    x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2;
1863145b7b3cSmrg	if ((y = w->core.y) == -1)
1864145b7b3cSmrg	    y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3;
1865145b7b3cSmrg    }
1866145b7b3cSmrg    XtSetArg (position[0], XtNx, x);
1867145b7b3cSmrg    XtSetArg (position[1], XtNy, y);
1868145b7b3cSmrg    XtSetValues (XtParent (w), position, (Cardinal) 2);
1869145b7b3cSmrg
1870145b7b3cSmrg    w->login.state = PROMPTING;
1871145b7b3cSmrg}
1872145b7b3cSmrg
1873578741aaSmrg
1874145b7b3cSmrgstatic void Realize (
1875145b7b3cSmrg     Widget gw,
1876145b7b3cSmrg     XtValueMask *valueMask,
1877145b7b3cSmrg     XSetWindowAttributes *attrs)
1878145b7b3cSmrg{
1879145b7b3cSmrg    LoginWidget	w = (LoginWidget) gw;
1880145b7b3cSmrg    Cursor cursor;
1881145b7b3cSmrg
1882145b7b3cSmrg    XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
1883145b7b3cSmrg		     *valueMask, attrs );
1884145b7b3cSmrg    InitI18N(gw);
1885145b7b3cSmrg
1886145b7b3cSmrg#ifdef USE_XFT
1887145b7b3cSmrg    w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w),
1888145b7b3cSmrg	   DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))),
1889145b7b3cSmrg				   w->core.colormap);
1890145b7b3cSmrg
1891145b7b3cSmrg#endif
1892145b7b3cSmrg
1893145b7b3cSmrg    cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr);
1894145b7b3cSmrg    XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor);
1895145b7b3cSmrg
1896145b7b3cSmrg#ifdef XPM
1897578741aaSmrg    /*
1898145b7b3cSmrg     * Check if Pixmap was valid
1899145b7b3cSmrg     */
1900145b7b3cSmrg    if (True == w->login.logoValid)
1901145b7b3cSmrg    {
1902145b7b3cSmrg        /*
1903578741aaSmrg         * Create pixmap window
1904145b7b3cSmrg         */
1905145b7b3cSmrg        {
1906145b7b3cSmrg            unsigned long valueMask = CWBackPixel | CWBackPixmap;
1907145b7b3cSmrg            XSetWindowAttributes windowAttributes = { 0 };
1908145b7b3cSmrg
1909145b7b3cSmrg            windowAttributes.background_pixel = w->core.background_pixel;
1910145b7b3cSmrg            windowAttributes.background_pixmap = None;
1911145b7b3cSmrg
1912145b7b3cSmrg            w->login.logoWindow = XCreateWindow(XtDisplay(w),
1913145b7b3cSmrg                XtWindow(w),
1914145b7b3cSmrg                w->core.width - w->login.outframewidth -
1915145b7b3cSmrg                    w->login.logoWidth - w->login.logoPadding,
1916145b7b3cSmrg                (w->core.height - w->login.logoHeight) /2,
1917145b7b3cSmrg                w->login.logoWidth, w->login.logoHeight, 0,
1918145b7b3cSmrg                CopyFromParent, InputOutput, CopyFromParent,
1919145b7b3cSmrg                valueMask, &windowAttributes);
1920145b7b3cSmrg        }
1921145b7b3cSmrg
1922145b7b3cSmrg        /*
1923145b7b3cSmrg         * check if we can use shape extension
1924145b7b3cSmrg         */
1925145b7b3cSmrg        if (True == w->login.useShape)
1926145b7b3cSmrg        {
1927145b7b3cSmrg            int foo, bar;
1928145b7b3cSmrg
1929145b7b3cSmrg            if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE)
1930145b7b3cSmrg            {
1931145b7b3cSmrg                XShapeCombineMask(XtDisplay(w), w->login.logoWindow,
1932145b7b3cSmrg                    ShapeBounding, w->login.logoX, w->login.logoY,
1933145b7b3cSmrg                    w->login.logoMask, ShapeSet);
1934145b7b3cSmrg            }
1935145b7b3cSmrg        }
1936145b7b3cSmrg
1937145b7b3cSmrg        XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow,
1938145b7b3cSmrg            w->login.logoPixmap);
1939145b7b3cSmrg        XMapWindow(XtDisplay(w), w->login.logoWindow);
1940145b7b3cSmrg    }
1941145b7b3cSmrg#endif /* XPM */
1942145b7b3cSmrg}
1943145b7b3cSmrg
1944145b7b3cSmrgstatic void Destroy (Widget gw)
1945145b7b3cSmrg{
1946145b7b3cSmrg    LoginWidget w = (LoginWidget)gw;
1947145b7b3cSmrg    bzero (w->login.data.name, NAME_LEN);
1948145b7b3cSmrg    bzero (w->login.data.passwd, PASSWORD_LEN);
1949145b7b3cSmrg
1950145b7b3cSmrg    if (PROMPT_TEXT(w,0) != NULL)
1951145b7b3cSmrg	XtFree(PROMPT_TEXT(w,0));
1952145b7b3cSmrg    if (PROMPT_TEXT(w,1) != NULL)
1953145b7b3cSmrg	XtFree(PROMPT_TEXT(w,1));
1954145b7b3cSmrg
1955145b7b3cSmrg#ifdef USE_XFT
1956145b7b3cSmrg    if (w->login.draw) {
1957145b7b3cSmrg	XftDrawDestroy(w->login.draw);
1958145b7b3cSmrg	w->login.draw = NULL;
1959145b7b3cSmrg    }
1960578741aaSmrg#endif
1961578741aaSmrg
1962145b7b3cSmrg    XtReleaseGC(gw, w->login.textGC);
1963145b7b3cSmrg    XtReleaseGC(gw, w->login.bgGC);
1964145b7b3cSmrg    XtReleaseGC(gw, w->login.xorGC);
1965145b7b3cSmrg#ifndef USE_XFT
1966145b7b3cSmrg    XtReleaseGC(gw, w->login.promptGC);
1967145b7b3cSmrg    XtReleaseGC(gw, w->login.greetGC);
1968145b7b3cSmrg    XtReleaseGC(gw, w->login.failGC);
1969145b7b3cSmrg#endif
1970145b7b3cSmrg    XtReleaseGC(gw, w->login.hiGC);
1971145b7b3cSmrg    XtReleaseGC(gw, w->login.shdGC);
1972145b7b3cSmrg
1973145b7b3cSmrg#ifdef XPM
1974145b7b3cSmrg    if (True == w->login.logoValid)
1975145b7b3cSmrg    {
1976145b7b3cSmrg        if (w->login.logoPixmap != 0)
1977145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoPixmap);
1978145b7b3cSmrg
1979145b7b3cSmrg        if (w->login.logoMask != 0)
1980145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoMask);
1981145b7b3cSmrg    }
1982145b7b3cSmrg#endif /* XPM */
1983145b7b3cSmrg}
1984145b7b3cSmrg
1985145b7b3cSmrg/* ARGSUSED */
1986145b7b3cSmrgstatic void Redisplay(
1987145b7b3cSmrg     Widget gw,
1988145b7b3cSmrg     XEvent *event,
1989145b7b3cSmrg     Region region)
1990145b7b3cSmrg{
1991145b7b3cSmrg    draw_it ((LoginWidget) gw);
1992145b7b3cSmrg}
1993145b7b3cSmrg
1994145b7b3cSmrg/*ARGSUSED*/
1995145b7b3cSmrgstatic Boolean SetValues (
1996145b7b3cSmrg    Widget  current,
1997145b7b3cSmrg    Widget  request,
1998145b7b3cSmrg    Widget  new,
1999145b7b3cSmrg    ArgList args,
2000145b7b3cSmrg    Cardinal *num_args)
2001145b7b3cSmrg{
2002145b7b3cSmrg    LoginWidget currentL, newL;
2003578741aaSmrg
2004145b7b3cSmrg    currentL = (LoginWidget) current;
2005145b7b3cSmrg    newL = (LoginWidget) new;
2006145b7b3cSmrg    if (GREETING (currentL) != GREETING (newL))
2007145b7b3cSmrg	return True;
2008145b7b3cSmrg    return False;
2009145b7b3cSmrg}
2010145b7b3cSmrg
2011145b7b3cSmrgstatic
2012145b7b3cSmrgchar defaultLoginTranslations [] =
2013145b7b3cSmrg"Ctrl<Key>H:	delete-previous-character() \n"
2014145b7b3cSmrg"Ctrl<Key>D:	delete-character() \n"
2015145b7b3cSmrg"Ctrl<Key>B:	move-backward-character() \n"
2016145b7b3cSmrg"Ctrl<Key>F:	move-forward-character() \n"
2017145b7b3cSmrg"Ctrl<Key>A:	move-to-begining() \n"
2018145b7b3cSmrg"Ctrl<Key>E:	move-to-end() \n"
2019145b7b3cSmrg"Ctrl<Key>K:	erase-to-end-of-line() \n"
2020145b7b3cSmrg"Ctrl<Key>U:	erase-line() \n"
2021145b7b3cSmrg"Ctrl<Key>X:	erase-line() \n"
2022145b7b3cSmrg"Ctrl<Key>C:	restart-session() \n"
2023145b7b3cSmrg"Ctrl<Key>\\\\:	abort-session() \n"
2024145b7b3cSmrg":Ctrl<Key>plus:	allow-all-access() \n"
2025145b7b3cSmrg"<Key>BackSpace:	delete-previous-character() \n"
2026145b7b3cSmrg#ifdef linux
2027145b7b3cSmrg"<Key>Delete:	delete-character() \n"
2028145b7b3cSmrg#else
2029145b7b3cSmrg"<Key>Delete:	delete-previous-character() \n"
2030145b7b3cSmrg#endif
2031145b7b3cSmrg"<Key>Return:	finish-field() \n"
2032145b7b3cSmrg"<Key>Tab:	tab-field() \n"
2033145b7b3cSmrg"<KeyPress>:	insert-char()"
2034145b7b3cSmrg;
2035145b7b3cSmrg
2036145b7b3cSmrgstatic
2037145b7b3cSmrgXtActionsRec loginActionsTable [] = {
2038145b7b3cSmrg  {"delete-previous-character",	DeleteBackwardChar},
2039145b7b3cSmrg  {"delete-character",		DeleteForwardChar},
2040145b7b3cSmrg  {"move-backward-character",	MoveBackwardChar},
2041145b7b3cSmrg  {"move-forward-character",	MoveForwardChar},
2042145b7b3cSmrg  {"move-to-begining",		MoveToBegining},
2043145b7b3cSmrg  {"move-to-end",		MoveToEnd},
2044145b7b3cSmrg  {"erase-to-end-of-line",	EraseToEndOfLine},
2045145b7b3cSmrg  {"erase-line",		EraseLine},
2046145b7b3cSmrg  {"finish-field", 		FinishField},
2047145b7b3cSmrg  {"tab-field", 		TabField},
2048145b7b3cSmrg  {"abort-session",		AbortSession},
2049145b7b3cSmrg  {"abort-display",		AbortDisplay},
2050145b7b3cSmrg  {"restart-session",		RestartSession},
2051145b7b3cSmrg  {"insert-char", 		InsertChar},
2052145b7b3cSmrg  {"set-session-argument",	SetSessionArgument},
2053145b7b3cSmrg  {"allow-all-access",		AllowAccess},
2054145b7b3cSmrg};
2055145b7b3cSmrg
2056145b7b3cSmrgLoginClassRec loginClassRec = {
2057145b7b3cSmrg    { /* core fields */
2058145b7b3cSmrg    /* superclass		*/	&widgetClassRec,
2059145b7b3cSmrg    /* class_name		*/	"Login",
2060145b7b3cSmrg    /* size			*/	sizeof(LoginRec),
2061145b7b3cSmrg    /* class_initialize		*/	ClassInitialize,
2062145b7b3cSmrg    /* class_part_initialize	*/	NULL,
2063145b7b3cSmrg    /* class_inited		*/	FALSE,
2064145b7b3cSmrg    /* initialize		*/	Initialize,
2065145b7b3cSmrg    /* initialize_hook		*/	NULL,
2066145b7b3cSmrg    /* realize			*/	Realize,
2067145b7b3cSmrg    /* actions			*/	loginActionsTable,
2068145b7b3cSmrg    /* num_actions		*/	XtNumber (loginActionsTable),
2069145b7b3cSmrg    /* resources		*/	resources,
2070145b7b3cSmrg    /* num_resources		*/	XtNumber(resources),
2071145b7b3cSmrg    /* xrm_class		*/	NULLQUARK,
2072145b7b3cSmrg    /* compress_motion		*/	TRUE,
2073145b7b3cSmrg    /* compress_exposure	*/	TRUE,
2074145b7b3cSmrg    /* compress_enterleave	*/	TRUE,
2075145b7b3cSmrg    /* visible_interest		*/	FALSE,
2076145b7b3cSmrg    /* destroy			*/	Destroy,
2077145b7b3cSmrg    /* resize			*/	NULL,
2078145b7b3cSmrg    /* expose			*/	Redisplay,
2079145b7b3cSmrg    /* set_values		*/	SetValues,
2080145b7b3cSmrg    /* set_values_hook		*/	NULL,
2081145b7b3cSmrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
2082145b7b3cSmrg    /* get_values_hook		*/	NULL,
2083145b7b3cSmrg    /* accept_focus		*/	NULL,
2084145b7b3cSmrg    /* version			*/	XtVersion,
2085145b7b3cSmrg    /* callback_private		*/	NULL,
2086145b7b3cSmrg    /* tm_table			*/	defaultLoginTranslations,
2087145b7b3cSmrg    /* query_geometry		*/	XtInheritQueryGeometry,
2088145b7b3cSmrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
2089145b7b3cSmrg    /* extension		*/	NULL
2090145b7b3cSmrg    }
2091145b7b3cSmrg};
2092145b7b3cSmrg
2093145b7b3cSmrgWidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
2094