Login.c revision b7d26471
1145b7b3cSmrg/*
2145b7b3cSmrg
3145b7b3cSmrgCopyright 1988, 1998  The Open Group
4145b7b3cSmrg
5145b7b3cSmrgPermission to use, copy, modify, distribute, and sell this software and its
6145b7b3cSmrgdocumentation for any purpose is hereby granted without fee, provided that
7145b7b3cSmrgthe above copyright notice appear in all copies and that both that
8145b7b3cSmrgcopyright notice and this permission notice appear in supporting
9145b7b3cSmrgdocumentation.
10145b7b3cSmrg
11145b7b3cSmrgThe above copyright notice and this permission notice shall be included
12145b7b3cSmrgin all copies or substantial portions of the Software.
13145b7b3cSmrg
14145b7b3cSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15145b7b3cSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16145b7b3cSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17145b7b3cSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18145b7b3cSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19145b7b3cSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20145b7b3cSmrgOTHER DEALINGS IN THE SOFTWARE.
21145b7b3cSmrg
22145b7b3cSmrgExcept as contained in this notice, the name of The Open Group shall
23145b7b3cSmrgnot be used in advertising or otherwise to promote the sale, use or
24145b7b3cSmrgother dealings in this Software without prior written authorization
25145b7b3cSmrgfrom The Open Group.
26145b7b3cSmrg
27145b7b3cSmrg*/
285ffd6003Smrg/*
29629baa8cSmrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
30145b7b3cSmrg *
31145b7b3cSmrg * Permission is hereby granted, free of charge, to any person obtaining a
325ffd6003Smrg * copy of this software and associated documentation files (the "Software"),
335ffd6003Smrg * to deal in the Software without restriction, including without limitation
345ffd6003Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
355ffd6003Smrg * and/or sell copies of the Software, and to permit persons to whom the
365ffd6003Smrg * Software is furnished to do so, subject to the following conditions:
37145b7b3cSmrg *
385ffd6003Smrg * The above copyright notice and this permission notice (including the next
395ffd6003Smrg * paragraph) shall be included in all copies or substantial portions of the
405ffd6003Smrg * Software.
41145b7b3cSmrg *
425ffd6003Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
435ffd6003Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
445ffd6003Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
455ffd6003Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
465ffd6003Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
475ffd6003Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
485ffd6003Smrg * DEALINGS IN THE SOFTWARE.
49145b7b3cSmrg */
50145b7b3cSmrg
51145b7b3cSmrg
52145b7b3cSmrg/*
53145b7b3cSmrg * xdm - display manager daemon
54145b7b3cSmrg * Author:  Keith Packard, MIT X Consortium
55145b7b3cSmrg *
56145b7b3cSmrg * Login.c
57145b7b3cSmrg */
58145b7b3cSmrg
59578741aaSmrg#include <X11/IntrinsicP.h>
60578741aaSmrg#include <X11/StringDefs.h>
61578741aaSmrg#include <X11/keysym.h>
62578741aaSmrg#include <X11/DECkeysym.h>
63578741aaSmrg#include <X11/Xfuncs.h>
64145b7b3cSmrg
65578741aaSmrg#include <stdio.h>
66578741aaSmrg#include <ctype.h>
67578741aaSmrg#include <time.h>
68578741aaSmrg#include <string.h>
69145b7b3cSmrg
70578741aaSmrg#include "dm.h"
71578741aaSmrg#include "dm_error.h"
72578741aaSmrg#include "greet.h"
73578741aaSmrg#include "LoginP.h"
74145b7b3cSmrg
75145b7b3cSmrg#ifdef XPM
76578741aaSmrg# include <sys/stat.h>
77578741aaSmrg# include <unistd.h>
78578741aaSmrg# include <X11/Xlib.h>
79578741aaSmrg# include <X11/xpm.h>
80578741aaSmrg# include <X11/extensions/shape.h>
81145b7b3cSmrg#endif /* XPM */
82145b7b3cSmrg
83145b7b3cSmrg#include <X11/cursorfont.h>
84145b7b3cSmrg
85145b7b3cSmrg#ifdef USE_XINERAMA
86578741aaSmrg# include <X11/extensions/Xinerama.h>
87145b7b3cSmrg#endif
88145b7b3cSmrg
89b7d26471Smrg#ifdef USE_XFT
90b7d26471Smrg# include <X11/extensions/Xrender.h>
91b7d26471Smrg#endif
92b7d26471Smrg
93145b7b3cSmrg#ifndef DEBUG
94145b7b3cSmrg# define XDM_ASSERT(a)	/* do nothing */
95145b7b3cSmrg#else
96145b7b3cSmrg# if defined(__STDC__) && __STDC_VERSION__ - 0 >= 199901L
97145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
98145b7b3cSmrg	Debug("Assertion failed in %s() at file %s line %d\n", \
99145b7b3cSmrg	      __func__, __FILE__, __LINE__); }
100145b7b3cSmrg# else
101145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
102145b7b3cSmrg	Debug("Assertion failed at file %s line %d\n", __FILE__, __LINE__); }
103145b7b3cSmrg# endif
104145b7b3cSmrg#endif
105145b7b3cSmrg
106145b7b3cSmrgstatic void RedrawFail (LoginWidget w);
107145b7b3cSmrgstatic void ResetLogin (LoginWidget w);
108145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id);
109145b7b3cSmrgstatic void EraseCursor (LoginWidget w);
110145b7b3cSmrgstatic void XorCursor (LoginWidget w);
111145b7b3cSmrg
112145b7b3cSmrg#define offset(field) XtOffsetOf(LoginRec, login.field)
113145b7b3cSmrg#define goffset(field) XtOffsetOf(WidgetRec, core.field)
114145b7b3cSmrg
115145b7b3cSmrg
116145b7b3cSmrgstatic XtResource resources[] = {
117145b7b3cSmrg    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
118145b7b3cSmrg	goffset(width), XtRImmediate,	(XtPointer) 0},
119145b7b3cSmrg    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
120145b7b3cSmrg	goffset(height), XtRImmediate,	(XtPointer) 0},
121145b7b3cSmrg    {XtNx, XtCX, XtRPosition, sizeof (Position),
122145b7b3cSmrg	goffset(x), XtRImmediate,	(XtPointer) -1},
123145b7b3cSmrg    {XtNy, XtCY, XtRPosition, sizeof (Position),
124145b7b3cSmrg	goffset(y), XtRImmediate,	(XtPointer) -1},
125578741aaSmrg#ifndef USE_XFT
126145b7b3cSmrg    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
127145b7b3cSmrg        offset(textpixel), XtRString,	XtDefaultForeground},
128145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel),
129145b7b3cSmrg        offset(promptpixel), XtRString,	XtDefaultForeground},
130145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel),
131145b7b3cSmrg        offset(greetpixel), XtRString,	XtDefaultForeground},
132145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel),
133145b7b3cSmrg	offset(failpixel), XtRString,	XtDefaultForeground},
134145b7b3cSmrg#endif
135145b7b3cSmrg
136145b7b3cSmrg#ifdef DANCING
137145b7b3cSmrg/* added by Caolan McNamara */
138145b7b3cSmrg	{XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int),
139145b7b3cSmrg	offset(lastEventTime), XtRImmediate,	(XtPointer)0},
140145b7b3cSmrg/* end (caolan) */
141145b7b3cSmrg#endif /* DANCING */
142145b7b3cSmrg
143578741aaSmrg#ifdef XPM
144145b7b3cSmrg/* added by Ivan Griffin (ivan.griffin@ul.ie) */
145145b7b3cSmrg        {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*),
146145b7b3cSmrg        offset(logoFileName), XtRImmediate, (XtPointer)0},
147145b7b3cSmrg        {XtNuseShape, XtCUseShape, XtRBoolean, sizeof(Boolean),
148145b7b3cSmrg        offset(useShape), XtRImmediate, (XtPointer) True},
149145b7b3cSmrg        {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int),
150145b7b3cSmrg        offset(logoPadding), XtRImmediate, (XtPointer) 5},
151145b7b3cSmrg/* end (ivan) */
152145b7b3cSmrg#endif /* XPM */
153145b7b3cSmrg
154145b7b3cSmrg/* added by Amit Margalit */
155145b7b3cSmrg    {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel),
156145b7b3cSmrg	offset(hipixel), XtRString,	XtDefaultForeground},
157145b7b3cSmrg    {XtNshdColor, XtCForeground, XtRPixel, sizeof (Pixel),
158145b7b3cSmrg	offset(shdpixel), XtRString,	XtDefaultForeground},
159b7d26471Smrg    {XtNinpColor, XtCForeground, XtRPixel, sizeof (Pixel),
160b7d26471Smrg	offset(inppixel), XtRString,	XtDefaultBackground},
161145b7b3cSmrg    {XtNframeWidth, XtCFrameWidth, XtRInt, sizeof(int),
162145b7b3cSmrg        offset(outframewidth), XtRImmediate, (XtPointer) 1},
163145b7b3cSmrg    {XtNinnerFramesWidth, XtCFrameWidth, XtRInt, sizeof(int),
164145b7b3cSmrg        offset(inframeswidth), XtRImmediate, (XtPointer) 1},
165145b7b3cSmrg    {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int),
166145b7b3cSmrg        offset(sepwidth), XtRImmediate, (XtPointer) 1},
167145b7b3cSmrg/* end (amit) */
168145b7b3cSmrg
169578741aaSmrg#ifndef USE_XFT
170145b7b3cSmrg    {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
171629baa8cSmrg	offset (textFont), XtRString,	"*-new century schoolbook-medium-r-normal-*-180-*"},
172145b7b3cSmrg    {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
173629baa8cSmrg	offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"},
174145b7b3cSmrg    {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
175629baa8cSmrg	offset (greetFont), XtRString,	"*-new century schoolbook-bold-i-normal-*-240-*"},
176145b7b3cSmrg    {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
177145b7b3cSmrg	offset (failFont), XtRString,	"*-new century schoolbook-bold-r-normal-*-180-*"},
178145b7b3cSmrg#else /* USE_XFT */
179145b7b3cSmrg    {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
180145b7b3cSmrg        offset (textFace), XtRString, "Serif-18"},
181145b7b3cSmrg    {XtNpromptFace, XtCFace, XtRXftFont, sizeof (XftFont *),
182145b7b3cSmrg        offset (promptFace), XtRString, "Serif-18:bold"},
183145b7b3cSmrg    {XtNgreetFace, XtCFace, XtRXftFont, sizeof (XftFont *),
184145b7b3cSmrg        offset (greetFace), XtRString, "Serif-24:italic"},
185145b7b3cSmrg    {XtNfailFace, XtCFace, XtRXftFont, sizeof (XftFont *),
186145b7b3cSmrg        offset (failFace), XtRString, "Serif-18:bold"},
187145b7b3cSmrg    {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
188145b7b3cSmrg        offset(textcolor), XtRString,	XtDefaultForeground},
189145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRXftColor, sizeof(XftColor),
190145b7b3cSmrg        offset(promptcolor), XtRString,	XtDefaultForeground},
191145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRXftColor, sizeof(XftColor),
192145b7b3cSmrg        offset(greetcolor), XtRString,	XtDefaultForeground},
193145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRXftColor, sizeof (XftColor),
194145b7b3cSmrg	offset(failcolor), XtRString,	XtDefaultForeground},
195145b7b3cSmrg#endif
196145b7b3cSmrg    {XtNgreeting, XtCGreeting, XtRString, sizeof (char *),
197629baa8cSmrg	offset(greeting), XtRString, "X Window System"},
198145b7b3cSmrg    {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *),
199145b7b3cSmrg	offset(unsecure_greet), XtRString, "This is an unsecure session"},
200145b7b3cSmrg    {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *),
201145b7b3cSmrg	offset(namePrompt), XtRString, "Login:  "},
202145b7b3cSmrg    {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *),
203145b7b3cSmrg	offset(passwdPrompt), XtRString, "Password:  "},
204145b7b3cSmrg    {XtNfail, XtCFail, XtRString, sizeof (char *),
205145b7b3cSmrg	offset(failMsg), XtRString,
206629baa8cSmrg	"Login incorrect or forbidden by policy"
207145b7b3cSmrg    },
208145b7b3cSmrg    {XtNchangePasswdMessage, XtCChangePasswdMessage, XtRString,
209145b7b3cSmrg	sizeof (char *), offset(passwdChangeMsg), XtRString,
210145b7b3cSmrg	(XtPointer) "Password Change Required" },
211145b7b3cSmrg    {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int),
212145b7b3cSmrg	offset(failTimeout), XtRImmediate, (XtPointer) 10},
213145b7b3cSmrg    {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer),
214145b7b3cSmrg	offset(notify_done), XtRFunction, (XtPointer) 0},
215145b7b3cSmrg    {XtNsessionArgument, XtCSessionArgument, XtRString,	sizeof (char *),
216145b7b3cSmrg	offset(sessionArg), XtRString, (XtPointer) 0 },
217145b7b3cSmrg    {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean),
218145b7b3cSmrg	offset(secure_session), XtRImmediate, (XtPointer) False },
219145b7b3cSmrg    {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean),
220145b7b3cSmrg	offset(allow_access), XtRImmediate, (XtPointer) False },
221145b7b3cSmrg    {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean),
222145b7b3cSmrg	offset(allow_null_passwd), XtRImmediate, (XtPointer) False},
223145b7b3cSmrg    {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean),
2245ffd6003Smrg	offset(allow_root_login), XtRImmediate, (XtPointer) True},
2255ffd6003Smrg    {XtNechoPasswd, XtCEchoPasswd, XtRBoolean, sizeof(Boolean),
226629baa8cSmrg	offset(echo_passwd), XtRImmediate, (XtPointer) False},
227629baa8cSmrg    {XtNechoPasswdChar, XtCEchoPasswdChar, XtRString,	sizeof (char *),
228629baa8cSmrg	offset(echo_passwd_char), XtRString, (XtPointer) "*" }
229145b7b3cSmrg};
230145b7b3cSmrg
231145b7b3cSmrg#undef offset
232145b7b3cSmrg#undef goffset
233145b7b3cSmrg
234145b7b3cSmrg#ifdef USE_XFT
235145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Face->max_advance_width)
236145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Face->ascent)
237145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Face->descent)
238145b7b3cSmrg#else
239145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Font->max_bounds.width)
240145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Font->max_bounds.ascent)
241145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Font->max_bounds.descent)
242145b7b3cSmrg#endif
243145b7b3cSmrg
244578741aaSmrg#define TEXT_X_INC(w)		F_MAX_WIDTH(text)
245578741aaSmrg#define TEXT_Y_INC(w)		(F_ASCENT(text) + F_DESCENT(text))
246145b7b3cSmrg
247578741aaSmrg#define PROMPT_X_INC(w)	F_MAX_WIDTH(prompt)
248578741aaSmrg#define PROMPT_Y_INC(w)	(F_ASCENT(prompt) + F_DESCENT(prompt))
249145b7b3cSmrg
250578741aaSmrg#define GREET_X_INC(w)		F_MAX_WIDTH(greet)
251578741aaSmrg#define GREET_Y_INC(w)		(F_ASCENT(greet) + F_DESCENT(greet))
252145b7b3cSmrg
253578741aaSmrg#define FAIL_X_INC(w)		F_MAX_WIDTH(fail)
254578741aaSmrg#define FAIL_Y_INC(w)		(F_ASCENT(fail) + F_DESCENT(fail))
255145b7b3cSmrg
256578741aaSmrg#define Y_INC(w)	max (TEXT_Y_INC(w), PROMPT_Y_INC(w))
257145b7b3cSmrg
258145b7b3cSmrg
259578741aaSmrg#define PROMPT_TEXT(w,n) 	((w)->login.prompts[n].promptText)
260578741aaSmrg#define DEF_PROMPT_TEXT(w,n) 	((w)->login.prompts[n].defaultPrompt)
261578741aaSmrg#define VALUE_TEXT(w,n) 	((w)->login.prompts[n].valueText)
262578741aaSmrg#define VALUE_TEXT_MAX(w,n)	((w)->login.prompts[n].valueTextMax)
263578741aaSmrg#define VALUE_SHOW_START(w,n)	((w)->login.prompts[n].valueShownStart)
264578741aaSmrg#define VALUE_SHOW_END(w,n)	((w)->login.prompts[n].valueShownEnd)
265578741aaSmrg#define PROMPT_STATE(w,n) 	((w)->login.prompts[n].state)
266578741aaSmrg#define PROMPT_CURSOR(w,n)	((w)->login.prompts[n].cursor)
267145b7b3cSmrg
268578741aaSmrg#define CUR_PROMPT_CURSOR(w)	PROMPT_CURSOR(w,w->login.activePrompt)
269145b7b3cSmrg
270578741aaSmrg#define CUR_PROMPT_TEXT(w, n)	(PROMPT_TEXT(w,n) != NULL ? \
271145b7b3cSmrg				 PROMPT_TEXT(w,n) : DEF_PROMPT_TEXT(w,n))
272145b7b3cSmrg
273145b7b3cSmrg#ifdef USE_XFT
274145b7b3cSmrg
275145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##color.pixel)
276145b7b3cSmrg
277145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	XmuXftTextWidth(XtDisplay (w), \
278145b7b3cSmrg					w->login.f##Face, (FcChar8 *) m, l)
279145b7b3cSmrgstatic int
280145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len);
281145b7b3cSmrg
282145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
283145b7b3cSmrg	/* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \
284145b7b3cSmrg	XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \
285145b7b3cSmrg			x, y, (FcChar8 *) m, l)
286145b7b3cSmrg
287145b7b3cSmrg#else
288145b7b3cSmrg
289145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##pixel)
290145b7b3cSmrg
291145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	(XTextWidth (w->login.f##Font, m, l))
292145b7b3cSmrg
293145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
294145b7b3cSmrg	XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l)
295145b7b3cSmrg
296145b7b3cSmrg#endif
297145b7b3cSmrg
298145b7b3cSmrg
299578741aaSmrg#define STRING_WIDTH(f, s) 	TEXT_WIDTH (f, s, strlen(s))
300145b7b3cSmrg
301629baa8cSmrg/* Padded width of logo image, if compiled with XPM support */
302629baa8cSmrg#ifdef XPM
303629baa8cSmrg# define LOGO_W(w)     ((w)->login.logoWidth + ((w)->login.logoPadding * 2))
304629baa8cSmrg#else
305629baa8cSmrg# define LOGO_W(w)     0
306629baa8cSmrg#endif
307145b7b3cSmrg
308578741aaSmrg#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth)
309145b7b3cSmrg
310578741aaSmrg#define DEF_PROMPT_W(w,n) TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt)
311578741aaSmrg#define CUR_PROMPT_W(w,n)  (max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \
312145b7b3cSmrg		     TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0))
313145b7b3cSmrg
314578741aaSmrg#define MAX_DEF_PROMPT_W(w) (max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1)))
315145b7b3cSmrg
316578741aaSmrg#define GREETING(w)	((w)->login.secure_session  && !(w)->login.allow_access ?\
317145b7b3cSmrg				(w)->login.greeting : (w)->login.unsecure_greet)
318578741aaSmrg#define GREET_X(w)	((int)((w->core.width - \
319145b7b3cSmrg			     	STRING_WIDTH (greet, GREETING(w))) / 2))
320578741aaSmrg#define GREET_Y(w)	(GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
321629baa8cSmrg#define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
322145b7b3cSmrg			      STRING_WIDTH (greet, w->login.unsecure_greet)) \
323629baa8cSmrg			 + LOGO_W(w))
324629baa8cSmrg
325578741aaSmrg#define PROMPT_X(w)	(2 * PROMPT_X_INC(w))
326578741aaSmrg#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)))
329578741aaSmrg#define PROMPT_W(w)	(w->core.width - (2 * TEXT_X_INC(w)))
330b7d26471Smrg#define PROMPT_H(w)	(5 * Y_INC(w) / 4)
331578741aaSmrg#define VALUE_X(w,n)	(PROMPT_X(w) + CUR_PROMPT_W(w,n))
332629baa8cSmrg#define CURSOR_W	5
333629baa8cSmrg#define MAX_VALUE_W(w,n) (PROMPT_W(w) - VALUE_X (w,n) - CURSOR_W - 1 - \
334629baa8cSmrg			  (w->login.inframeswidth * 2) - LOGO_W(w))
335578741aaSmrg#define PROMPT_SPACE_Y(w)	(10 * Y_INC(w) / 5)
336145b7b3cSmrg
337b7d26471Smrg#define ERROR_X(w,m)	((int)(w->core.width - LOGO_W(w) - STRING_WIDTH (fail, m)) / 2)
338578741aaSmrg#define FAIL_X(w)	ERROR_X(w, w->login.fail)
339578741aaSmrg#define FAIL_Y(w)	(PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail))
340145b7b3cSmrg
341629baa8cSmrg#define ERROR_W(w,m)	(STRING_WIDTH (fail, m) + LOGO_W(w))
342145b7b3cSmrg
343578741aaSmrg#define FAIL_W(w)	max(ERROR_W(w, w->login.failMsg), \
344145b7b3cSmrg			    ERROR_W(w, w->login.passwdChangeMsg))
345145b7b3cSmrg
346578741aaSmrg#define PAD_X(w)	(2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w))))
347145b7b3cSmrg
348578741aaSmrg#define PAD_Y(w)	(max (max (Y_INC(w), GREET_Y_INC(w)),\
349145b7b3cSmrg			     FAIL_Y_INC(w)))
350578741aaSmrg
351145b7b3cSmrg#ifndef max
352145b7b3cSmrgstatic inline int max (int a, int b) { return a > b ? a : b; }
353145b7b3cSmrg#endif
354145b7b3cSmrg
355145b7b3cSmrgstatic void
356145b7b3cSmrgrealizeValue (LoginWidget w, int cursor, int promptNum, GC gc)
357145b7b3cSmrg{
3585ffd6003Smrg    loginPromptState state = PROMPT_STATE(w, promptNum);
359145b7b3cSmrg    char *text = VALUE_TEXT(w, promptNum);
360145b7b3cSmrg    int	x, y, height, width, curoff;
361145b7b3cSmrg
362145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
363145b7b3cSmrg
3645ffd6003Smrg    /* replace all password characters with asterisks */
3655ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
3665ffd6003Smrg    {
3675ffd6003Smrg	Cardinal length = strlen(text);
3685ffd6003Smrg	Cardinal i = 0;
3695ffd6003Smrg
3705ffd6003Smrg	text = XtMalloc(length + 1);
3715ffd6003Smrg
3725ffd6003Smrg	if (text == NULL)
3735ffd6003Smrg	{
3745ffd6003Smrg	    LogOutOfMem("realizeValue");
3755ffd6003Smrg	    return;
3765ffd6003Smrg	}
3775ffd6003Smrg
3785ffd6003Smrg	while (i < length)
3795ffd6003Smrg	{
380629baa8cSmrg	    text[i++] = w->login.echo_passwd_char[0];
3815ffd6003Smrg	}
3825ffd6003Smrg
3835ffd6003Smrg	text[i] = 0;
3845ffd6003Smrg    }
3855ffd6003Smrg
386145b7b3cSmrg    x = VALUE_X (w,promptNum);
387145b7b3cSmrg    y = PROMPT_Y (w,promptNum);
388145b7b3cSmrg
389629baa8cSmrg    height = PROMPT_H(w) - (w->login.inframeswidth * 2);
390629baa8cSmrg    width = MAX_VALUE_W(w,promptNum);
391145b7b3cSmrg
392145b7b3cSmrg    if (cursor > VALUE_SHOW_START(w, promptNum))
393145b7b3cSmrg	curoff = TEXT_WIDTH (text, text, cursor);
394145b7b3cSmrg    else
395145b7b3cSmrg	curoff = 0;
396145b7b3cSmrg
397145b7b3cSmrg
398145b7b3cSmrg    if (gc == w->login.bgGC) {
399145b7b3cSmrg	if (curoff < width) {
400145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
401145b7b3cSmrg			    x + curoff, y - TEXT_Y_INC(w),
402145b7b3cSmrg			    width - curoff, height);
403145b7b3cSmrg	}
4045ffd6003Smrg    } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) ||
4055ffd6003Smrg	       ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)))
4065ffd6003Smrg    {
407145b7b3cSmrg	int offset = max(cursor, VALUE_SHOW_START(w, promptNum));
408145b7b3cSmrg	int textlen = strlen (text + offset);
409578741aaSmrg
410629baa8cSmrg	if (TEXT_WIDTH (text, text + offset, textlen) > (width - curoff)) {
411145b7b3cSmrg	    /* Recalculate amount of text that can fit in field */
412145b7b3cSmrg	    offset = VALUE_SHOW_START(w, promptNum);
413145b7b3cSmrg	    textlen = strlen (text + offset);
414145b7b3cSmrg
415629baa8cSmrg	    while ((textlen > 0) &&
416629baa8cSmrg		   (TEXT_WIDTH (text, text + offset, textlen) > width))
417145b7b3cSmrg	    {
418145b7b3cSmrg		if (offset < PROMPT_CURSOR(w, promptNum)) {
419145b7b3cSmrg		    offset++;
420145b7b3cSmrg		}
421145b7b3cSmrg		textlen--;
422578741aaSmrg	    }
423145b7b3cSmrg
424145b7b3cSmrg	    VALUE_SHOW_START(w, promptNum) = offset;
425145b7b3cSmrg	    VALUE_SHOW_END(w, promptNum) = offset + textlen;
426145b7b3cSmrg
427145b7b3cSmrg	    /* Erase old string */
428145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC,
429145b7b3cSmrg			    x, y - TEXT_Y_INC(w), width, height);
430145b7b3cSmrg
431145b7b3cSmrg	    DRAW_STRING(text, x, y, text + offset, textlen);
432145b7b3cSmrg	} else {
433145b7b3cSmrg	    DRAW_STRING(text, x + curoff, y, text + offset, textlen);
434145b7b3cSmrg	}
435145b7b3cSmrg    }
4365ffd6003Smrg    /* free memory */
4375ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
4385ffd6003Smrg    {
4395ffd6003Smrg	XtFree(text);
4405ffd6003Smrg    }
441145b7b3cSmrg}
442145b7b3cSmrg
443145b7b3cSmrgstatic void
444145b7b3cSmrgEraseValue (LoginWidget w, int cursor, int promptNum)
445145b7b3cSmrg{
446145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.bgGC);
447145b7b3cSmrg}
448145b7b3cSmrg
449145b7b3cSmrgstatic void
450145b7b3cSmrgDrawValue (LoginWidget w, int cursor, int promptNum)
451145b7b3cSmrg{
452145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.textGC);
453145b7b3cSmrg#ifdef DANCING
454145b7b3cSmrg    /*as good a place as any Caolan begin*/
455145b7b3cSmrg    w->login.lastEventTime = time(NULL);
456145b7b3cSmrg    /*as good a place as any Caolan end*/
457145b7b3cSmrg#endif /* DANCING */
458145b7b3cSmrg}
459145b7b3cSmrg
460145b7b3cSmrgstatic void
461145b7b3cSmrgrealizeCursor (LoginWidget w, GC gc)
462145b7b3cSmrg{
463145b7b3cSmrg    int	x, y;
464145b7b3cSmrg    int height, width;
465145b7b3cSmrg
466145b7b3cSmrg    if (w->login.state != PROMPTING) {
467145b7b3cSmrg	return;
468145b7b3cSmrg    }
469578741aaSmrg
470145b7b3cSmrg    x = VALUE_X (w, w->login.activePrompt);
471145b7b3cSmrg    y = PROMPT_Y (w, w->login.activePrompt);
472145b7b3cSmrg    height = (F_ASCENT(text) + F_DESCENT(text));
473145b7b3cSmrg    width = 1;
474145b7b3cSmrg
475145b7b3cSmrg    switch (PROMPT_STATE(w, w->login.activePrompt)) {
476145b7b3cSmrg    case LOGIN_PROMPT_NOT_SHOWN:
477145b7b3cSmrg    case LOGIN_TEXT_INFO:
478145b7b3cSmrg	return;
479145b7b3cSmrg    case LOGIN_PROMPT_ECHO_ON:
480145b7b3cSmrg	if (CUR_PROMPT_CURSOR(w) > 0) {
481145b7b3cSmrg	    x += TEXT_WIDTH (text,
482145b7b3cSmrg			     VALUE_TEXT(w, w->login.activePrompt)
483145b7b3cSmrg			     + VALUE_SHOW_START(w, w->login.activePrompt),
484145b7b3cSmrg			     PROMPT_CURSOR(w, w->login.activePrompt)
485145b7b3cSmrg			     - VALUE_SHOW_START(w, w->login.activePrompt) );
486145b7b3cSmrg	}
487145b7b3cSmrg	break;
488145b7b3cSmrg    case LOGIN_PROMPT_ECHO_OFF:
4895ffd6003Smrg	if (w->login.echo_passwd == True) {
490629baa8cSmrg	    if (w->login.echo_passwd_char[0] != 0) {
491629baa8cSmrg		int len = PROMPT_CURSOR(w, w->login.activePrompt) -
492629baa8cSmrg		    VALUE_SHOW_START(w, w->login.activePrompt);
4935ffd6003Smrg
494629baa8cSmrg		x += len*TEXT_WIDTH(text, w->login.echo_passwd_char, 1);
495629baa8cSmrg	    } else {
496629baa8cSmrg		/* Move cursor one pixel per character to give some feedback
497629baa8cSmrg		   without giving away the password length */
498629baa8cSmrg		if (PROMPT_CURSOR(w, w->login.activePrompt) <
499629baa8cSmrg		    MAX_VALUE_W(w, w->login.activePrompt))
500629baa8cSmrg		    x += PROMPT_CURSOR(w, w->login.activePrompt);
501629baa8cSmrg		else
502629baa8cSmrg		    x += MAX_VALUE_W(w, w->login.activePrompt);
503629baa8cSmrg	    }
5045ffd6003Smrg	}
505145b7b3cSmrg	break;
506145b7b3cSmrg    }
507578741aaSmrg
508145b7b3cSmrg    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
509145b7b3cSmrg		    x, y+1 - F_ASCENT(text), width, height-1);
510145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
511629baa8cSmrg		    x-1 , y - F_ASCENT(text));
512145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
513629baa8cSmrg		    x+1 , y - F_ASCENT(text));
514145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
515629baa8cSmrg		    x-1 , y - F_ASCENT(text)+height);
516145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
517629baa8cSmrg		    x+1 , y - F_ASCENT(text)+height);
518145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
519629baa8cSmrg		    x-2 , y - F_ASCENT(text));
520145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
521629baa8cSmrg		    x+2 , y - F_ASCENT(text));
522145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
523629baa8cSmrg		    x-2 , y - F_ASCENT(text)+height);
524145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
525629baa8cSmrg		    x+2 , y - F_ASCENT(text)+height);
526145b7b3cSmrg
527578741aaSmrg    XFlush (XtDisplay(w));
528145b7b3cSmrg}
529145b7b3cSmrg
530145b7b3cSmrgstatic void
531145b7b3cSmrgEraseFail (LoginWidget w)
532145b7b3cSmrg{
533578741aaSmrg#ifdef USE_XFT
534145b7b3cSmrg    w->login.failUp = 0;
535145b7b3cSmrg    RedrawFail(w);
536578741aaSmrg#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));
543578741aaSmrg#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
595578741aaSmrg#ifndef USE_XFT
596145b7b3cSmrg    if (w->login.failUp)
597578741aaSmrg#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;
605578741aaSmrg		char lastspace = ' ';
606145b7b3cSmrg
607145b7b3cSmrg		y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w));
608578741aaSmrg
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);
628578741aaSmrg
629145b7b3cSmrg		    x = ERROR_X(w, start);
630145b7b3cSmrg#ifdef USE_XFT
631145b7b3cSmrg		    if (w->login.failUp == 0) {
6325ffd6003Smrg			XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
633145b7b3cSmrg				   ERROR_W(w, start), FAIL_Y_INC(w), False);
634145b7b3cSmrg		    } else
635578741aaSmrg#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) {
6535ffd6003Smrg	    XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
654145b7b3cSmrg		       ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False);
655145b7b3cSmrg	} else
656578741aaSmrg#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
7075ffd6003Smrg    /* draw window borders */
708145b7b3cSmrg    for(i=1;i<=(w->login.outframewidth);i++)
709145b7b3cSmrg    {
710145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
711629baa8cSmrg		i-1,i-1,w->core.width-i,i-1);
712145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
713629baa8cSmrg		i-1,i-1,i-1,w->core.height-i);
714145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
715629baa8cSmrg		w->core.width-i,i-1,w->core.width-i,w->core.height-i);
716145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
717629baa8cSmrg		i-1,w->core.height-i,w->core.width-i,w->core.height-i);
718145b7b3cSmrg    }
719578741aaSmrg
720145b7b3cSmrg    /* make separator line */
721145b7b3cSmrg    gr_line_x = w->login.outframewidth;
722145b7b3cSmrg    gr_line_y = GREET_Y(w) + GREET_Y_INC(w);
723145b7b3cSmrg    gr_line_w = w->core.width - 2*(w->login.outframewidth);
724145b7b3cSmrg
725145b7b3cSmrg#ifdef XPM
726145b7b3cSmrg    gr_line_x += w->login.logoPadding;
727145b7b3cSmrg    gr_line_w -= w->login.logoWidth + (3 * (w->login.logoPadding));
728145b7b3cSmrg#endif /* XPM */
729145b7b3cSmrg
730145b7b3cSmrg    for(i=1;i<=(w->login.sepwidth);i++)
731145b7b3cSmrg    {
732145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
733145b7b3cSmrg        gr_line_x,           gr_line_y + i-1,
734145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + i-1);
735145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
736145b7b3cSmrg        gr_line_x,           gr_line_y + 2*(w->login.inframeswidth) -i,
737145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + 2*(w->login.inframeswidth) -i);
738145b7b3cSmrg    }
739145b7b3cSmrg
740145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++)
741145b7b3cSmrg    {
742145b7b3cSmrg	int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth - 3;
743145b7b3cSmrg	int in_frame_y
744145b7b3cSmrg	    = PROMPT_Y(w,p) - w->login.inframeswidth - 1 - TEXT_Y_INC(w);
745578741aaSmrg
746629baa8cSmrg	int in_width = PROMPT_W(w) - VALUE_X(w,p) - LOGO_W(w);
747145b7b3cSmrg	int in_height = PROMPT_H(w) + w->login.inframeswidth + 2;
748578741aaSmrg
749b7d26471Smrg	GC topLeftGC, botRightGC, inpGC;
750145b7b3cSmrg
751145b7b3cSmrg	if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) ||
752145b7b3cSmrg	    (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) {
753145b7b3cSmrg	    topLeftGC = w->login.shdGC;
754145b7b3cSmrg	    botRightGC = w->login.hiGC;
755b7d26471Smrg	    inpGC = w->login.inpGC;
756145b7b3cSmrg	} else {
757b7d26471Smrg	    topLeftGC = botRightGC = inpGC = w->login.bgGC;
758145b7b3cSmrg	}
759145b7b3cSmrg
7605ffd6003Smrg	/* draw borders of editboxes */
761145b7b3cSmrg	for (i=1; i<=(w->login.inframeswidth); i++)
762145b7b3cSmrg	{
763145b7b3cSmrg	    /* Make top/left sides */
764145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
765145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
766578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1);
767145b7b3cSmrg
768145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
769145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
770578741aaSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i);
771145b7b3cSmrg
772145b7b3cSmrg	    /* Make bottom/right sides */
773145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
774145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1,
775578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
776145b7b3cSmrg
777145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
778145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i,
779145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
780145b7b3cSmrg	}
781b7d26471Smrg	XFillRectangle(XtDisplay (w), XtWindow (w), inpGC,
782b7d26471Smrg	    in_frame_x + w->login.inframeswidth,
783b7d26471Smrg	    in_frame_y + w->login.inframeswidth,
784b7d26471Smrg	    in_width - 2*w->login.inframeswidth,
785b7d26471Smrg	    in_height - 2*w->login.inframeswidth);
786145b7b3cSmrg    }
787145b7b3cSmrg
788145b7b3cSmrg    if (GREETING(w)[0]) {
789145b7b3cSmrg	int gx = GREET_X(w);
790145b7b3cSmrg
791145b7b3cSmrg#ifdef XPM
792145b7b3cSmrg	gx -= ((w->login.logoWidth/2) + w->login.logoPadding);
793578741aaSmrg#endif
794145b7b3cSmrg	DRAW_STRING (greet, gx, GREET_Y(w), GREETING(w), strlen (GREETING(w)));
795145b7b3cSmrg    }
796145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++) {
797145b7b3cSmrg	if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) {
798145b7b3cSmrg	    DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p),
799145b7b3cSmrg			 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p)));
800145b7b3cSmrg	    DrawValue (w, 0, p);
801145b7b3cSmrg	}
802145b7b3cSmrg    }
803145b7b3cSmrg    RedrawFail (w);
804145b7b3cSmrg    XorCursor (w);
8055ffd6003Smrg    XSetInputFocus (XtDisplay (w), XtWindow (w),
8065ffd6003Smrg		    RevertToPointerRoot, CurrentTime);
807145b7b3cSmrg}
808145b7b3cSmrg
809145b7b3cSmrg/* Returns 0 on success, -1 on failure */
810145b7b3cSmrg_X_INTERNAL
811145b7b3cSmrgint
812145b7b3cSmrgSetPrompt (Widget ctx, int promptNum, const char *message,
813145b7b3cSmrg	   loginPromptState state, Boolean minimumTime)
814145b7b3cSmrg{
815145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
816145b7b3cSmrg    char *prompt;
817145b7b3cSmrg    int messageLen, e;
818145b7b3cSmrg    const char *stateNames[4] = {
819145b7b3cSmrg	"LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON",
820145b7b3cSmrg	"LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" };
821145b7b3cSmrg    loginPromptState priorState;
822578741aaSmrg
823145b7b3cSmrg    Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum,
824145b7b3cSmrg	  message ? message : "<NULL>", stateNames[state], state);
825145b7b3cSmrg
826145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
827578741aaSmrg
828145b7b3cSmrg    if (PROMPT_TEXT(w, promptNum) != NULL) {
829145b7b3cSmrg	XtFree(PROMPT_TEXT(w, promptNum));
830145b7b3cSmrg	PROMPT_TEXT(w, promptNum) = NULL;
831145b7b3cSmrg    }
832145b7b3cSmrg
833145b7b3cSmrg    priorState = PROMPT_STATE(w, promptNum);
834145b7b3cSmrg    PROMPT_STATE(w, promptNum) = state;
835145b7b3cSmrg
836145b7b3cSmrg    if (state == LOGIN_PROMPT_NOT_SHOWN) {
837145b7b3cSmrg	return 0;
838145b7b3cSmrg    }
839145b7b3cSmrg
840145b7b3cSmrg    if (message == NULL) {
841145b7b3cSmrg	message = DEF_PROMPT_TEXT(w, promptNum);
842145b7b3cSmrg    }
843145b7b3cSmrg
844145b7b3cSmrg    messageLen = strlen(message);
845578741aaSmrg
846145b7b3cSmrg    prompt = XtMalloc(messageLen + 3);
847145b7b3cSmrg    if (prompt == NULL) {
848145b7b3cSmrg	LogOutOfMem ("SetPrompt");
849145b7b3cSmrg	return -1;
850145b7b3cSmrg    }
851578741aaSmrg
852145b7b3cSmrg    strncpy(prompt, message, messageLen);
853578741aaSmrg
854145b7b3cSmrg    /* Make sure text prompts have at least two spaces at end */
855145b7b3cSmrg    e = messageLen;
856578741aaSmrg
857145b7b3cSmrg    if (!isspace(message[messageLen - 2])) {
858145b7b3cSmrg	prompt[e] = ' ';
859145b7b3cSmrg	e++;
860145b7b3cSmrg    }
861145b7b3cSmrg    if (!isspace(message[messageLen - 1])) {
862145b7b3cSmrg	prompt[e] = ' ';
863145b7b3cSmrg	e++;
864145b7b3cSmrg    }
865145b7b3cSmrg    prompt[e] = '\0';
866145b7b3cSmrg
867145b7b3cSmrg    PROMPT_TEXT(w, promptNum) = prompt;
868145b7b3cSmrg
869145b7b3cSmrg    if (w->login.state == INITIALIZING) {
870145b7b3cSmrg	return 0;
871145b7b3cSmrg    }
872578741aaSmrg
873145b7b3cSmrg    if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) {
874145b7b3cSmrg	time_t now = time(NULL);
875145b7b3cSmrg	int timeleft = w->login.msgTimeout - now;
876578741aaSmrg
877145b7b3cSmrg	if (timeleft > 0) {
878145b7b3cSmrg	    sleep(timeleft);
879145b7b3cSmrg	}
880145b7b3cSmrg	w->login.msgTimeout = 0;
881145b7b3cSmrg    }
882145b7b3cSmrg
883145b7b3cSmrg    if (state == LOGIN_TEXT_INFO) {
884145b7b3cSmrg	if (minimumTime) {
885145b7b3cSmrg	    time_t now = time(NULL);
886145b7b3cSmrg	    w->login.msgTimeout = now + w->login.failTimeout;
887145b7b3cSmrg	}
888145b7b3cSmrg	w->login.state = SHOW_MESSAGE;
889145b7b3cSmrg    } else {
890145b7b3cSmrg	w->login.activePrompt = promptNum;
891145b7b3cSmrg	w->login.state = PROMPTING;
892145b7b3cSmrg    }
893578741aaSmrg
894145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
895145b7b3cSmrg    XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE);
896145b7b3cSmrg    draw_it(w);
897145b7b3cSmrg    return 0;
898145b7b3cSmrg}
899145b7b3cSmrg
900145b7b3cSmrg_X_INTERNAL
901145b7b3cSmrgconst char *
902145b7b3cSmrgGetPrompt(Widget ctx, int promptNum)
903145b7b3cSmrg{
904145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
905145b7b3cSmrg
906145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
907578741aaSmrg
908145b7b3cSmrg    return CUR_PROMPT_TEXT(w,promptNum);
909145b7b3cSmrg}
910145b7b3cSmrg
911145b7b3cSmrg_X_INTERNAL
912145b7b3cSmrgint
913145b7b3cSmrgSetValue(Widget ctx, int promptNum, char *value)
914145b7b3cSmrg{
915145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
916145b7b3cSmrg
917145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
918578741aaSmrg
919145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
920145b7b3cSmrg	return -1;
921145b7b3cSmrg
922145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
923578741aaSmrg
924145b7b3cSmrg    if (VALUE_TEXT(w, promptNum) == NULL)
925145b7b3cSmrg	return -1;
926145b7b3cSmrg
927145b7b3cSmrg    if (value == NULL) {
928145b7b3cSmrg	bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum));
929145b7b3cSmrg    } else {
930145b7b3cSmrg	strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum));
931145b7b3cSmrg	VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0';
932145b7b3cSmrg    }
933145b7b3cSmrg
934145b7b3cSmrg    VALUE_SHOW_START(w, promptNum) = 0;
935145b7b3cSmrg    VALUE_SHOW_END(w, promptNum) = 0;
936145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
937578741aaSmrg
938145b7b3cSmrg    return 0;
939145b7b3cSmrg}
940145b7b3cSmrg
941145b7b3cSmrg_X_INTERNAL
942145b7b3cSmrgconst char *
943145b7b3cSmrgGetValue(Widget ctx, int promptNum)
944145b7b3cSmrg{
945145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
946145b7b3cSmrg
947145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
948578741aaSmrg
949145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
950145b7b3cSmrg	return NULL;
951145b7b3cSmrg
952145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
953145b7b3cSmrg
954145b7b3cSmrg    return VALUE_TEXT(w, promptNum);
955145b7b3cSmrg}
956145b7b3cSmrg
957145b7b3cSmrg
958145b7b3cSmrgstatic void
959145b7b3cSmrgrealizeDeleteChar (LoginWidget ctx)
960145b7b3cSmrg{
961145b7b3cSmrg    if (ctx->login.state == PROMPTING) {
962145b7b3cSmrg	int promptNum = ctx->login.activePrompt;
963145b7b3cSmrg	int redrawFrom = PROMPT_CURSOR(ctx, promptNum);
964578741aaSmrg
965145b7b3cSmrg	if (PROMPT_CURSOR(ctx,promptNum) <  (int)strlen(VALUE_TEXT(ctx,promptNum))) {
966145b7b3cSmrg	    if (redrawFrom < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
967145b7b3cSmrg		redrawFrom = 0;
968145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
969145b7b3cSmrg		VALUE_SHOW_START(ctx, ctx->login.activePrompt)
970145b7b3cSmrg		    = PROMPT_CURSOR(ctx,promptNum);
971145b7b3cSmrg	    } else {
972145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
973145b7b3cSmrg	    }
974145b7b3cSmrg	    strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
975145b7b3cSmrg		   VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1);
976145b7b3cSmrg	    DrawValue (ctx, redrawFrom, promptNum);
977145b7b3cSmrg	}
978145b7b3cSmrg    }
979145b7b3cSmrg}
980145b7b3cSmrg
981145b7b3cSmrg/*ARGSUSED*/
982145b7b3cSmrgstatic void
983145b7b3cSmrgDeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
984145b7b3cSmrg{
985145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
986145b7b3cSmrg
987145b7b3cSmrg    RemoveFail (ctx);
988145b7b3cSmrg
989145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
990145b7b3cSmrg	return;
991145b7b3cSmrg    }
992145b7b3cSmrg
993145b7b3cSmrg    XorCursor (ctx);
994145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0) {
995145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
996145b7b3cSmrg	realizeDeleteChar(ctx);
997145b7b3cSmrg    }
998578741aaSmrg    XorCursor (ctx);
999145b7b3cSmrg}
1000145b7b3cSmrg
1001145b7b3cSmrg/*ARGSUSED*/
1002145b7b3cSmrgstatic void
1003145b7b3cSmrgDeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1004145b7b3cSmrg{
1005145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1006145b7b3cSmrg
1007145b7b3cSmrg    RemoveFail (ctx);
1008145b7b3cSmrg
1009145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1010145b7b3cSmrg	return;
1011145b7b3cSmrg    }
1012145b7b3cSmrg
1013145b7b3cSmrg    XorCursor (ctx);
1014145b7b3cSmrg    realizeDeleteChar(ctx);
1015578741aaSmrg    XorCursor (ctx);
1016145b7b3cSmrg}
1017145b7b3cSmrg
1018145b7b3cSmrg/*ARGSUSED*/
1019145b7b3cSmrgstatic void
1020145b7b3cSmrgMoveBackwardChar (
1021145b7b3cSmrg    Widget	ctxw,
1022145b7b3cSmrg    XEvent	*event,
1023145b7b3cSmrg    String	*params,
1024145b7b3cSmrg    Cardinal	*num_params)
1025145b7b3cSmrg{
1026145b7b3cSmrg    LoginWidget	ctx = (LoginWidget)ctxw;
1027145b7b3cSmrg
1028145b7b3cSmrg    RemoveFail (ctx);
1029145b7b3cSmrg
1030145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1031145b7b3cSmrg	return;
1032145b7b3cSmrg    }
1033145b7b3cSmrg
1034145b7b3cSmrg    XorCursor (ctx);
1035145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0)
1036145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
1037145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
1038145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1039145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt)
1040145b7b3cSmrg	    = CUR_PROMPT_CURSOR(ctx);
1041145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1042145b7b3cSmrg    }
1043145b7b3cSmrg    XorCursor (ctx);
1044145b7b3cSmrg}
1045145b7b3cSmrg
1046145b7b3cSmrg/*ARGSUSED*/
1047145b7b3cSmrgstatic void
1048145b7b3cSmrgMoveForwardChar (
1049145b7b3cSmrg    Widget	ctxw,
1050145b7b3cSmrg    XEvent	*event,
1051145b7b3cSmrg    String	*params,
1052145b7b3cSmrg    Cardinal	*num_params)
1053145b7b3cSmrg{
1054145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1055145b7b3cSmrg
1056145b7b3cSmrg    RemoveFail (ctx);
1057145b7b3cSmrg
1058145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1059145b7b3cSmrg	return;
1060145b7b3cSmrg    }
1061145b7b3cSmrg
1062145b7b3cSmrg    XorCursor (ctx);
1063145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) <
1064145b7b3cSmrg	(int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) {
1065145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) += 1;
1066145b7b3cSmrg	if (VALUE_SHOW_END(ctx, ctx->login.activePrompt)
1067145b7b3cSmrg	    < CUR_PROMPT_CURSOR(ctx)) {
1068145b7b3cSmrg	    EraseValue(ctx, 0, ctx->login.activePrompt);
1069145b7b3cSmrg	    DrawValue(ctx, 0, ctx->login.activePrompt);
1070145b7b3cSmrg	}
1071145b7b3cSmrg    }
1072145b7b3cSmrg    XorCursor (ctx);
1073145b7b3cSmrg}
1074145b7b3cSmrg
1075145b7b3cSmrg/*ARGSUSED*/
1076145b7b3cSmrgstatic void
1077145b7b3cSmrgMoveToBegining (
1078145b7b3cSmrg    Widget	ctxw,
1079145b7b3cSmrg    XEvent	*event,
1080145b7b3cSmrg    String	*params,
1081145b7b3cSmrg    Cardinal	*num_params)
1082145b7b3cSmrg{
1083145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1084145b7b3cSmrg
1085145b7b3cSmrg    RemoveFail (ctx);
1086145b7b3cSmrg
1087145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1088145b7b3cSmrg	return;
1089145b7b3cSmrg    }
1090145b7b3cSmrg
1091145b7b3cSmrg    XorCursor (ctx);
1092145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = 0;
1093145b7b3cSmrg    if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) {
1094145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1095145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0;
1096145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1097145b7b3cSmrg    }
1098145b7b3cSmrg    XorCursor (ctx);
1099145b7b3cSmrg}
1100145b7b3cSmrg
1101145b7b3cSmrg/*ARGSUSED*/
1102145b7b3cSmrgstatic void
1103145b7b3cSmrgMoveToEnd (
1104145b7b3cSmrg    Widget	ctxw,
1105145b7b3cSmrg    XEvent	*event,
1106145b7b3cSmrg    String	*params,
1107145b7b3cSmrg    Cardinal	*num_params)
1108145b7b3cSmrg{
1109145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1110145b7b3cSmrg
1111145b7b3cSmrg    RemoveFail (ctx);
1112145b7b3cSmrg
1113145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1114145b7b3cSmrg	return;
1115145b7b3cSmrg    }
1116145b7b3cSmrg
1117145b7b3cSmrg    XorCursor (ctx);
1118145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt));
1119145b7b3cSmrg    if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) {
1120145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1121145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1122145b7b3cSmrg    }
1123145b7b3cSmrg    XorCursor (ctx);
1124145b7b3cSmrg}
1125145b7b3cSmrg
1126145b7b3cSmrg/*ARGSUSED*/
1127145b7b3cSmrgstatic void
1128145b7b3cSmrgEraseToEndOfLine (
1129145b7b3cSmrg    Widget	ctxw,
1130145b7b3cSmrg    XEvent	*event,
1131145b7b3cSmrg    String	*params,
1132145b7b3cSmrg    Cardinal	*num_params)
1133145b7b3cSmrg{
1134145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1135145b7b3cSmrg
1136145b7b3cSmrg    RemoveFail (ctx);
1137145b7b3cSmrg
1138145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1139145b7b3cSmrg	return;
1140145b7b3cSmrg    }
1141145b7b3cSmrg
1142145b7b3cSmrg    XorCursor (ctx);
1143145b7b3cSmrg    EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt);
1144145b7b3cSmrg    bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) +
1145145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx),
1146145b7b3cSmrg	  VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) -
1147145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx));
1148145b7b3cSmrg    XorCursor (ctx);
1149145b7b3cSmrg}
1150145b7b3cSmrg
1151145b7b3cSmrg/*ARGSUSED*/
1152145b7b3cSmrgstatic void
1153145b7b3cSmrgEraseLine (
1154145b7b3cSmrg    Widget	ctxw,
1155145b7b3cSmrg    XEvent	*event,
1156145b7b3cSmrg    String	*params,
1157145b7b3cSmrg    Cardinal	*num_params)
1158145b7b3cSmrg{
1159145b7b3cSmrg    MoveToBegining (ctxw, event, params, num_params);
1160145b7b3cSmrg    EraseToEndOfLine (ctxw, event, params, num_params);
1161145b7b3cSmrg}
1162145b7b3cSmrg
1163145b7b3cSmrg/*ARGSUSED*/
1164145b7b3cSmrgstatic void
1165145b7b3cSmrgFinishField (
1166145b7b3cSmrg    Widget	ctxw,
1167145b7b3cSmrg    XEvent	*event,
1168145b7b3cSmrg    String	*params,
1169145b7b3cSmrg    Cardinal	*num_params)
1170145b7b3cSmrg{
1171145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1172145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1173145b7b3cSmrg    int nextPrompt;
1174145b7b3cSmrg
1175145b7b3cSmrg    RemoveFail (ctx);
1176145b7b3cSmrg
1177145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1178145b7b3cSmrg	return;
1179145b7b3cSmrg    }
1180145b7b3cSmrg
1181145b7b3cSmrg    XorCursor (ctx);
1182145b7b3cSmrg
1183145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) {
1184145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1185145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1186145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1187145b7b3cSmrg	    break;
1188145b7b3cSmrg	}
1189145b7b3cSmrg    }
1190145b7b3cSmrg    if (nextPrompt > LAST_PROMPT) {
1191145b7b3cSmrg	ctx->login.state = DONE;
1192145b7b3cSmrg	(*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
1193145b7b3cSmrg	Debug("FinishField #%d: now DONE\n", promptNum);
1194145b7b3cSmrg    } else {
1195145b7b3cSmrg	Debug("FinishField #%d: %d next\n", promptNum, nextPrompt);
1196145b7b3cSmrg    }
1197145b7b3cSmrg
1198145b7b3cSmrg    XorCursor (ctx);
1199145b7b3cSmrg}
1200145b7b3cSmrg
1201145b7b3cSmrg/*ARGSUSED*/
1202145b7b3cSmrgstatic void
1203145b7b3cSmrgTabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1204145b7b3cSmrg{
1205145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1206145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1207145b7b3cSmrg    int nextPrompt;
1208145b7b3cSmrg
1209145b7b3cSmrg    RemoveFail (ctx);
1210145b7b3cSmrg
1211145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1212145b7b3cSmrg	return;
1213145b7b3cSmrg    }
1214145b7b3cSmrg
1215145b7b3cSmrg    XorCursor (ctx);
1216145b7b3cSmrg
1217145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) {
1218145b7b3cSmrg	if (nextPrompt > LAST_PROMPT) {
1219145b7b3cSmrg	    nextPrompt = 0;
1220145b7b3cSmrg	}
1221578741aaSmrg
1222145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1223145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1224145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1225145b7b3cSmrg	    break;
1226145b7b3cSmrg	}
1227145b7b3cSmrg    }
1228145b7b3cSmrg    XorCursor (ctx);
1229145b7b3cSmrg}
1230145b7b3cSmrg
1231145b7b3cSmrg/*ARGSUSED*/
1232145b7b3cSmrgstatic void
1233145b7b3cSmrgAllowAccess (
1234145b7b3cSmrg    Widget	ctxw,
1235145b7b3cSmrg    XEvent	*event,
1236145b7b3cSmrg    String	*params,
1237145b7b3cSmrg    Cardinal	*num_params)
1238145b7b3cSmrg{
1239145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1240145b7b3cSmrg    Arg	arglist[1];
1241145b7b3cSmrg    Boolean allow;
1242145b7b3cSmrg
1243145b7b3cSmrg    RemoveFail (ctx);
1244145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
1245145b7b3cSmrg    XtGetValues ((Widget) ctx, arglist, 1);
1246145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, !allow);
1247145b7b3cSmrg    XtSetValues ((Widget) ctx, arglist, 1);
1248145b7b3cSmrg}
1249145b7b3cSmrg
1250145b7b3cSmrg/*ARGSUSED*/
1251145b7b3cSmrgstatic void
1252145b7b3cSmrgSetSessionArgument (
1253145b7b3cSmrg    Widget	ctxw,
1254145b7b3cSmrg    XEvent	*event,
1255145b7b3cSmrg    String	*params,
1256145b7b3cSmrg    Cardinal	*num_params)
1257145b7b3cSmrg{
1258145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1259145b7b3cSmrg
1260145b7b3cSmrg    RemoveFail (ctx);
1261145b7b3cSmrg    if (ctx->login.sessionArg)
1262145b7b3cSmrg	XtFree (ctx->login.sessionArg);
1263145b7b3cSmrg    ctx->login.sessionArg = NULL;
1264145b7b3cSmrg    if (*num_params > 0) {
1265145b7b3cSmrg	ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
1266145b7b3cSmrg	if (ctx->login.sessionArg)
1267145b7b3cSmrg	    strcpy (ctx->login.sessionArg, params[0]);
1268145b7b3cSmrg	else
1269145b7b3cSmrg	    LogOutOfMem ("set session argument");
1270145b7b3cSmrg    }
1271145b7b3cSmrg}
1272145b7b3cSmrg
1273145b7b3cSmrg/*ARGSUSED*/
1274145b7b3cSmrgstatic void
1275145b7b3cSmrgRestartSession (
1276145b7b3cSmrg    Widget	ctxw,
1277145b7b3cSmrg    XEvent	*event,
1278145b7b3cSmrg    String	*params,
1279145b7b3cSmrg    Cardinal	*num_params)
1280145b7b3cSmrg{
1281145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1282145b7b3cSmrg
1283145b7b3cSmrg    XorCursor (ctx);
1284145b7b3cSmrg    RemoveFail (ctx);
1285145b7b3cSmrg    ctx->login.state = DONE;
1286145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
1287145b7b3cSmrg    XorCursor (ctx);
1288145b7b3cSmrg}
1289145b7b3cSmrg
1290145b7b3cSmrg/*ARGSUSED*/
1291145b7b3cSmrgstatic void
1292145b7b3cSmrgAbortSession (
1293145b7b3cSmrg    Widget	ctxw,
1294145b7b3cSmrg    XEvent	*event,
1295145b7b3cSmrg    String	*params,
1296145b7b3cSmrg    Cardinal	*num_params)
1297145b7b3cSmrg{
1298145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1299145b7b3cSmrg
1300145b7b3cSmrg    XorCursor (ctx);
1301145b7b3cSmrg    RemoveFail (ctx);
1302145b7b3cSmrg    ctx->login.state = DONE;
1303145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
1304145b7b3cSmrg    XorCursor (ctx);
1305145b7b3cSmrg}
1306145b7b3cSmrg
1307145b7b3cSmrg/*ARGSUSED*/
1308145b7b3cSmrgstatic void
1309145b7b3cSmrgAbortDisplay (
1310145b7b3cSmrg    Widget	ctxw,
1311145b7b3cSmrg    XEvent	*event,
1312145b7b3cSmrg    String	*params,
1313145b7b3cSmrg    Cardinal	*num_params)
1314145b7b3cSmrg{
1315145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1316145b7b3cSmrg
1317145b7b3cSmrg    XorCursor (ctx);
1318145b7b3cSmrg    RemoveFail (ctx);
1319145b7b3cSmrg    ctx->login.state = DONE;
1320145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
1321145b7b3cSmrg    XorCursor (ctx);
1322145b7b3cSmrg}
1323145b7b3cSmrg
1324145b7b3cSmrgstatic void
1325145b7b3cSmrgResetLogin (LoginWidget w)
1326145b7b3cSmrg{
1327145b7b3cSmrg    int i;
1328145b7b3cSmrg
1329145b7b3cSmrg    for (i = 0; i < NUM_PROMPTS ; i++) {
1330145b7b3cSmrg	EraseValue(w, 0, i);
1331145b7b3cSmrg	bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i));
1332145b7b3cSmrg	VALUE_SHOW_START(w, i) = 0;
1333145b7b3cSmrg	PROMPT_CURSOR(w, i) = 0;
1334145b7b3cSmrg    }
1335145b7b3cSmrg    w->login.state = PROMPTING;
1336145b7b3cSmrg    w->login.activePrompt = 0;
1337145b7b3cSmrg}
1338145b7b3cSmrg
1339145b7b3cSmrgstatic void
1340145b7b3cSmrgInitI18N(Widget ctxw)
1341145b7b3cSmrg{
1342145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1343145b7b3cSmrg    XIM         xim = (XIM) NULL;
1344145b7b3cSmrg    char *p;
1345145b7b3cSmrg
1346145b7b3cSmrg    ctx->login.xic = (XIC) NULL;
1347145b7b3cSmrg
1348145b7b3cSmrg    if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
1349145b7b3cSmrg	xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL);
1350145b7b3cSmrg
1351145b7b3cSmrg    if (!xim) {
1352145b7b3cSmrg	LogError("Failed to open input method\n");
1353145b7b3cSmrg	return;
1354145b7b3cSmrg    }
1355145b7b3cSmrg
1356145b7b3cSmrg    ctx->login.xic = XCreateIC(xim,
1357145b7b3cSmrg	XNInputStyle, (XIMPreeditNothing|XIMStatusNothing),
1358145b7b3cSmrg	XNClientWindow, ctx->core.window,
1359145b7b3cSmrg	XNFocusWindow,  ctx->core.window, NULL);
1360145b7b3cSmrg
1361145b7b3cSmrg    if (!ctx->login.xic) {
1362145b7b3cSmrg	LogError("Failed to create input context\n");
1363145b7b3cSmrg	XCloseIM(xim);
1364145b7b3cSmrg    }
1365145b7b3cSmrg    return;
1366145b7b3cSmrg}
1367145b7b3cSmrg
1368145b7b3cSmrg/* ARGSUSED */
1369145b7b3cSmrgstatic void
1370145b7b3cSmrgInsertChar (
1371145b7b3cSmrg    Widget	ctxw,
1372145b7b3cSmrg    XEvent	*event,
1373145b7b3cSmrg    String	*params,
1374145b7b3cSmrg    Cardinal	*num_params)
1375145b7b3cSmrg{
1376145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1377145b7b3cSmrg
1378145b7b3cSmrg    char strbuf[128];
1379145b7b3cSmrg    int  len, promptNum = ctx->login.activePrompt;
1380145b7b3cSmrg    KeySym  keysym = 0;
1381145b7b3cSmrg
1382145b7b3cSmrg    if (ctx->login.xic) {
1383145b7b3cSmrg	static Status status;
1384145b7b3cSmrg	len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf,
1385145b7b3cSmrg			      sizeof (strbuf), &keysym, &status);
1386145b7b3cSmrg    } else {
1387145b7b3cSmrg	static XComposeStatus compose_status = {NULL, 0};
1388145b7b3cSmrg	len = XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1389145b7b3cSmrg			     &keysym, &compose_status);
1390145b7b3cSmrg    }
1391145b7b3cSmrg    strbuf[len] = '\0';
1392145b7b3cSmrg
1393145b7b3cSmrg    /*
1394145b7b3cSmrg     * Note: You can override this default key handling
1395145b7b3cSmrg     * by the settings in the translation table
1396145b7b3cSmrg     * loginActionsTable at the end of this file.
1397145b7b3cSmrg     */
1398145b7b3cSmrg    switch (keysym) {
1399145b7b3cSmrg    case XK_Return:
1400145b7b3cSmrg    case XK_KP_Enter:
1401145b7b3cSmrg    case XK_Linefeed:
1402145b7b3cSmrg    case XK_Execute:
1403145b7b3cSmrg	FinishField(ctxw, event, params, num_params);
1404145b7b3cSmrg	return;
1405145b7b3cSmrg    case XK_BackSpace:
1406145b7b3cSmrg	DeleteBackwardChar(ctxw, event, params, num_params);
1407145b7b3cSmrg	return;
1408145b7b3cSmrg    case XK_Delete:
1409145b7b3cSmrg    case XK_KP_Delete:
1410145b7b3cSmrg    case DXK_Remove:
1411145b7b3cSmrg	/* Sorry, it's not a telex machine, it's a terminal */
1412145b7b3cSmrg	DeleteForwardChar(ctxw, event, params, num_params);
1413145b7b3cSmrg	return;
1414145b7b3cSmrg    case XK_Left:
1415145b7b3cSmrg    case XK_KP_Left:
1416145b7b3cSmrg	MoveBackwardChar(ctxw, event, params, num_params);
1417145b7b3cSmrg	return;
1418145b7b3cSmrg    case XK_Right:
1419145b7b3cSmrg    case XK_KP_Right:
1420145b7b3cSmrg	MoveForwardChar(ctxw, event, params, num_params);
1421145b7b3cSmrg	return;
1422145b7b3cSmrg    case XK_End:
1423145b7b3cSmrg    case XK_KP_End:
1424145b7b3cSmrg	MoveToEnd(ctxw, event, params, num_params);
1425145b7b3cSmrg	return;
1426145b7b3cSmrg    case XK_Home:
1427145b7b3cSmrg    case XK_KP_Home:
1428145b7b3cSmrg	MoveToBegining(ctxw, event, params, num_params);
1429145b7b3cSmrg	return;
1430145b7b3cSmrg    default:
1431145b7b3cSmrg	if (len == 0) {
1432145b7b3cSmrg	    if (!IsModifierKey(keysym))  /* it's not a modifier */
1433145b7b3cSmrg		XBell(XtDisplay(ctxw), 60);
1434145b7b3cSmrg	    return;
1435145b7b3cSmrg	} else
1436145b7b3cSmrg	    break;
1437145b7b3cSmrg    }
1438145b7b3cSmrg
1439578741aaSmrg    if (ctx->login.state == PROMPTING) {
1440145b7b3cSmrg	if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >=
1441145b7b3cSmrg	     (VALUE_TEXT_MAX(ctx,promptNum) - 1))) {
1442145b7b3cSmrg	    len = VALUE_TEXT_MAX(ctx,promptNum) -
1443145b7b3cSmrg		strlen(VALUE_TEXT(ctx, promptNum)) - 2;
1444145b7b3cSmrg	}
1445145b7b3cSmrg    }
1446145b7b3cSmrg    EraseCursor (ctx);
1447145b7b3cSmrg    RemoveFail (ctx);
1448145b7b3cSmrg    if (len != 0)
1449145b7b3cSmrg    {
1450145b7b3cSmrg	if (ctx->login.state == PROMPTING) {
1451145b7b3cSmrg	    EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1452145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len,
1453145b7b3cSmrg		    VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1454145b7b3cSmrg		    strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1);
1455145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1456145b7b3cSmrg		     strbuf, len);
1457145b7b3cSmrg	    DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1458145b7b3cSmrg	    PROMPT_CURSOR(ctx, promptNum) += len;
1459145b7b3cSmrg	}
1460145b7b3cSmrg    }
1461145b7b3cSmrg    XorCursor (ctx);
1462145b7b3cSmrg}
1463145b7b3cSmrg
1464145b7b3cSmrg
1465145b7b3cSmrg/**** Copied from xclock.c - original author: Keith Packard ****/
1466145b7b3cSmrg#ifdef USE_XFT
1467145b7b3cSmrgstatic XtConvertArgRec xftColorConvertArgs[] = {
1468145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1469145b7b3cSmrg     sizeof(Screen *)},
1470145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
1471145b7b3cSmrg     sizeof(Colormap)}
1472145b7b3cSmrg};
1473145b7b3cSmrg
1474578741aaSmrg# define	donestr(type, value, tstr) \
1475145b7b3cSmrg	{							\
1476145b7b3cSmrg	    if (toVal->addr != NULL) {				\
1477145b7b3cSmrg		if (toVal->size < sizeof(type)) {		\
1478145b7b3cSmrg		    toVal->size = sizeof(type);			\
1479145b7b3cSmrg		    XtDisplayStringConversionWarning(dpy, 	\
1480145b7b3cSmrg			(char*) fromVal->addr, tstr);		\
1481145b7b3cSmrg		    return False;				\
1482145b7b3cSmrg		}						\
1483145b7b3cSmrg		*(type*)(toVal->addr) = (value);		\
1484145b7b3cSmrg	    }							\
1485145b7b3cSmrg	    else {						\
1486145b7b3cSmrg		static type static_val;				\
1487145b7b3cSmrg		static_val = (value);				\
1488145b7b3cSmrg		toVal->addr = (XPointer)&static_val;		\
1489145b7b3cSmrg	    }							\
1490145b7b3cSmrg	    toVal->size = sizeof(type);				\
1491145b7b3cSmrg	    return True;					\
1492145b7b3cSmrg	}
1493145b7b3cSmrg
1494145b7b3cSmrgstatic void
1495145b7b3cSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1496145b7b3cSmrg		 XrmValuePtr args, Cardinal *num_args)
1497145b7b3cSmrg{
1498145b7b3cSmrg    Screen	*screen;
1499145b7b3cSmrg    Colormap	colormap;
1500145b7b3cSmrg    XftColor	*color;
1501578741aaSmrg
1502145b7b3cSmrg    if (*num_args != 2)
1503145b7b3cSmrg    {
1504145b7b3cSmrg	XtAppErrorMsg (app,
1505145b7b3cSmrg		       "freeXftColor", "wrongParameters",
1506145b7b3cSmrg		       "XtToolkitError",
1507145b7b3cSmrg		       "Freeing an XftColor requires screen and colormap arguments",
1508145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1509145b7b3cSmrg	return;
1510145b7b3cSmrg    }
1511145b7b3cSmrg
1512145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1513145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1514145b7b3cSmrg    color = (XftColor *) toVal->addr;
1515145b7b3cSmrg    XftColorFree (DisplayOfScreen (screen),
1516145b7b3cSmrg		  DefaultVisual (DisplayOfScreen (screen),
1517145b7b3cSmrg				 XScreenNumberOfScreen (screen)),
1518145b7b3cSmrg		  colormap, color);
1519145b7b3cSmrg}
1520578741aaSmrg
1521145b7b3cSmrgstatic Boolean
1522145b7b3cSmrgXmuCvtStringToXftColor(Display *dpy,
1523145b7b3cSmrg		       XrmValue *args, Cardinal *num_args,
1524145b7b3cSmrg		       XrmValue *fromVal, XrmValue *toVal,
1525145b7b3cSmrg		       XtPointer *converter_data)
1526145b7b3cSmrg{
1527145b7b3cSmrg    char	    *spec;
1528145b7b3cSmrg    XRenderColor    renderColor;
1529145b7b3cSmrg    XftColor	    xftColor;
1530145b7b3cSmrg    Screen	    *screen;
1531145b7b3cSmrg    Colormap	    colormap;
1532578741aaSmrg
1533145b7b3cSmrg    if (*num_args != 2)
1534145b7b3cSmrg    {
1535145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1536145b7b3cSmrg		       "cvtStringToXftColor", "wrongParameters",
1537145b7b3cSmrg		       "XtToolkitError",
1538145b7b3cSmrg		       "String to render color conversion needs screen and colormap arguments",
1539145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1540145b7b3cSmrg	return False;
1541145b7b3cSmrg    }
1542145b7b3cSmrg
1543145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1544145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1545145b7b3cSmrg
1546145b7b3cSmrg    spec = (char *) fromVal->addr;
1547145b7b3cSmrg    if (strcasecmp (spec, XtDefaultForeground) == 0)
1548145b7b3cSmrg    {
1549145b7b3cSmrg	renderColor.red = 0;
1550145b7b3cSmrg	renderColor.green = 0;
1551145b7b3cSmrg	renderColor.blue = 0;
1552145b7b3cSmrg	renderColor.alpha = 0xffff;
1553145b7b3cSmrg    }
1554145b7b3cSmrg    else if (strcasecmp (spec, XtDefaultBackground) == 0)
1555145b7b3cSmrg    {
1556145b7b3cSmrg	renderColor.red = 0xffff;
1557145b7b3cSmrg	renderColor.green = 0xffff;
1558145b7b3cSmrg	renderColor.blue = 0xffff;
1559145b7b3cSmrg	renderColor.alpha = 0xffff;
1560145b7b3cSmrg    }
1561145b7b3cSmrg    else if (!XRenderParseColor (dpy, spec, &renderColor))
1562145b7b3cSmrg	return False;
1563578741aaSmrg    if (!XftColorAllocValue (dpy,
1564145b7b3cSmrg			     DefaultVisual (dpy,
1565145b7b3cSmrg					    XScreenNumberOfScreen (screen)),
1566145b7b3cSmrg			     colormap,
1567145b7b3cSmrg			     &renderColor,
1568145b7b3cSmrg			     &xftColor))
1569145b7b3cSmrg	return False;
1570578741aaSmrg
1571145b7b3cSmrg    donestr (XftColor, xftColor, XtRXftColor);
1572145b7b3cSmrg}
1573145b7b3cSmrg
1574145b7b3cSmrgstatic void
1575145b7b3cSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1576145b7b3cSmrg		XrmValuePtr args, Cardinal *num_args)
1577145b7b3cSmrg{
1578145b7b3cSmrg    Screen  *screen;
1579145b7b3cSmrg    XftFont *font;
1580578741aaSmrg
1581145b7b3cSmrg    if (*num_args != 1)
1582145b7b3cSmrg    {
1583145b7b3cSmrg	XtAppErrorMsg (app,
1584145b7b3cSmrg		       "freeXftFont", "wrongParameters",
1585145b7b3cSmrg		       "XtToolkitError",
1586145b7b3cSmrg		       "Freeing an XftFont requires screen argument",
1587145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1588145b7b3cSmrg	return;
1589145b7b3cSmrg    }
1590145b7b3cSmrg
1591145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1592145b7b3cSmrg    font = *((XftFont **) toVal->addr);
1593145b7b3cSmrg    if (font)
1594145b7b3cSmrg	XftFontClose (DisplayOfScreen (screen), font);
1595145b7b3cSmrg}
1596145b7b3cSmrg
1597145b7b3cSmrgstatic Boolean
1598145b7b3cSmrgXmuCvtStringToXftFont(Display *dpy,
1599145b7b3cSmrg		      XrmValue *args, Cardinal *num_args,
1600145b7b3cSmrg		      XrmValue *fromVal, XrmValue *toVal,
1601145b7b3cSmrg		      XtPointer *converter_data)
1602145b7b3cSmrg{
1603145b7b3cSmrg    char    *name;
1604145b7b3cSmrg    XftFont *font;
1605145b7b3cSmrg    Screen  *screen;
1606578741aaSmrg
1607145b7b3cSmrg    if (*num_args != 1)
1608145b7b3cSmrg    {
1609145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1610145b7b3cSmrg		       "cvtStringToXftFont", "wrongParameters",
1611145b7b3cSmrg		       "XtToolkitError",
1612145b7b3cSmrg		       "String to XftFont conversion needs screen argument",
1613145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1614145b7b3cSmrg	return False;
1615145b7b3cSmrg    }
1616145b7b3cSmrg
1617145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1618145b7b3cSmrg    name = (char *) fromVal->addr;
1619578741aaSmrg
1620145b7b3cSmrg    font = XftFontOpenName (dpy,
1621145b7b3cSmrg			    XScreenNumberOfScreen (screen),
1622145b7b3cSmrg			    name);
1623145b7b3cSmrg    if (font)
1624145b7b3cSmrg    {
1625145b7b3cSmrg	donestr (XftFont *, font, XtRXftFont);
1626145b7b3cSmrg    }
1627145b7b3cSmrg    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
1628145b7b3cSmrg    return False;
1629145b7b3cSmrg}
1630145b7b3cSmrg
1631145b7b3cSmrgstatic XtConvertArgRec xftFontConvertArgs[] = {
1632145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1633145b7b3cSmrg     sizeof(Screen *)},
1634145b7b3cSmrg};
1635145b7b3cSmrg
1636145b7b3cSmrg
1637145b7b3cSmrgstatic int
1638145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len)
1639145b7b3cSmrg{
1640145b7b3cSmrg    XGlyphInfo  extents;
1641145b7b3cSmrg
1642145b7b3cSmrg    XftTextExtents8 (dpy, font, string, len, &extents);
1643145b7b3cSmrg
1644145b7b3cSmrg    return extents.xOff;
1645145b7b3cSmrg}
1646145b7b3cSmrg
1647145b7b3cSmrg#endif /* USE_XFT */
1648145b7b3cSmrg
1649578741aaSmrgstatic void
1650145b7b3cSmrgClassInitialize(void)
1651145b7b3cSmrg{
1652145b7b3cSmrg#ifdef USE_XFT
1653578741aaSmrg    XtSetTypeConverter (XtRString, XtRXftColor,
1654578741aaSmrg			XmuCvtStringToXftColor,
1655145b7b3cSmrg			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
1656145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftColor);
1657145b7b3cSmrg    XtSetTypeConverter (XtRString, XtRXftFont,
1658145b7b3cSmrg			XmuCvtStringToXftFont,
1659145b7b3cSmrg			xftFontConvertArgs, XtNumber(xftFontConvertArgs),
1660145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftFont);
1661145b7b3cSmrg#endif /* USE_XFT */
1662145b7b3cSmrg}
1663145b7b3cSmrg/**** End of portion borrowed from xclock ****/
1664145b7b3cSmrg
1665145b7b3cSmrg/* ARGSUSED */
1666145b7b3cSmrgstatic void Initialize (
1667145b7b3cSmrg    Widget greq,
1668145b7b3cSmrg    Widget gnew,
1669145b7b3cSmrg    ArgList args,
1670145b7b3cSmrg    Cardinal *num_args)
1671145b7b3cSmrg{
1672145b7b3cSmrg    LoginWidget w = (LoginWidget)gnew;
1673145b7b3cSmrg    XtGCMask	valuemask, xvaluemask;
1674145b7b3cSmrg    XGCValues	myXGCV;
1675145b7b3cSmrg    Arg		position[2];
1676145b7b3cSmrg    Position	x, y;
1677145b7b3cSmrg#ifdef USE_XINERAMA
1678145b7b3cSmrg    XineramaScreenInfo *screens;
1679145b7b3cSmrg    int                 s_num;
1680145b7b3cSmrg#endif
1681145b7b3cSmrg    int 	rv = 0;
1682578741aaSmrg
1683145b7b3cSmrg    myXGCV.foreground = w->login.hipixel;
1684145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1685145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1686145b7b3cSmrg    w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV);
1687145b7b3cSmrg
1688145b7b3cSmrg    myXGCV.foreground = w->login.shdpixel;
1689145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1690145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1691145b7b3cSmrg    w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV);
1692145b7b3cSmrg
1693b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1694b7d26471Smrg    myXGCV.background = w->core.background_pixel;
1695b7d26471Smrg    valuemask = GCForeground | GCBackground;
1696b7d26471Smrg    w->login.inpGC = XtGetGC(gnew, valuemask, &myXGCV);
1697b7d26471Smrg
1698145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text);
1699145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1700145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1701145b7b3cSmrg#ifndef USE_XFT
1702145b7b3cSmrg    if (w->login.textFont) {
1703145b7b3cSmrg	myXGCV.font = w->login.textFont->fid;
1704145b7b3cSmrg	valuemask |= GCFont;
1705145b7b3cSmrg    }
1706578741aaSmrg#endif
1707145b7b3cSmrg    w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
1708b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1709145b7b3cSmrg    w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
1710145b7b3cSmrg
1711b7d26471Smrg    myXGCV.foreground = TEXT_COLOR(text) ^ w->login.inppixel;
1712145b7b3cSmrg    myXGCV.function = GXxor;
1713145b7b3cSmrg    xvaluemask = valuemask | GCFunction;
1714145b7b3cSmrg    w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1715145b7b3cSmrg
1716145b7b3cSmrg#ifndef USE_XFT
1717145b7b3cSmrg    /*
1718145b7b3cSmrg     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
1719145b7b3cSmrg     * returns the curently contained font.
1720145b7b3cSmrg     */
1721145b7b3cSmrg
1722145b7b3cSmrg    if (w->login.textFont == NULL)
1723145b7b3cSmrg	w->login.textFont = XQueryFont (XtDisplay (w),
1724145b7b3cSmrg		XGContextFromGC (XDefaultGCOfScreen (XtScreen (w))));
1725145b7b3cSmrg
1726145b7b3cSmrg    xvaluemask = valuemask;
1727145b7b3cSmrg    if (w->login.promptFont == NULL)
1728145b7b3cSmrg        w->login.promptFont = w->login.textFont;
1729145b7b3cSmrg    else
1730145b7b3cSmrg	xvaluemask |= GCFont;
1731145b7b3cSmrg
1732145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(prompt);
1733145b7b3cSmrg    myXGCV.font = w->login.promptFont->fid;
1734145b7b3cSmrg    w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1735145b7b3cSmrg
1736145b7b3cSmrg    xvaluemask = valuemask;
1737145b7b3cSmrg    if (w->login.greetFont == NULL)
1738629baa8cSmrg	w->login.greetFont = w->login.textFont;
1739145b7b3cSmrg    else
1740145b7b3cSmrg	xvaluemask |= GCFont;
1741145b7b3cSmrg
1742145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(greet);
1743145b7b3cSmrg    myXGCV.font = w->login.greetFont->fid;
1744145b7b3cSmrg    w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1745145b7b3cSmrg
1746145b7b3cSmrg    xvaluemask = valuemask;
1747145b7b3cSmrg    if (w->login.failFont == NULL)
1748145b7b3cSmrg	w->login.failFont = w->login.textFont;
1749145b7b3cSmrg    else
1750145b7b3cSmrg	xvaluemask |= GCFont;
1751145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(fail);
1752145b7b3cSmrg    myXGCV.font = w->login.failFont->fid;
1753145b7b3cSmrg    w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1754145b7b3cSmrg#endif /* USE_XFT */
1755145b7b3cSmrg
1756145b7b3cSmrg#ifdef XPM
1757145b7b3cSmrg    w->login.logoValid = False;
1758145b7b3cSmrg
1759145b7b3cSmrg    if (NULL != w->login.logoFileName)
1760145b7b3cSmrg    {
1761145b7b3cSmrg        XpmAttributes myAttributes = { 0 };
1762145b7b3cSmrg        Window tmpWindow = { 0 };
1763145b7b3cSmrg        struct stat myBuffer = { 0 };
1764145b7b3cSmrg        unsigned int myPixmapDepth = 0;
1765145b7b3cSmrg
1766145b7b3cSmrg        if (0 != stat(w->login.logoFileName, &myBuffer))
1767145b7b3cSmrg        {
1768145b7b3cSmrg            LogError("Unable to stat() pixmap file %s\n",
1769145b7b3cSmrg                w->login.logoFileName);
1770145b7b3cSmrg            w->login.logoValid = False;
1771145b7b3cSmrg            goto SkipXpmLoad;
1772145b7b3cSmrg        }
1773145b7b3cSmrg
1774145b7b3cSmrg        myAttributes.valuemask |= XpmReturnPixels;
1775145b7b3cSmrg        myAttributes.valuemask |= XpmReturnExtensions;
1776145b7b3cSmrg
1777145b7b3cSmrg        rv = XpmReadFileToPixmap(XtDisplay(w),		/* display */
1778145b7b3cSmrg	     RootWindowOfScreen(XtScreen(w)),		/* window */
1779145b7b3cSmrg	     w->login.logoFileName,			/* XPM filename */
1780145b7b3cSmrg	     &(w->login.logoPixmap),			/* pixmap */
1781145b7b3cSmrg	     &(w->login.logoMask),			/* pixmap mask */
1782145b7b3cSmrg	     &myAttributes);				/* XPM attributes */
1783578741aaSmrg
1784145b7b3cSmrg	if ( rv < 0 )
1785145b7b3cSmrg	{
1786145b7b3cSmrg	    LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName,
1787145b7b3cSmrg		     XpmGetErrorString(rv));
1788145b7b3cSmrg	    goto SkipXpmLoad;
1789145b7b3cSmrg	}
1790145b7b3cSmrg
1791145b7b3cSmrg	w->login.logoValid = True;
1792145b7b3cSmrg
1793145b7b3cSmrg        XGetGeometry(XtDisplay(w), w->login.logoPixmap,
1794145b7b3cSmrg            &tmpWindow,
1795145b7b3cSmrg            &(w->login.logoX),
1796145b7b3cSmrg            &(w->login.logoY),
1797145b7b3cSmrg            &(w->login.logoWidth),
1798145b7b3cSmrg            &(w->login.logoHeight),
1799145b7b3cSmrg            &(w->login.logoBorderWidth),
1800145b7b3cSmrg            &myPixmapDepth);
1801145b7b3cSmrg    } else {
1802145b7b3cSmrg	w->login.logoX = 0;
1803145b7b3cSmrg	w->login.logoY = 0;
1804145b7b3cSmrg	w->login.logoWidth = 0;
1805145b7b3cSmrg	w->login.logoHeight = 0;
1806145b7b3cSmrg	w->login.logoBorderWidth = 0;
1807145b7b3cSmrg    }
1808145b7b3cSmrg
1809145b7b3cSmrg
1810145b7b3cSmrgSkipXpmLoad:
1811145b7b3cSmrg#endif /* XPM */
1812145b7b3cSmrg    w->login.data.name[0] = '\0';
1813145b7b3cSmrg    w->login.data.passwd[0] = '\0';
1814145b7b3cSmrg    w->login.state = INITIALIZING;
1815145b7b3cSmrg    w->login.activePrompt = LOGIN_PROMPT_USERNAME;
1816145b7b3cSmrg    w->login.failUp = 0;
1817145b7b3cSmrg    w->login.fail = (char *) w->login.failMsg;
1818145b7b3cSmrg
1819145b7b3cSmrg    /* Set prompt defaults */
1820145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= NULL;
1821145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.namePrompt;
1822145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.data.name;
1823145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME)	= sizeof(w->login.data.name);
1824145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME)	= 0;
1825578741aaSmrg
1826145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= NULL;
1827145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.passwdPrompt;
1828145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.data.passwd;
1829145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD)	= sizeof(w->login.data.passwd);
1830145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD)	= 0;
1831145b7b3cSmrg
1832145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False);
1833145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False);
1834578741aaSmrg
1835145b7b3cSmrg    if (w->core.width == 0)
1836145b7b3cSmrg	w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
1837145b7b3cSmrg    if (w->core.height == 0) {
1838145b7b3cSmrg	int fy = FAIL_Y(w);
1839145b7b3cSmrg	int pady = PAD_Y(w);
1840145b7b3cSmrg
1841145b7b3cSmrg#ifndef XPM
1842145b7b3cSmrg	w->core.height = fy + pady;	/* for stupid compilers */
1843145b7b3cSmrg#else
1844145b7b3cSmrg/*	w->core.height = fy + pady;	* for stupid compilers */
1845145b7b3cSmrg
1846145b7b3cSmrg        w->core.height = max(fy + pady,
1847145b7b3cSmrg            (w->login.logoHeight + (2*w->login.logoPadding)) + pady);
1848578741aaSmrg
1849145b7b3cSmrg#endif /* XPM */
1850145b7b3cSmrg    }
1851145b7b3cSmrg#ifdef USE_XINERAMA
1852145b7b3cSmrg    if (
1853145b7b3cSmrg	XineramaIsActive(XtDisplay(w)) &&
1854145b7b3cSmrg	(screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL
1855145b7b3cSmrg       )
1856145b7b3cSmrg    {
1857145b7b3cSmrg	if ((x = w->core.x) == -1)
1858145b7b3cSmrg	    x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2;
1859145b7b3cSmrg	if ((y = w->core.y) == -1)
1860145b7b3cSmrg	    y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3;
1861578741aaSmrg
1862145b7b3cSmrg	XFree(screens);
1863145b7b3cSmrg    }
1864145b7b3cSmrg    else
1865145b7b3cSmrg#endif
1866145b7b3cSmrg    {
1867145b7b3cSmrg	if ((x = w->core.x) == -1)
1868145b7b3cSmrg	    x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2;
1869145b7b3cSmrg	if ((y = w->core.y) == -1)
1870145b7b3cSmrg	    y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3;
1871145b7b3cSmrg    }
1872145b7b3cSmrg    XtSetArg (position[0], XtNx, x);
1873145b7b3cSmrg    XtSetArg (position[1], XtNy, y);
1874145b7b3cSmrg    XtSetValues (XtParent (w), position, (Cardinal) 2);
1875145b7b3cSmrg
1876145b7b3cSmrg    w->login.state = PROMPTING;
1877145b7b3cSmrg}
1878145b7b3cSmrg
1879578741aaSmrg
1880145b7b3cSmrgstatic void Realize (
1881145b7b3cSmrg     Widget gw,
1882145b7b3cSmrg     XtValueMask *valueMask,
1883145b7b3cSmrg     XSetWindowAttributes *attrs)
1884145b7b3cSmrg{
1885145b7b3cSmrg    LoginWidget	w = (LoginWidget) gw;
1886145b7b3cSmrg    Cursor cursor;
1887145b7b3cSmrg
1888145b7b3cSmrg    XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
1889145b7b3cSmrg		     *valueMask, attrs );
1890145b7b3cSmrg    InitI18N(gw);
1891145b7b3cSmrg
1892145b7b3cSmrg#ifdef USE_XFT
1893145b7b3cSmrg    w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w),
1894145b7b3cSmrg	   DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))),
1895145b7b3cSmrg				   w->core.colormap);
1896145b7b3cSmrg
1897145b7b3cSmrg#endif
1898145b7b3cSmrg
1899145b7b3cSmrg    cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr);
1900145b7b3cSmrg    XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor);
1901145b7b3cSmrg
1902145b7b3cSmrg#ifdef XPM
1903578741aaSmrg    /*
1904145b7b3cSmrg     * Check if Pixmap was valid
1905145b7b3cSmrg     */
1906145b7b3cSmrg    if (True == w->login.logoValid)
1907145b7b3cSmrg    {
1908145b7b3cSmrg        /*
1909578741aaSmrg         * Create pixmap window
1910145b7b3cSmrg         */
1911145b7b3cSmrg        {
1912629baa8cSmrg            XSetWindowAttributes windowAttributes = {
1913629baa8cSmrg                .background_pixel = w->core.background_pixel,
1914629baa8cSmrg                .background_pixmap = None
1915629baa8cSmrg            };
1916145b7b3cSmrg
1917145b7b3cSmrg            w->login.logoWindow = XCreateWindow(XtDisplay(w),
1918145b7b3cSmrg                XtWindow(w),
1919145b7b3cSmrg                w->core.width - w->login.outframewidth -
1920145b7b3cSmrg                    w->login.logoWidth - w->login.logoPadding,
1921145b7b3cSmrg                (w->core.height - w->login.logoHeight) /2,
1922145b7b3cSmrg                w->login.logoWidth, w->login.logoHeight, 0,
1923145b7b3cSmrg                CopyFromParent, InputOutput, CopyFromParent,
1924629baa8cSmrg                CWBackPixel | CWBackPixmap, &windowAttributes);
1925145b7b3cSmrg        }
1926145b7b3cSmrg
1927145b7b3cSmrg        /*
1928145b7b3cSmrg         * check if we can use shape extension
1929145b7b3cSmrg         */
1930145b7b3cSmrg        if (True == w->login.useShape)
1931145b7b3cSmrg        {
1932145b7b3cSmrg            int foo, bar;
1933145b7b3cSmrg
1934145b7b3cSmrg            if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE)
1935145b7b3cSmrg            {
1936145b7b3cSmrg                XShapeCombineMask(XtDisplay(w), w->login.logoWindow,
1937145b7b3cSmrg                    ShapeBounding, w->login.logoX, w->login.logoY,
1938145b7b3cSmrg                    w->login.logoMask, ShapeSet);
1939145b7b3cSmrg            }
1940145b7b3cSmrg        }
1941145b7b3cSmrg
1942145b7b3cSmrg        XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow,
1943145b7b3cSmrg            w->login.logoPixmap);
1944145b7b3cSmrg        XMapWindow(XtDisplay(w), w->login.logoWindow);
1945145b7b3cSmrg    }
1946145b7b3cSmrg#endif /* XPM */
1947145b7b3cSmrg}
1948145b7b3cSmrg
1949145b7b3cSmrgstatic void Destroy (Widget gw)
1950145b7b3cSmrg{
1951145b7b3cSmrg    LoginWidget w = (LoginWidget)gw;
1952145b7b3cSmrg    bzero (w->login.data.name, NAME_LEN);
1953145b7b3cSmrg    bzero (w->login.data.passwd, PASSWORD_LEN);
1954145b7b3cSmrg
1955145b7b3cSmrg    if (PROMPT_TEXT(w,0) != NULL)
1956145b7b3cSmrg	XtFree(PROMPT_TEXT(w,0));
1957145b7b3cSmrg    if (PROMPT_TEXT(w,1) != NULL)
1958145b7b3cSmrg	XtFree(PROMPT_TEXT(w,1));
1959145b7b3cSmrg
1960145b7b3cSmrg#ifdef USE_XFT
1961145b7b3cSmrg    if (w->login.draw) {
1962145b7b3cSmrg	XftDrawDestroy(w->login.draw);
1963145b7b3cSmrg	w->login.draw = NULL;
1964145b7b3cSmrg    }
1965578741aaSmrg#endif
1966578741aaSmrg
1967145b7b3cSmrg    XtReleaseGC(gw, w->login.textGC);
1968145b7b3cSmrg    XtReleaseGC(gw, w->login.bgGC);
1969145b7b3cSmrg    XtReleaseGC(gw, w->login.xorGC);
1970145b7b3cSmrg#ifndef USE_XFT
1971145b7b3cSmrg    XtReleaseGC(gw, w->login.promptGC);
1972145b7b3cSmrg    XtReleaseGC(gw, w->login.greetGC);
1973145b7b3cSmrg    XtReleaseGC(gw, w->login.failGC);
1974145b7b3cSmrg#endif
1975145b7b3cSmrg    XtReleaseGC(gw, w->login.hiGC);
1976145b7b3cSmrg    XtReleaseGC(gw, w->login.shdGC);
1977b7d26471Smrg    XtReleaseGC(gw, w->login.inpGC);
1978145b7b3cSmrg
1979145b7b3cSmrg#ifdef XPM
1980145b7b3cSmrg    if (True == w->login.logoValid)
1981145b7b3cSmrg    {
1982145b7b3cSmrg        if (w->login.logoPixmap != 0)
1983145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoPixmap);
1984145b7b3cSmrg
1985145b7b3cSmrg        if (w->login.logoMask != 0)
1986145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoMask);
1987145b7b3cSmrg    }
1988145b7b3cSmrg#endif /* XPM */
1989145b7b3cSmrg}
1990145b7b3cSmrg
1991145b7b3cSmrg/* ARGSUSED */
1992145b7b3cSmrgstatic void Redisplay(
1993145b7b3cSmrg     Widget gw,
1994145b7b3cSmrg     XEvent *event,
1995145b7b3cSmrg     Region region)
1996145b7b3cSmrg{
1997145b7b3cSmrg    draw_it ((LoginWidget) gw);
1998145b7b3cSmrg}
1999145b7b3cSmrg
2000145b7b3cSmrg/*ARGSUSED*/
2001145b7b3cSmrgstatic Boolean SetValues (
2002145b7b3cSmrg    Widget  current,
2003145b7b3cSmrg    Widget  request,
2004145b7b3cSmrg    Widget  new,
2005145b7b3cSmrg    ArgList args,
2006145b7b3cSmrg    Cardinal *num_args)
2007145b7b3cSmrg{
2008145b7b3cSmrg    LoginWidget currentL, newL;
2009578741aaSmrg
2010145b7b3cSmrg    currentL = (LoginWidget) current;
2011145b7b3cSmrg    newL = (LoginWidget) new;
2012145b7b3cSmrg    if (GREETING (currentL) != GREETING (newL))
2013145b7b3cSmrg	return True;
2014145b7b3cSmrg    return False;
2015145b7b3cSmrg}
2016145b7b3cSmrg
2017145b7b3cSmrgstatic
2018145b7b3cSmrgchar defaultLoginTranslations [] =
2019145b7b3cSmrg"Ctrl<Key>H:	delete-previous-character() \n"
2020145b7b3cSmrg"Ctrl<Key>D:	delete-character() \n"
2021145b7b3cSmrg"Ctrl<Key>B:	move-backward-character() \n"
2022145b7b3cSmrg"Ctrl<Key>F:	move-forward-character() \n"
2023145b7b3cSmrg"Ctrl<Key>A:	move-to-begining() \n"
2024145b7b3cSmrg"Ctrl<Key>E:	move-to-end() \n"
2025145b7b3cSmrg"Ctrl<Key>K:	erase-to-end-of-line() \n"
2026145b7b3cSmrg"Ctrl<Key>U:	erase-line() \n"
2027145b7b3cSmrg"Ctrl<Key>X:	erase-line() \n"
2028145b7b3cSmrg"Ctrl<Key>C:	restart-session() \n"
2029145b7b3cSmrg"Ctrl<Key>\\\\:	abort-session() \n"
2030145b7b3cSmrg":Ctrl<Key>plus:	allow-all-access() \n"
2031145b7b3cSmrg"<Key>BackSpace:	delete-previous-character() \n"
2032145b7b3cSmrg#ifdef linux
2033145b7b3cSmrg"<Key>Delete:	delete-character() \n"
2034145b7b3cSmrg#else
2035145b7b3cSmrg"<Key>Delete:	delete-previous-character() \n"
2036145b7b3cSmrg#endif
2037145b7b3cSmrg"<Key>Return:	finish-field() \n"
2038145b7b3cSmrg"<Key>Tab:	tab-field() \n"
2039145b7b3cSmrg"<KeyPress>:	insert-char()"
2040145b7b3cSmrg;
2041145b7b3cSmrg
2042145b7b3cSmrgstatic
2043145b7b3cSmrgXtActionsRec loginActionsTable [] = {
2044145b7b3cSmrg  {"delete-previous-character",	DeleteBackwardChar},
2045145b7b3cSmrg  {"delete-character",		DeleteForwardChar},
2046145b7b3cSmrg  {"move-backward-character",	MoveBackwardChar},
2047145b7b3cSmrg  {"move-forward-character",	MoveForwardChar},
2048145b7b3cSmrg  {"move-to-begining",		MoveToBegining},
2049145b7b3cSmrg  {"move-to-end",		MoveToEnd},
2050145b7b3cSmrg  {"erase-to-end-of-line",	EraseToEndOfLine},
2051145b7b3cSmrg  {"erase-line",		EraseLine},
2052145b7b3cSmrg  {"finish-field", 		FinishField},
2053145b7b3cSmrg  {"tab-field", 		TabField},
2054145b7b3cSmrg  {"abort-session",		AbortSession},
2055145b7b3cSmrg  {"abort-display",		AbortDisplay},
2056145b7b3cSmrg  {"restart-session",		RestartSession},
2057145b7b3cSmrg  {"insert-char", 		InsertChar},
2058145b7b3cSmrg  {"set-session-argument",	SetSessionArgument},
2059145b7b3cSmrg  {"allow-all-access",		AllowAccess},
2060145b7b3cSmrg};
2061145b7b3cSmrg
2062145b7b3cSmrgLoginClassRec loginClassRec = {
2063145b7b3cSmrg    { /* core fields */
2064145b7b3cSmrg    /* superclass		*/	&widgetClassRec,
2065145b7b3cSmrg    /* class_name		*/	"Login",
2066145b7b3cSmrg    /* size			*/	sizeof(LoginRec),
2067145b7b3cSmrg    /* class_initialize		*/	ClassInitialize,
2068145b7b3cSmrg    /* class_part_initialize	*/	NULL,
2069145b7b3cSmrg    /* class_inited		*/	FALSE,
2070145b7b3cSmrg    /* initialize		*/	Initialize,
2071145b7b3cSmrg    /* initialize_hook		*/	NULL,
2072145b7b3cSmrg    /* realize			*/	Realize,
2073145b7b3cSmrg    /* actions			*/	loginActionsTable,
2074145b7b3cSmrg    /* num_actions		*/	XtNumber (loginActionsTable),
2075145b7b3cSmrg    /* resources		*/	resources,
2076145b7b3cSmrg    /* num_resources		*/	XtNumber(resources),
2077145b7b3cSmrg    /* xrm_class		*/	NULLQUARK,
2078145b7b3cSmrg    /* compress_motion		*/	TRUE,
2079145b7b3cSmrg    /* compress_exposure	*/	TRUE,
2080145b7b3cSmrg    /* compress_enterleave	*/	TRUE,
2081145b7b3cSmrg    /* visible_interest		*/	FALSE,
2082145b7b3cSmrg    /* destroy			*/	Destroy,
2083145b7b3cSmrg    /* resize			*/	NULL,
2084145b7b3cSmrg    /* expose			*/	Redisplay,
2085145b7b3cSmrg    /* set_values		*/	SetValues,
2086145b7b3cSmrg    /* set_values_hook		*/	NULL,
2087145b7b3cSmrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
2088145b7b3cSmrg    /* get_values_hook		*/	NULL,
2089145b7b3cSmrg    /* accept_focus		*/	NULL,
2090145b7b3cSmrg    /* version			*/	XtVersion,
2091145b7b3cSmrg    /* callback_private		*/	NULL,
2092145b7b3cSmrg    /* tm_table			*/	defaultLoginTranslations,
2093145b7b3cSmrg    /* query_geometry		*/	XtInheritQueryGeometry,
2094145b7b3cSmrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
2095145b7b3cSmrg    /* extension		*/	NULL
2096145b7b3cSmrg    }
2097145b7b3cSmrg};
2098145b7b3cSmrg
2099145b7b3cSmrgWidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
2100