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