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