Login.c revision 629baa8c
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
89145b7b3cSmrg#ifndef DEBUG
90145b7b3cSmrg# define XDM_ASSERT(a)	/* do nothing */
91145b7b3cSmrg#else
92145b7b3cSmrg# if defined(__STDC__) && __STDC_VERSION__ - 0 >= 199901L
93145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
94145b7b3cSmrg	Debug("Assertion failed in %s() at file %s line %d\n", \
95145b7b3cSmrg	      __func__, __FILE__, __LINE__); }
96145b7b3cSmrg# else
97145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
98145b7b3cSmrg	Debug("Assertion failed at file %s line %d\n", __FILE__, __LINE__); }
99145b7b3cSmrg# endif
100145b7b3cSmrg#endif
101145b7b3cSmrg
102145b7b3cSmrgstatic void RedrawFail (LoginWidget w);
103145b7b3cSmrgstatic void ResetLogin (LoginWidget w);
104145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id);
105145b7b3cSmrgstatic void EraseCursor (LoginWidget w);
106145b7b3cSmrgstatic void XorCursor (LoginWidget w);
107145b7b3cSmrg
108145b7b3cSmrg#define offset(field) XtOffsetOf(LoginRec, login.field)
109145b7b3cSmrg#define goffset(field) XtOffsetOf(WidgetRec, core.field)
110145b7b3cSmrg
111145b7b3cSmrg
112145b7b3cSmrgstatic XtResource resources[] = {
113145b7b3cSmrg    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
114145b7b3cSmrg	goffset(width), XtRImmediate,	(XtPointer) 0},
115145b7b3cSmrg    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
116145b7b3cSmrg	goffset(height), XtRImmediate,	(XtPointer) 0},
117145b7b3cSmrg    {XtNx, XtCX, XtRPosition, sizeof (Position),
118145b7b3cSmrg	goffset(x), XtRImmediate,	(XtPointer) -1},
119145b7b3cSmrg    {XtNy, XtCY, XtRPosition, sizeof (Position),
120145b7b3cSmrg	goffset(y), XtRImmediate,	(XtPointer) -1},
121578741aaSmrg#ifndef USE_XFT
122145b7b3cSmrg    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
123145b7b3cSmrg        offset(textpixel), XtRString,	XtDefaultForeground},
124145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel),
125145b7b3cSmrg        offset(promptpixel), XtRString,	XtDefaultForeground},
126145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel),
127145b7b3cSmrg        offset(greetpixel), XtRString,	XtDefaultForeground},
128145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel),
129145b7b3cSmrg	offset(failpixel), XtRString,	XtDefaultForeground},
130145b7b3cSmrg#endif
131145b7b3cSmrg
132145b7b3cSmrg#ifdef DANCING
133145b7b3cSmrg/* added by Caolan McNamara */
134145b7b3cSmrg	{XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int),
135145b7b3cSmrg	offset(lastEventTime), XtRImmediate,	(XtPointer)0},
136145b7b3cSmrg/* end (caolan) */
137145b7b3cSmrg#endif /* DANCING */
138145b7b3cSmrg
139578741aaSmrg#ifdef XPM
140145b7b3cSmrg/* added by Ivan Griffin (ivan.griffin@ul.ie) */
141145b7b3cSmrg        {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*),
142145b7b3cSmrg        offset(logoFileName), XtRImmediate, (XtPointer)0},
143145b7b3cSmrg        {XtNuseShape, XtCUseShape, XtRBoolean, sizeof(Boolean),
144145b7b3cSmrg        offset(useShape), XtRImmediate, (XtPointer) True},
145145b7b3cSmrg        {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int),
146145b7b3cSmrg        offset(logoPadding), XtRImmediate, (XtPointer) 5},
147145b7b3cSmrg/* end (ivan) */
148145b7b3cSmrg#endif /* XPM */
149145b7b3cSmrg
150145b7b3cSmrg/* added by Amit Margalit */
151145b7b3cSmrg    {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel),
152145b7b3cSmrg	offset(hipixel), XtRString,	XtDefaultForeground},
153145b7b3cSmrg    {XtNshdColor, XtCForeground, XtRPixel, sizeof (Pixel),
154145b7b3cSmrg	offset(shdpixel), XtRString,	XtDefaultForeground},
155145b7b3cSmrg    {XtNframeWidth, XtCFrameWidth, XtRInt, sizeof(int),
156145b7b3cSmrg        offset(outframewidth), XtRImmediate, (XtPointer) 1},
157145b7b3cSmrg    {XtNinnerFramesWidth, XtCFrameWidth, XtRInt, sizeof(int),
158145b7b3cSmrg        offset(inframeswidth), XtRImmediate, (XtPointer) 1},
159145b7b3cSmrg    {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int),
160145b7b3cSmrg        offset(sepwidth), XtRImmediate, (XtPointer) 1},
161145b7b3cSmrg/* end (amit) */
162145b7b3cSmrg
163578741aaSmrg#ifndef USE_XFT
164145b7b3cSmrg    {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
165629baa8cSmrg	offset (textFont), XtRString,	"*-new century schoolbook-medium-r-normal-*-180-*"},
166145b7b3cSmrg    {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
167629baa8cSmrg	offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"},
168145b7b3cSmrg    {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
169629baa8cSmrg	offset (greetFont), XtRString,	"*-new century schoolbook-bold-i-normal-*-240-*"},
170145b7b3cSmrg    {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
171145b7b3cSmrg	offset (failFont), XtRString,	"*-new century schoolbook-bold-r-normal-*-180-*"},
172145b7b3cSmrg#else /* USE_XFT */
173145b7b3cSmrg    {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
174145b7b3cSmrg        offset (textFace), XtRString, "Serif-18"},
175145b7b3cSmrg    {XtNpromptFace, XtCFace, XtRXftFont, sizeof (XftFont *),
176145b7b3cSmrg        offset (promptFace), XtRString, "Serif-18:bold"},
177145b7b3cSmrg    {XtNgreetFace, XtCFace, XtRXftFont, sizeof (XftFont *),
178145b7b3cSmrg        offset (greetFace), XtRString, "Serif-24:italic"},
179145b7b3cSmrg    {XtNfailFace, XtCFace, XtRXftFont, sizeof (XftFont *),
180145b7b3cSmrg        offset (failFace), XtRString, "Serif-18:bold"},
181145b7b3cSmrg    {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
182145b7b3cSmrg        offset(textcolor), XtRString,	XtDefaultForeground},
183145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRXftColor, sizeof(XftColor),
184145b7b3cSmrg        offset(promptcolor), XtRString,	XtDefaultForeground},
185145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRXftColor, sizeof(XftColor),
186145b7b3cSmrg        offset(greetcolor), XtRString,	XtDefaultForeground},
187145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRXftColor, sizeof (XftColor),
188145b7b3cSmrg	offset(failcolor), XtRString,	XtDefaultForeground},
189145b7b3cSmrg#endif
190145b7b3cSmrg    {XtNgreeting, XtCGreeting, XtRString, sizeof (char *),
191629baa8cSmrg	offset(greeting), XtRString, "X Window System"},
192145b7b3cSmrg    {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *),
193145b7b3cSmrg	offset(unsecure_greet), XtRString, "This is an unsecure session"},
194145b7b3cSmrg    {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *),
195145b7b3cSmrg	offset(namePrompt), XtRString, "Login:  "},
196145b7b3cSmrg    {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *),
197145b7b3cSmrg	offset(passwdPrompt), XtRString, "Password:  "},
198145b7b3cSmrg    {XtNfail, XtCFail, XtRString, sizeof (char *),
199145b7b3cSmrg	offset(failMsg), XtRString,
200629baa8cSmrg	"Login incorrect or forbidden by policy"
201145b7b3cSmrg    },
202145b7b3cSmrg    {XtNchangePasswdMessage, XtCChangePasswdMessage, XtRString,
203145b7b3cSmrg	sizeof (char *), offset(passwdChangeMsg), XtRString,
204145b7b3cSmrg	(XtPointer) "Password Change Required" },
205145b7b3cSmrg    {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int),
206145b7b3cSmrg	offset(failTimeout), XtRImmediate, (XtPointer) 10},
207145b7b3cSmrg    {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer),
208145b7b3cSmrg	offset(notify_done), XtRFunction, (XtPointer) 0},
209145b7b3cSmrg    {XtNsessionArgument, XtCSessionArgument, XtRString,	sizeof (char *),
210145b7b3cSmrg	offset(sessionArg), XtRString, (XtPointer) 0 },
211145b7b3cSmrg    {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean),
212145b7b3cSmrg	offset(secure_session), XtRImmediate, (XtPointer) False },
213145b7b3cSmrg    {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean),
214145b7b3cSmrg	offset(allow_access), XtRImmediate, (XtPointer) False },
215145b7b3cSmrg    {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean),
216145b7b3cSmrg	offset(allow_null_passwd), XtRImmediate, (XtPointer) False},
217145b7b3cSmrg    {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean),
2185ffd6003Smrg	offset(allow_root_login), XtRImmediate, (XtPointer) True},
2195ffd6003Smrg    {XtNechoPasswd, XtCEchoPasswd, XtRBoolean, sizeof(Boolean),
220629baa8cSmrg	offset(echo_passwd), XtRImmediate, (XtPointer) False},
221629baa8cSmrg    {XtNechoPasswdChar, XtCEchoPasswdChar, XtRString,	sizeof (char *),
222629baa8cSmrg	offset(echo_passwd_char), XtRString, (XtPointer) "*" }
223145b7b3cSmrg};
224145b7b3cSmrg
225145b7b3cSmrg#undef offset
226145b7b3cSmrg#undef goffset
227145b7b3cSmrg
228145b7b3cSmrg#ifdef USE_XFT
229145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Face->max_advance_width)
230145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Face->ascent)
231145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Face->descent)
232145b7b3cSmrg#else
233145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Font->max_bounds.width)
234145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Font->max_bounds.ascent)
235145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Font->max_bounds.descent)
236145b7b3cSmrg#endif
237145b7b3cSmrg
238578741aaSmrg#define TEXT_X_INC(w)		F_MAX_WIDTH(text)
239578741aaSmrg#define TEXT_Y_INC(w)		(F_ASCENT(text) + F_DESCENT(text))
240145b7b3cSmrg
241578741aaSmrg#define PROMPT_X_INC(w)	F_MAX_WIDTH(prompt)
242578741aaSmrg#define PROMPT_Y_INC(w)	(F_ASCENT(prompt) + F_DESCENT(prompt))
243145b7b3cSmrg
244578741aaSmrg#define GREET_X_INC(w)		F_MAX_WIDTH(greet)
245578741aaSmrg#define GREET_Y_INC(w)		(F_ASCENT(greet) + F_DESCENT(greet))
246145b7b3cSmrg
247578741aaSmrg#define FAIL_X_INC(w)		F_MAX_WIDTH(fail)
248578741aaSmrg#define FAIL_Y_INC(w)		(F_ASCENT(fail) + F_DESCENT(fail))
249145b7b3cSmrg
250578741aaSmrg#define Y_INC(w)	max (TEXT_Y_INC(w), PROMPT_Y_INC(w))
251145b7b3cSmrg
252145b7b3cSmrg
253578741aaSmrg#define PROMPT_TEXT(w,n) 	((w)->login.prompts[n].promptText)
254578741aaSmrg#define DEF_PROMPT_TEXT(w,n) 	((w)->login.prompts[n].defaultPrompt)
255578741aaSmrg#define VALUE_TEXT(w,n) 	((w)->login.prompts[n].valueText)
256578741aaSmrg#define VALUE_TEXT_MAX(w,n)	((w)->login.prompts[n].valueTextMax)
257578741aaSmrg#define VALUE_SHOW_START(w,n)	((w)->login.prompts[n].valueShownStart)
258578741aaSmrg#define VALUE_SHOW_END(w,n)	((w)->login.prompts[n].valueShownEnd)
259578741aaSmrg#define PROMPT_STATE(w,n) 	((w)->login.prompts[n].state)
260578741aaSmrg#define PROMPT_CURSOR(w,n)	((w)->login.prompts[n].cursor)
261145b7b3cSmrg
262578741aaSmrg#define CUR_PROMPT_CURSOR(w)	PROMPT_CURSOR(w,w->login.activePrompt)
263145b7b3cSmrg
264578741aaSmrg#define CUR_PROMPT_TEXT(w, n)	(PROMPT_TEXT(w,n) != NULL ? \
265145b7b3cSmrg				 PROMPT_TEXT(w,n) : DEF_PROMPT_TEXT(w,n))
266145b7b3cSmrg
267145b7b3cSmrg#ifdef USE_XFT
268145b7b3cSmrg
269145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##color.pixel)
270145b7b3cSmrg
271145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	XmuXftTextWidth(XtDisplay (w), \
272145b7b3cSmrg					w->login.f##Face, (FcChar8 *) m, l)
273145b7b3cSmrgstatic int
274145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len);
275145b7b3cSmrg
276145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
277145b7b3cSmrg	/* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \
278145b7b3cSmrg	XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \
279145b7b3cSmrg			x, y, (FcChar8 *) m, l)
280145b7b3cSmrg
281145b7b3cSmrg#else
282145b7b3cSmrg
283145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##pixel)
284145b7b3cSmrg
285145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	(XTextWidth (w->login.f##Font, m, l))
286145b7b3cSmrg
287145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
288145b7b3cSmrg	XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l)
289145b7b3cSmrg
290145b7b3cSmrg#endif
291145b7b3cSmrg
292145b7b3cSmrg
293578741aaSmrg#define STRING_WIDTH(f, s) 	TEXT_WIDTH (f, s, strlen(s))
294145b7b3cSmrg
295629baa8cSmrg/* Padded width of logo image, if compiled with XPM support */
296629baa8cSmrg#ifdef XPM
297629baa8cSmrg# define LOGO_W(w)     ((w)->login.logoWidth + ((w)->login.logoPadding * 2))
298629baa8cSmrg#else
299629baa8cSmrg# define LOGO_W(w)     0
300629baa8cSmrg#endif
301145b7b3cSmrg
302578741aaSmrg#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth)
303145b7b3cSmrg
304578741aaSmrg#define DEF_PROMPT_W(w,n) TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt)
305578741aaSmrg#define CUR_PROMPT_W(w,n)  (max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \
306145b7b3cSmrg		     TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0))
307145b7b3cSmrg
308578741aaSmrg#define MAX_DEF_PROMPT_W(w) (max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1)))
309145b7b3cSmrg
310578741aaSmrg#define GREETING(w)	((w)->login.secure_session  && !(w)->login.allow_access ?\
311145b7b3cSmrg				(w)->login.greeting : (w)->login.unsecure_greet)
312578741aaSmrg#define GREET_X(w)	((int)((w->core.width - \
313145b7b3cSmrg			     	STRING_WIDTH (greet, GREETING(w))) / 2))
314578741aaSmrg#define GREET_Y(w)	(GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
315629baa8cSmrg#define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
316145b7b3cSmrg			      STRING_WIDTH (greet, w->login.unsecure_greet)) \
317629baa8cSmrg			 + LOGO_W(w))
318629baa8cSmrg
319578741aaSmrg#define PROMPT_X(w)	(2 * PROMPT_X_INC(w))
320578741aaSmrg#define PROMPT_Y(w,n)	((GREET_Y(w) + GREET_Y_INC(w) +\
321145b7b3cSmrg			  F_ASCENT(greet) + Y_INC(w)) + \
322145b7b3cSmrg			 (n * PROMPT_SPACE_Y(w)))
323578741aaSmrg#define PROMPT_W(w)	(w->core.width - (2 * TEXT_X_INC(w)))
324578741aaSmrg#define PROMPT_H(w)	(3 * Y_INC(w) / 2)
325578741aaSmrg#define VALUE_X(w,n)	(PROMPT_X(w) + CUR_PROMPT_W(w,n))
326629baa8cSmrg#define CURSOR_W	5
327629baa8cSmrg#define MAX_VALUE_W(w,n) (PROMPT_W(w) - VALUE_X (w,n) - CURSOR_W - 1 - \
328629baa8cSmrg			  (w->login.inframeswidth * 2) - LOGO_W(w))
329578741aaSmrg#define PROMPT_SPACE_Y(w)	(10 * Y_INC(w) / 5)
330145b7b3cSmrg
331578741aaSmrg#define ERROR_X(w,m)	((int)(w->core.width - STRING_WIDTH (fail, m)) / 2)
332578741aaSmrg#define FAIL_X(w)	ERROR_X(w, w->login.fail)
333578741aaSmrg#define FAIL_Y(w)	(PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail))
334145b7b3cSmrg
335629baa8cSmrg#define ERROR_W(w,m)	(STRING_WIDTH (fail, m) + LOGO_W(w))
336145b7b3cSmrg
337578741aaSmrg#define FAIL_W(w)	max(ERROR_W(w, w->login.failMsg), \
338145b7b3cSmrg			    ERROR_W(w, w->login.passwdChangeMsg))
339145b7b3cSmrg
340578741aaSmrg#define PAD_X(w)	(2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w))))
341145b7b3cSmrg
342578741aaSmrg#define PAD_Y(w)	(max (max (Y_INC(w), GREET_Y_INC(w)),\
343145b7b3cSmrg			     FAIL_Y_INC(w)))
344578741aaSmrg
345145b7b3cSmrg#ifndef max
346145b7b3cSmrgstatic inline int max (int a, int b) { return a > b ? a : b; }
347145b7b3cSmrg#endif
348145b7b3cSmrg
349145b7b3cSmrgstatic void
350145b7b3cSmrgrealizeValue (LoginWidget w, int cursor, int promptNum, GC gc)
351145b7b3cSmrg{
3525ffd6003Smrg    loginPromptState state = PROMPT_STATE(w, promptNum);
353145b7b3cSmrg    char *text = VALUE_TEXT(w, promptNum);
354145b7b3cSmrg    int	x, y, height, width, curoff;
355145b7b3cSmrg
356145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
357145b7b3cSmrg
3585ffd6003Smrg    /* replace all password characters with asterisks */
3595ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
3605ffd6003Smrg    {
3615ffd6003Smrg	Cardinal length = strlen(text);
3625ffd6003Smrg	Cardinal i = 0;
3635ffd6003Smrg
3645ffd6003Smrg	text = XtMalloc(length + 1);
3655ffd6003Smrg
3665ffd6003Smrg	if (text == NULL)
3675ffd6003Smrg	{
3685ffd6003Smrg	    LogOutOfMem("realizeValue");
3695ffd6003Smrg	    return;
3705ffd6003Smrg	}
3715ffd6003Smrg
3725ffd6003Smrg	while (i < length)
3735ffd6003Smrg	{
374629baa8cSmrg	    text[i++] = w->login.echo_passwd_char[0];
3755ffd6003Smrg	}
3765ffd6003Smrg
3775ffd6003Smrg	text[i] = 0;
3785ffd6003Smrg    }
3795ffd6003Smrg
380145b7b3cSmrg    x = VALUE_X (w,promptNum);
381145b7b3cSmrg    y = PROMPT_Y (w,promptNum);
382145b7b3cSmrg
383629baa8cSmrg    height = PROMPT_H(w) - (w->login.inframeswidth * 2);
384629baa8cSmrg    width = MAX_VALUE_W(w,promptNum);
385145b7b3cSmrg
386145b7b3cSmrg    if (cursor > VALUE_SHOW_START(w, promptNum))
387145b7b3cSmrg	curoff = TEXT_WIDTH (text, text, cursor);
388145b7b3cSmrg    else
389145b7b3cSmrg	curoff = 0;
390145b7b3cSmrg
391145b7b3cSmrg
392145b7b3cSmrg    if (gc == w->login.bgGC) {
393145b7b3cSmrg	if (curoff < width) {
394145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
395145b7b3cSmrg			    x + curoff, y - TEXT_Y_INC(w),
396145b7b3cSmrg			    width - curoff, height);
397145b7b3cSmrg	}
3985ffd6003Smrg    } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) ||
3995ffd6003Smrg	       ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)))
4005ffd6003Smrg    {
401145b7b3cSmrg	int offset = max(cursor, VALUE_SHOW_START(w, promptNum));
402145b7b3cSmrg	int textlen = strlen (text + offset);
403578741aaSmrg
404629baa8cSmrg	if (TEXT_WIDTH (text, text + offset, textlen) > (width - curoff)) {
405145b7b3cSmrg	    /* Recalculate amount of text that can fit in field */
406145b7b3cSmrg	    offset = VALUE_SHOW_START(w, promptNum);
407145b7b3cSmrg	    textlen = strlen (text + offset);
408145b7b3cSmrg
409629baa8cSmrg	    while ((textlen > 0) &&
410629baa8cSmrg		   (TEXT_WIDTH (text, text + offset, textlen) > width))
411145b7b3cSmrg	    {
412145b7b3cSmrg		if (offset < PROMPT_CURSOR(w, promptNum)) {
413145b7b3cSmrg		    offset++;
414145b7b3cSmrg		}
415145b7b3cSmrg		textlen--;
416578741aaSmrg	    }
417145b7b3cSmrg
418145b7b3cSmrg	    VALUE_SHOW_START(w, promptNum) = offset;
419145b7b3cSmrg	    VALUE_SHOW_END(w, promptNum) = offset + textlen;
420145b7b3cSmrg
421145b7b3cSmrg	    /* Erase old string */
422145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC,
423145b7b3cSmrg			    x, y - TEXT_Y_INC(w), width, height);
424145b7b3cSmrg
425145b7b3cSmrg	    DRAW_STRING(text, x, y, text + offset, textlen);
426145b7b3cSmrg	} else {
427145b7b3cSmrg	    DRAW_STRING(text, x + curoff, y, text + offset, textlen);
428145b7b3cSmrg	}
429145b7b3cSmrg    }
4305ffd6003Smrg    /* free memory */
4315ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
4325ffd6003Smrg    {
4335ffd6003Smrg	XtFree(text);
4345ffd6003Smrg    }
435145b7b3cSmrg}
436145b7b3cSmrg
437145b7b3cSmrgstatic void
438145b7b3cSmrgEraseValue (LoginWidget w, int cursor, int promptNum)
439145b7b3cSmrg{
440145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.bgGC);
441145b7b3cSmrg}
442145b7b3cSmrg
443145b7b3cSmrgstatic void
444145b7b3cSmrgDrawValue (LoginWidget w, int cursor, int promptNum)
445145b7b3cSmrg{
446145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.textGC);
447145b7b3cSmrg#ifdef DANCING
448145b7b3cSmrg    /*as good a place as any Caolan begin*/
449145b7b3cSmrg    w->login.lastEventTime = time(NULL);
450145b7b3cSmrg    /*as good a place as any Caolan end*/
451145b7b3cSmrg#endif /* DANCING */
452145b7b3cSmrg}
453145b7b3cSmrg
454145b7b3cSmrgstatic void
455145b7b3cSmrgrealizeCursor (LoginWidget w, GC gc)
456145b7b3cSmrg{
457145b7b3cSmrg    int	x, y;
458145b7b3cSmrg    int height, width;
459145b7b3cSmrg
460145b7b3cSmrg    if (w->login.state != PROMPTING) {
461145b7b3cSmrg	return;
462145b7b3cSmrg    }
463578741aaSmrg
464145b7b3cSmrg    x = VALUE_X (w, w->login.activePrompt);
465145b7b3cSmrg    y = PROMPT_Y (w, w->login.activePrompt);
466145b7b3cSmrg    height = (F_ASCENT(text) + F_DESCENT(text));
467145b7b3cSmrg    width = 1;
468145b7b3cSmrg
469145b7b3cSmrg    switch (PROMPT_STATE(w, w->login.activePrompt)) {
470145b7b3cSmrg    case LOGIN_PROMPT_NOT_SHOWN:
471145b7b3cSmrg    case LOGIN_TEXT_INFO:
472145b7b3cSmrg	return;
473145b7b3cSmrg    case LOGIN_PROMPT_ECHO_ON:
474145b7b3cSmrg	if (CUR_PROMPT_CURSOR(w) > 0) {
475145b7b3cSmrg	    x += TEXT_WIDTH (text,
476145b7b3cSmrg			     VALUE_TEXT(w, w->login.activePrompt)
477145b7b3cSmrg			     + VALUE_SHOW_START(w, w->login.activePrompt),
478145b7b3cSmrg			     PROMPT_CURSOR(w, w->login.activePrompt)
479145b7b3cSmrg			     - VALUE_SHOW_START(w, w->login.activePrompt) );
480145b7b3cSmrg	}
481145b7b3cSmrg	break;
482145b7b3cSmrg    case LOGIN_PROMPT_ECHO_OFF:
4835ffd6003Smrg	if (w->login.echo_passwd == True) {
484629baa8cSmrg	    if (w->login.echo_passwd_char[0] != 0) {
485629baa8cSmrg		int len = PROMPT_CURSOR(w, w->login.activePrompt) -
486629baa8cSmrg		    VALUE_SHOW_START(w, w->login.activePrompt);
4875ffd6003Smrg
488629baa8cSmrg		x += len*TEXT_WIDTH(text, w->login.echo_passwd_char, 1);
489629baa8cSmrg	    } else {
490629baa8cSmrg		/* Move cursor one pixel per character to give some feedback
491629baa8cSmrg		   without giving away the password length */
492629baa8cSmrg		if (PROMPT_CURSOR(w, w->login.activePrompt) <
493629baa8cSmrg		    MAX_VALUE_W(w, w->login.activePrompt))
494629baa8cSmrg		    x += PROMPT_CURSOR(w, w->login.activePrompt);
495629baa8cSmrg		else
496629baa8cSmrg		    x += MAX_VALUE_W(w, w->login.activePrompt);
497629baa8cSmrg	    }
4985ffd6003Smrg	}
499145b7b3cSmrg	break;
500145b7b3cSmrg    }
501578741aaSmrg
502145b7b3cSmrg    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
503145b7b3cSmrg		    x, y+1 - F_ASCENT(text), width, height-1);
504145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
505629baa8cSmrg		    x-1 , y - F_ASCENT(text));
506145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
507629baa8cSmrg		    x+1 , y - F_ASCENT(text));
508145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
509629baa8cSmrg		    x-1 , y - F_ASCENT(text)+height);
510145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
511629baa8cSmrg		    x+1 , y - F_ASCENT(text)+height);
512145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
513629baa8cSmrg		    x-2 , y - F_ASCENT(text));
514145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
515629baa8cSmrg		    x+2 , y - F_ASCENT(text));
516145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
517629baa8cSmrg		    x-2 , y - F_ASCENT(text)+height);
518145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
519629baa8cSmrg		    x+2 , y - F_ASCENT(text)+height);
520145b7b3cSmrg
521578741aaSmrg    XFlush (XtDisplay(w));
522145b7b3cSmrg}
523145b7b3cSmrg
524145b7b3cSmrgstatic void
525145b7b3cSmrgEraseFail (LoginWidget w)
526145b7b3cSmrg{
527578741aaSmrg#ifdef USE_XFT
528145b7b3cSmrg    w->login.failUp = 0;
529145b7b3cSmrg    RedrawFail(w);
530578741aaSmrg#else
531145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
532145b7b3cSmrg			w->core.background_pixel);
533145b7b3cSmrg    RedrawFail(w);
534145b7b3cSmrg    w->login.failUp = 0;
535145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
536145b7b3cSmrg			TEXT_COLOR(fail));
537578741aaSmrg#endif
538145b7b3cSmrg}
539145b7b3cSmrg
540145b7b3cSmrgstatic void
541145b7b3cSmrgXorCursor (LoginWidget w)
542145b7b3cSmrg{
543145b7b3cSmrg    realizeCursor (w, w->login.xorGC);
544145b7b3cSmrg}
545145b7b3cSmrg
546145b7b3cSmrgstatic void
547145b7b3cSmrgRemoveFail (LoginWidget w)
548145b7b3cSmrg{
549145b7b3cSmrg    if (w->login.failUp)
550145b7b3cSmrg	EraseFail (w);
551145b7b3cSmrg}
552145b7b3cSmrg
553145b7b3cSmrgstatic void
554145b7b3cSmrgEraseCursor (LoginWidget w)
555145b7b3cSmrg{
556145b7b3cSmrg    realizeCursor (w, w->login.bgGC);
557145b7b3cSmrg}
558145b7b3cSmrg
559145b7b3cSmrg/*ARGSUSED*/
560145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id)
561145b7b3cSmrg{
562145b7b3cSmrg    LoginWidget	w = (LoginWidget)client_data;
563145b7b3cSmrg
564145b7b3cSmrg    Debug ("failTimeout\n");
565145b7b3cSmrg    w->login.interval_id = 0;
566145b7b3cSmrg    EraseFail (w);
567145b7b3cSmrg}
568145b7b3cSmrg
569145b7b3cSmrg_X_INTERNAL
570145b7b3cSmrgvoid
571145b7b3cSmrgDrawFail (Widget ctx)
572145b7b3cSmrg{
573145b7b3cSmrg    LoginWidget	w;
574145b7b3cSmrg
575145b7b3cSmrg    w = (LoginWidget) ctx;
576145b7b3cSmrg    XorCursor (w);
577145b7b3cSmrg    ResetLogin (w);
578145b7b3cSmrg    XorCursor (w);
579145b7b3cSmrg    ErrorMessage(ctx, w->login.failMsg, True);
580145b7b3cSmrg}
581145b7b3cSmrg
582145b7b3cSmrgstatic void
583145b7b3cSmrgRedrawFail (LoginWidget w)
584145b7b3cSmrg{
585145b7b3cSmrg    int x = FAIL_X(w);
586145b7b3cSmrg    int y = FAIL_Y(w);
587145b7b3cSmrg    int maxw = w->core.width - PAD_X(w);
588145b7b3cSmrg
589578741aaSmrg#ifndef USE_XFT
590145b7b3cSmrg    if (w->login.failUp)
591578741aaSmrg#endif
592145b7b3cSmrg    {
593145b7b3cSmrg	Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp);
594145b7b3cSmrg	if (ERROR_W(w, w->login.fail) > maxw) {
595145b7b3cSmrg	    /* Too long to fit on one line, break into multiple lines */
596145b7b3cSmrg	    char *tempCopy = strdup(w->login.fail);
597145b7b3cSmrg	    if (tempCopy != NULL) {
598145b7b3cSmrg		char *start, *next;
599578741aaSmrg		char lastspace = ' ';
600145b7b3cSmrg
601145b7b3cSmrg		y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w));
602578741aaSmrg
603145b7b3cSmrg		for (start = next = tempCopy; start != NULL ; start = next) {
604145b7b3cSmrg		    /* search for longest string broken by whitespace that
605145b7b3cSmrg		       will fit on a single line */
606145b7b3cSmrg		    do {
607145b7b3cSmrg			if (next != start) {
608145b7b3cSmrg			    *next = lastspace;
609145b7b3cSmrg			}
610145b7b3cSmrg			for (next = next + 1;
611145b7b3cSmrg			     (*next != '\0') && !isspace(*next) ; next++)
612145b7b3cSmrg			{
613145b7b3cSmrg			    /* this loop intentionally left blank */
614145b7b3cSmrg			}
615145b7b3cSmrg			if (*next != '\0') {
616145b7b3cSmrg			    lastspace = *next;
617145b7b3cSmrg			    *next = '\0';
618145b7b3cSmrg			} else {
619145b7b3cSmrg			    next = NULL;
620145b7b3cSmrg			}
621145b7b3cSmrg		    } while ((next != NULL) && ERROR_W(w, start) < maxw);
622578741aaSmrg
623145b7b3cSmrg		    x = ERROR_X(w, start);
624145b7b3cSmrg#ifdef USE_XFT
625145b7b3cSmrg		    if (w->login.failUp == 0) {
6265ffd6003Smrg			XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
627145b7b3cSmrg				   ERROR_W(w, start), FAIL_Y_INC(w), False);
628145b7b3cSmrg		    } else
629578741aaSmrg#endif
630145b7b3cSmrg			DRAW_STRING (fail, x, y, start, strlen(start));
631145b7b3cSmrg
632145b7b3cSmrg		    if (next != NULL) {
633145b7b3cSmrg			next++;
634145b7b3cSmrg			y += FAIL_Y_INC(w);
635145b7b3cSmrg		    }
636145b7b3cSmrg		}
637145b7b3cSmrg		free(tempCopy);
638145b7b3cSmrg		return;
639145b7b3cSmrg	    }
640145b7b3cSmrg	    /* if strdup failed, fall through to draw all at once, even
641145b7b3cSmrg	       though we know it can't all fit */
642145b7b3cSmrg	    LogOutOfMem("RedrawFail");
643145b7b3cSmrg	}
644145b7b3cSmrg
645145b7b3cSmrg#ifdef USE_XFT
646145b7b3cSmrg	if (w->login.failUp == 0) {
6475ffd6003Smrg	    XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
648145b7b3cSmrg		       ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False);
649145b7b3cSmrg	} else
650578741aaSmrg#endif
651145b7b3cSmrg	    DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail));
652145b7b3cSmrg    }
653145b7b3cSmrg}
654145b7b3cSmrg
655145b7b3cSmrg_X_INTERNAL
656145b7b3cSmrgvoid
657145b7b3cSmrgErrorMessage(Widget ctx, const char *message, Bool timeout)
658145b7b3cSmrg{
659145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
660145b7b3cSmrg
661145b7b3cSmrg/*  Debug("ErrorMessage: %s\n", message);   */
662145b7b3cSmrg    if (w->login.interval_id != 0) {
663145b7b3cSmrg	XtRemoveTimeOut(w->login.interval_id);
664145b7b3cSmrg	w->login.interval_id = 0;
665145b7b3cSmrg    }
666145b7b3cSmrg    RemoveFail(w);
667145b7b3cSmrg    if (w->login.fail != w->login.failMsg)
668145b7b3cSmrg	free(w->login.fail);
669145b7b3cSmrg    w->login.fail = strdup(message);
670145b7b3cSmrg    if (w->login.fail == NULL)
671145b7b3cSmrg	w->login.fail = (char *) w->login.failMsg;
672145b7b3cSmrg    w->login.failUp = 1;
673145b7b3cSmrg    RedrawFail (w);
674145b7b3cSmrg    if (timeout && (w->login.failTimeout > 0)) {
675145b7b3cSmrg	Debug ("failTimeout: %d\n", w->login.failTimeout);
676145b7b3cSmrg	w->login.interval_id =
677145b7b3cSmrg	    XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w),
678145b7b3cSmrg			    w->login.failTimeout * 1000,
679145b7b3cSmrg			    failTimeout, (XtPointer) w);
680145b7b3cSmrg    }
681145b7b3cSmrg}
682145b7b3cSmrg
683145b7b3cSmrg_X_INTERNAL
684145b7b3cSmrgvoid
685145b7b3cSmrgShowChangePasswdMessage(Widget ctx)
686145b7b3cSmrg{
687145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
688145b7b3cSmrg
689145b7b3cSmrg    ErrorMessage(ctx, w->login.passwdChangeMsg, False);
690145b7b3cSmrg}
691145b7b3cSmrg
692145b7b3cSmrgstatic void
693145b7b3cSmrgdraw_it (LoginWidget w)
694145b7b3cSmrg{
695145b7b3cSmrg    int p;
696145b7b3cSmrg    int i;
697145b7b3cSmrg    int gr_line_x, gr_line_y, gr_line_w;
698145b7b3cSmrg
699145b7b3cSmrg    EraseCursor (w);
700145b7b3cSmrg
7015ffd6003Smrg    /* draw window borders */
702145b7b3cSmrg    for(i=1;i<=(w->login.outframewidth);i++)
703145b7b3cSmrg    {
704145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
705629baa8cSmrg		i-1,i-1,w->core.width-i,i-1);
706145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
707629baa8cSmrg		i-1,i-1,i-1,w->core.height-i);
708145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
709629baa8cSmrg		w->core.width-i,i-1,w->core.width-i,w->core.height-i);
710145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
711629baa8cSmrg		i-1,w->core.height-i,w->core.width-i,w->core.height-i);
712145b7b3cSmrg    }
713578741aaSmrg
714145b7b3cSmrg    /* make separator line */
715145b7b3cSmrg    gr_line_x = w->login.outframewidth;
716145b7b3cSmrg    gr_line_y = GREET_Y(w) + GREET_Y_INC(w);
717145b7b3cSmrg    gr_line_w = w->core.width - 2*(w->login.outframewidth);
718145b7b3cSmrg
719145b7b3cSmrg#ifdef XPM
720145b7b3cSmrg    gr_line_x += w->login.logoPadding;
721145b7b3cSmrg    gr_line_w -= w->login.logoWidth + (3 * (w->login.logoPadding));
722145b7b3cSmrg#endif /* XPM */
723145b7b3cSmrg
724145b7b3cSmrg    for(i=1;i<=(w->login.sepwidth);i++)
725145b7b3cSmrg    {
726145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
727145b7b3cSmrg        gr_line_x,           gr_line_y + i-1,
728145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + i-1);
729145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
730145b7b3cSmrg        gr_line_x,           gr_line_y + 2*(w->login.inframeswidth) -i,
731145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + 2*(w->login.inframeswidth) -i);
732145b7b3cSmrg    }
733145b7b3cSmrg
734145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++)
735145b7b3cSmrg    {
736145b7b3cSmrg	int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth - 3;
737145b7b3cSmrg	int in_frame_y
738145b7b3cSmrg	    = PROMPT_Y(w,p) - w->login.inframeswidth - 1 - TEXT_Y_INC(w);
739578741aaSmrg
740629baa8cSmrg	int in_width = PROMPT_W(w) - VALUE_X(w,p) - LOGO_W(w);
741145b7b3cSmrg	int in_height = PROMPT_H(w) + w->login.inframeswidth + 2;
742578741aaSmrg
743145b7b3cSmrg	GC topLeftGC, botRightGC;
744145b7b3cSmrg
745145b7b3cSmrg	if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) ||
746145b7b3cSmrg	    (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) {
747145b7b3cSmrg	    topLeftGC = w->login.shdGC;
748145b7b3cSmrg	    botRightGC = w->login.hiGC;
749145b7b3cSmrg	} else {
750145b7b3cSmrg	    topLeftGC = botRightGC = w->login.bgGC;
751145b7b3cSmrg	}
752145b7b3cSmrg
7535ffd6003Smrg	/* draw borders of editboxes */
754145b7b3cSmrg	for (i=1; i<=(w->login.inframeswidth); i++)
755145b7b3cSmrg	{
756145b7b3cSmrg	    /* Make top/left sides */
757145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
758145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
759578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1);
760145b7b3cSmrg
761145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
762145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
763578741aaSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i);
764145b7b3cSmrg
765145b7b3cSmrg	    /* Make bottom/right sides */
766145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
767145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1,
768578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
769145b7b3cSmrg
770145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
771145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i,
772145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
773145b7b3cSmrg	}
774145b7b3cSmrg    }
775145b7b3cSmrg
776145b7b3cSmrg    if (GREETING(w)[0]) {
777145b7b3cSmrg	int gx = GREET_X(w);
778145b7b3cSmrg
779145b7b3cSmrg#ifdef XPM
780145b7b3cSmrg	gx -= ((w->login.logoWidth/2) + w->login.logoPadding);
781578741aaSmrg#endif
782145b7b3cSmrg	DRAW_STRING (greet, gx, GREET_Y(w), GREETING(w), strlen (GREETING(w)));
783145b7b3cSmrg    }
784145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++) {
785145b7b3cSmrg	if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) {
786145b7b3cSmrg	    DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p),
787145b7b3cSmrg			 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p)));
788145b7b3cSmrg	    DrawValue (w, 0, p);
789145b7b3cSmrg	}
790145b7b3cSmrg    }
791145b7b3cSmrg    RedrawFail (w);
792145b7b3cSmrg    XorCursor (w);
7935ffd6003Smrg    XSetInputFocus (XtDisplay (w), XtWindow (w),
7945ffd6003Smrg		    RevertToPointerRoot, CurrentTime);
795145b7b3cSmrg}
796145b7b3cSmrg
797145b7b3cSmrg/* Returns 0 on success, -1 on failure */
798145b7b3cSmrg_X_INTERNAL
799145b7b3cSmrgint
800145b7b3cSmrgSetPrompt (Widget ctx, int promptNum, const char *message,
801145b7b3cSmrg	   loginPromptState state, Boolean minimumTime)
802145b7b3cSmrg{
803145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
804145b7b3cSmrg    char *prompt;
805145b7b3cSmrg    int messageLen, e;
806145b7b3cSmrg    const char *stateNames[4] = {
807145b7b3cSmrg	"LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON",
808145b7b3cSmrg	"LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" };
809145b7b3cSmrg    loginPromptState priorState;
810578741aaSmrg
811145b7b3cSmrg    Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum,
812145b7b3cSmrg	  message ? message : "<NULL>", stateNames[state], state);
813145b7b3cSmrg
814145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
815578741aaSmrg
816145b7b3cSmrg    if (PROMPT_TEXT(w, promptNum) != NULL) {
817145b7b3cSmrg	XtFree(PROMPT_TEXT(w, promptNum));
818145b7b3cSmrg	PROMPT_TEXT(w, promptNum) = NULL;
819145b7b3cSmrg    }
820145b7b3cSmrg
821145b7b3cSmrg    priorState = PROMPT_STATE(w, promptNum);
822145b7b3cSmrg    PROMPT_STATE(w, promptNum) = state;
823145b7b3cSmrg
824145b7b3cSmrg    if (state == LOGIN_PROMPT_NOT_SHOWN) {
825145b7b3cSmrg	return 0;
826145b7b3cSmrg    }
827145b7b3cSmrg
828145b7b3cSmrg    if (message == NULL) {
829145b7b3cSmrg	message = DEF_PROMPT_TEXT(w, promptNum);
830145b7b3cSmrg    }
831145b7b3cSmrg
832145b7b3cSmrg    messageLen = strlen(message);
833578741aaSmrg
834145b7b3cSmrg    prompt = XtMalloc(messageLen + 3);
835145b7b3cSmrg    if (prompt == NULL) {
836145b7b3cSmrg	LogOutOfMem ("SetPrompt");
837145b7b3cSmrg	return -1;
838145b7b3cSmrg    }
839578741aaSmrg
840145b7b3cSmrg    strncpy(prompt, message, messageLen);
841578741aaSmrg
842145b7b3cSmrg    /* Make sure text prompts have at least two spaces at end */
843145b7b3cSmrg    e = messageLen;
844578741aaSmrg
845145b7b3cSmrg    if (!isspace(message[messageLen - 2])) {
846145b7b3cSmrg	prompt[e] = ' ';
847145b7b3cSmrg	e++;
848145b7b3cSmrg    }
849145b7b3cSmrg    if (!isspace(message[messageLen - 1])) {
850145b7b3cSmrg	prompt[e] = ' ';
851145b7b3cSmrg	e++;
852145b7b3cSmrg    }
853145b7b3cSmrg    prompt[e] = '\0';
854145b7b3cSmrg
855145b7b3cSmrg    PROMPT_TEXT(w, promptNum) = prompt;
856145b7b3cSmrg
857145b7b3cSmrg    if (w->login.state == INITIALIZING) {
858145b7b3cSmrg	return 0;
859145b7b3cSmrg    }
860578741aaSmrg
861145b7b3cSmrg    if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) {
862145b7b3cSmrg	time_t now = time(NULL);
863145b7b3cSmrg	int timeleft = w->login.msgTimeout - now;
864578741aaSmrg
865145b7b3cSmrg	if (timeleft > 0) {
866145b7b3cSmrg	    sleep(timeleft);
867145b7b3cSmrg	}
868145b7b3cSmrg	w->login.msgTimeout = 0;
869145b7b3cSmrg    }
870145b7b3cSmrg
871145b7b3cSmrg    if (state == LOGIN_TEXT_INFO) {
872145b7b3cSmrg	if (minimumTime) {
873145b7b3cSmrg	    time_t now = time(NULL);
874145b7b3cSmrg	    w->login.msgTimeout = now + w->login.failTimeout;
875145b7b3cSmrg	}
876145b7b3cSmrg	w->login.state = SHOW_MESSAGE;
877145b7b3cSmrg    } else {
878145b7b3cSmrg	w->login.activePrompt = promptNum;
879145b7b3cSmrg	w->login.state = PROMPTING;
880145b7b3cSmrg    }
881578741aaSmrg
882145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
883145b7b3cSmrg    XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE);
884145b7b3cSmrg    draw_it(w);
885145b7b3cSmrg    return 0;
886145b7b3cSmrg}
887145b7b3cSmrg
888145b7b3cSmrg_X_INTERNAL
889145b7b3cSmrgconst char *
890145b7b3cSmrgGetPrompt(Widget ctx, int promptNum)
891145b7b3cSmrg{
892145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
893145b7b3cSmrg
894145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
895578741aaSmrg
896145b7b3cSmrg    return CUR_PROMPT_TEXT(w,promptNum);
897145b7b3cSmrg}
898145b7b3cSmrg
899145b7b3cSmrg_X_INTERNAL
900145b7b3cSmrgint
901145b7b3cSmrgSetValue(Widget ctx, int promptNum, char *value)
902145b7b3cSmrg{
903145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
904145b7b3cSmrg
905145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
906578741aaSmrg
907145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
908145b7b3cSmrg	return -1;
909145b7b3cSmrg
910145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
911578741aaSmrg
912145b7b3cSmrg    if (VALUE_TEXT(w, promptNum) == NULL)
913145b7b3cSmrg	return -1;
914145b7b3cSmrg
915145b7b3cSmrg    if (value == NULL) {
916145b7b3cSmrg	bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum));
917145b7b3cSmrg    } else {
918145b7b3cSmrg	strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum));
919145b7b3cSmrg	VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0';
920145b7b3cSmrg    }
921145b7b3cSmrg
922145b7b3cSmrg    VALUE_SHOW_START(w, promptNum) = 0;
923145b7b3cSmrg    VALUE_SHOW_END(w, promptNum) = 0;
924145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
925578741aaSmrg
926145b7b3cSmrg    return 0;
927145b7b3cSmrg}
928145b7b3cSmrg
929145b7b3cSmrg_X_INTERNAL
930145b7b3cSmrgconst char *
931145b7b3cSmrgGetValue(Widget ctx, int promptNum)
932145b7b3cSmrg{
933145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
934145b7b3cSmrg
935145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
936578741aaSmrg
937145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
938145b7b3cSmrg	return NULL;
939145b7b3cSmrg
940145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
941145b7b3cSmrg
942145b7b3cSmrg    return VALUE_TEXT(w, promptNum);
943145b7b3cSmrg}
944145b7b3cSmrg
945145b7b3cSmrg
946145b7b3cSmrgstatic void
947145b7b3cSmrgrealizeDeleteChar (LoginWidget ctx)
948145b7b3cSmrg{
949145b7b3cSmrg    if (ctx->login.state == PROMPTING) {
950145b7b3cSmrg	int promptNum = ctx->login.activePrompt;
951145b7b3cSmrg	int redrawFrom = PROMPT_CURSOR(ctx, promptNum);
952578741aaSmrg
953145b7b3cSmrg	if (PROMPT_CURSOR(ctx,promptNum) <  (int)strlen(VALUE_TEXT(ctx,promptNum))) {
954145b7b3cSmrg	    if (redrawFrom < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
955145b7b3cSmrg		redrawFrom = 0;
956145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
957145b7b3cSmrg		VALUE_SHOW_START(ctx, ctx->login.activePrompt)
958145b7b3cSmrg		    = PROMPT_CURSOR(ctx,promptNum);
959145b7b3cSmrg	    } else {
960145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
961145b7b3cSmrg	    }
962145b7b3cSmrg	    strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
963145b7b3cSmrg		   VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1);
964145b7b3cSmrg	    DrawValue (ctx, redrawFrom, promptNum);
965145b7b3cSmrg	}
966145b7b3cSmrg    }
967145b7b3cSmrg}
968145b7b3cSmrg
969145b7b3cSmrg/*ARGSUSED*/
970145b7b3cSmrgstatic void
971145b7b3cSmrgDeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
972145b7b3cSmrg{
973145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
974145b7b3cSmrg
975145b7b3cSmrg    RemoveFail (ctx);
976145b7b3cSmrg
977145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
978145b7b3cSmrg	return;
979145b7b3cSmrg    }
980145b7b3cSmrg
981145b7b3cSmrg    XorCursor (ctx);
982145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0) {
983145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
984145b7b3cSmrg	realizeDeleteChar(ctx);
985145b7b3cSmrg    }
986578741aaSmrg    XorCursor (ctx);
987145b7b3cSmrg}
988145b7b3cSmrg
989145b7b3cSmrg/*ARGSUSED*/
990145b7b3cSmrgstatic void
991145b7b3cSmrgDeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
992145b7b3cSmrg{
993145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
994145b7b3cSmrg
995145b7b3cSmrg    RemoveFail (ctx);
996145b7b3cSmrg
997145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
998145b7b3cSmrg	return;
999145b7b3cSmrg    }
1000145b7b3cSmrg
1001145b7b3cSmrg    XorCursor (ctx);
1002145b7b3cSmrg    realizeDeleteChar(ctx);
1003578741aaSmrg    XorCursor (ctx);
1004145b7b3cSmrg}
1005145b7b3cSmrg
1006145b7b3cSmrg/*ARGSUSED*/
1007145b7b3cSmrgstatic void
1008145b7b3cSmrgMoveBackwardChar (
1009145b7b3cSmrg    Widget	ctxw,
1010145b7b3cSmrg    XEvent	*event,
1011145b7b3cSmrg    String	*params,
1012145b7b3cSmrg    Cardinal	*num_params)
1013145b7b3cSmrg{
1014145b7b3cSmrg    LoginWidget	ctx = (LoginWidget)ctxw;
1015145b7b3cSmrg
1016145b7b3cSmrg    RemoveFail (ctx);
1017145b7b3cSmrg
1018145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1019145b7b3cSmrg	return;
1020145b7b3cSmrg    }
1021145b7b3cSmrg
1022145b7b3cSmrg    XorCursor (ctx);
1023145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0)
1024145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
1025145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
1026145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1027145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt)
1028145b7b3cSmrg	    = CUR_PROMPT_CURSOR(ctx);
1029145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1030145b7b3cSmrg    }
1031145b7b3cSmrg    XorCursor (ctx);
1032145b7b3cSmrg}
1033145b7b3cSmrg
1034145b7b3cSmrg/*ARGSUSED*/
1035145b7b3cSmrgstatic void
1036145b7b3cSmrgMoveForwardChar (
1037145b7b3cSmrg    Widget	ctxw,
1038145b7b3cSmrg    XEvent	*event,
1039145b7b3cSmrg    String	*params,
1040145b7b3cSmrg    Cardinal	*num_params)
1041145b7b3cSmrg{
1042145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1043145b7b3cSmrg
1044145b7b3cSmrg    RemoveFail (ctx);
1045145b7b3cSmrg
1046145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1047145b7b3cSmrg	return;
1048145b7b3cSmrg    }
1049145b7b3cSmrg
1050145b7b3cSmrg    XorCursor (ctx);
1051145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) <
1052145b7b3cSmrg	(int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) {
1053145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) += 1;
1054145b7b3cSmrg	if (VALUE_SHOW_END(ctx, ctx->login.activePrompt)
1055145b7b3cSmrg	    < CUR_PROMPT_CURSOR(ctx)) {
1056145b7b3cSmrg	    EraseValue(ctx, 0, ctx->login.activePrompt);
1057145b7b3cSmrg	    DrawValue(ctx, 0, ctx->login.activePrompt);
1058145b7b3cSmrg	}
1059145b7b3cSmrg    }
1060145b7b3cSmrg    XorCursor (ctx);
1061145b7b3cSmrg}
1062145b7b3cSmrg
1063145b7b3cSmrg/*ARGSUSED*/
1064145b7b3cSmrgstatic void
1065145b7b3cSmrgMoveToBegining (
1066145b7b3cSmrg    Widget	ctxw,
1067145b7b3cSmrg    XEvent	*event,
1068145b7b3cSmrg    String	*params,
1069145b7b3cSmrg    Cardinal	*num_params)
1070145b7b3cSmrg{
1071145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1072145b7b3cSmrg
1073145b7b3cSmrg    RemoveFail (ctx);
1074145b7b3cSmrg
1075145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1076145b7b3cSmrg	return;
1077145b7b3cSmrg    }
1078145b7b3cSmrg
1079145b7b3cSmrg    XorCursor (ctx);
1080145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = 0;
1081145b7b3cSmrg    if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) {
1082145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1083145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0;
1084145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1085145b7b3cSmrg    }
1086145b7b3cSmrg    XorCursor (ctx);
1087145b7b3cSmrg}
1088145b7b3cSmrg
1089145b7b3cSmrg/*ARGSUSED*/
1090145b7b3cSmrgstatic void
1091145b7b3cSmrgMoveToEnd (
1092145b7b3cSmrg    Widget	ctxw,
1093145b7b3cSmrg    XEvent	*event,
1094145b7b3cSmrg    String	*params,
1095145b7b3cSmrg    Cardinal	*num_params)
1096145b7b3cSmrg{
1097145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1098145b7b3cSmrg
1099145b7b3cSmrg    RemoveFail (ctx);
1100145b7b3cSmrg
1101145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1102145b7b3cSmrg	return;
1103145b7b3cSmrg    }
1104145b7b3cSmrg
1105145b7b3cSmrg    XorCursor (ctx);
1106145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt));
1107145b7b3cSmrg    if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) {
1108145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1109145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1110145b7b3cSmrg    }
1111145b7b3cSmrg    XorCursor (ctx);
1112145b7b3cSmrg}
1113145b7b3cSmrg
1114145b7b3cSmrg/*ARGSUSED*/
1115145b7b3cSmrgstatic void
1116145b7b3cSmrgEraseToEndOfLine (
1117145b7b3cSmrg    Widget	ctxw,
1118145b7b3cSmrg    XEvent	*event,
1119145b7b3cSmrg    String	*params,
1120145b7b3cSmrg    Cardinal	*num_params)
1121145b7b3cSmrg{
1122145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1123145b7b3cSmrg
1124145b7b3cSmrg    RemoveFail (ctx);
1125145b7b3cSmrg
1126145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1127145b7b3cSmrg	return;
1128145b7b3cSmrg    }
1129145b7b3cSmrg
1130145b7b3cSmrg    XorCursor (ctx);
1131145b7b3cSmrg    EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt);
1132145b7b3cSmrg    bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) +
1133145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx),
1134145b7b3cSmrg	  VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) -
1135145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx));
1136145b7b3cSmrg    XorCursor (ctx);
1137145b7b3cSmrg}
1138145b7b3cSmrg
1139145b7b3cSmrg/*ARGSUSED*/
1140145b7b3cSmrgstatic void
1141145b7b3cSmrgEraseLine (
1142145b7b3cSmrg    Widget	ctxw,
1143145b7b3cSmrg    XEvent	*event,
1144145b7b3cSmrg    String	*params,
1145145b7b3cSmrg    Cardinal	*num_params)
1146145b7b3cSmrg{
1147145b7b3cSmrg    MoveToBegining (ctxw, event, params, num_params);
1148145b7b3cSmrg    EraseToEndOfLine (ctxw, event, params, num_params);
1149145b7b3cSmrg}
1150145b7b3cSmrg
1151145b7b3cSmrg/*ARGSUSED*/
1152145b7b3cSmrgstatic void
1153145b7b3cSmrgFinishField (
1154145b7b3cSmrg    Widget	ctxw,
1155145b7b3cSmrg    XEvent	*event,
1156145b7b3cSmrg    String	*params,
1157145b7b3cSmrg    Cardinal	*num_params)
1158145b7b3cSmrg{
1159145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1160145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1161145b7b3cSmrg    int nextPrompt;
1162145b7b3cSmrg
1163145b7b3cSmrg    RemoveFail (ctx);
1164145b7b3cSmrg
1165145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1166145b7b3cSmrg	return;
1167145b7b3cSmrg    }
1168145b7b3cSmrg
1169145b7b3cSmrg    XorCursor (ctx);
1170145b7b3cSmrg
1171145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) {
1172145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1173145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1174145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1175145b7b3cSmrg	    break;
1176145b7b3cSmrg	}
1177145b7b3cSmrg    }
1178145b7b3cSmrg    if (nextPrompt > LAST_PROMPT) {
1179145b7b3cSmrg	ctx->login.state = DONE;
1180145b7b3cSmrg	(*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
1181145b7b3cSmrg	Debug("FinishField #%d: now DONE\n", promptNum);
1182145b7b3cSmrg    } else {
1183145b7b3cSmrg	Debug("FinishField #%d: %d next\n", promptNum, nextPrompt);
1184145b7b3cSmrg    }
1185145b7b3cSmrg
1186145b7b3cSmrg    XorCursor (ctx);
1187145b7b3cSmrg}
1188145b7b3cSmrg
1189145b7b3cSmrg/*ARGSUSED*/
1190145b7b3cSmrgstatic void
1191145b7b3cSmrgTabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1192145b7b3cSmrg{
1193145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1194145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1195145b7b3cSmrg    int nextPrompt;
1196145b7b3cSmrg
1197145b7b3cSmrg    RemoveFail (ctx);
1198145b7b3cSmrg
1199145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1200145b7b3cSmrg	return;
1201145b7b3cSmrg    }
1202145b7b3cSmrg
1203145b7b3cSmrg    XorCursor (ctx);
1204145b7b3cSmrg
1205145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) {
1206145b7b3cSmrg	if (nextPrompt > LAST_PROMPT) {
1207145b7b3cSmrg	    nextPrompt = 0;
1208145b7b3cSmrg	}
1209578741aaSmrg
1210145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1211145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1212145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1213145b7b3cSmrg	    break;
1214145b7b3cSmrg	}
1215145b7b3cSmrg    }
1216145b7b3cSmrg    XorCursor (ctx);
1217145b7b3cSmrg}
1218145b7b3cSmrg
1219145b7b3cSmrg/*ARGSUSED*/
1220145b7b3cSmrgstatic void
1221145b7b3cSmrgAllowAccess (
1222145b7b3cSmrg    Widget	ctxw,
1223145b7b3cSmrg    XEvent	*event,
1224145b7b3cSmrg    String	*params,
1225145b7b3cSmrg    Cardinal	*num_params)
1226145b7b3cSmrg{
1227145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1228145b7b3cSmrg    Arg	arglist[1];
1229145b7b3cSmrg    Boolean allow;
1230145b7b3cSmrg
1231145b7b3cSmrg    RemoveFail (ctx);
1232145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
1233145b7b3cSmrg    XtGetValues ((Widget) ctx, arglist, 1);
1234145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, !allow);
1235145b7b3cSmrg    XtSetValues ((Widget) ctx, arglist, 1);
1236145b7b3cSmrg}
1237145b7b3cSmrg
1238145b7b3cSmrg/*ARGSUSED*/
1239145b7b3cSmrgstatic void
1240145b7b3cSmrgSetSessionArgument (
1241145b7b3cSmrg    Widget	ctxw,
1242145b7b3cSmrg    XEvent	*event,
1243145b7b3cSmrg    String	*params,
1244145b7b3cSmrg    Cardinal	*num_params)
1245145b7b3cSmrg{
1246145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1247145b7b3cSmrg
1248145b7b3cSmrg    RemoveFail (ctx);
1249145b7b3cSmrg    if (ctx->login.sessionArg)
1250145b7b3cSmrg	XtFree (ctx->login.sessionArg);
1251145b7b3cSmrg    ctx->login.sessionArg = NULL;
1252145b7b3cSmrg    if (*num_params > 0) {
1253145b7b3cSmrg	ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
1254145b7b3cSmrg	if (ctx->login.sessionArg)
1255145b7b3cSmrg	    strcpy (ctx->login.sessionArg, params[0]);
1256145b7b3cSmrg	else
1257145b7b3cSmrg	    LogOutOfMem ("set session argument");
1258145b7b3cSmrg    }
1259145b7b3cSmrg}
1260145b7b3cSmrg
1261145b7b3cSmrg/*ARGSUSED*/
1262145b7b3cSmrgstatic void
1263145b7b3cSmrgRestartSession (
1264145b7b3cSmrg    Widget	ctxw,
1265145b7b3cSmrg    XEvent	*event,
1266145b7b3cSmrg    String	*params,
1267145b7b3cSmrg    Cardinal	*num_params)
1268145b7b3cSmrg{
1269145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1270145b7b3cSmrg
1271145b7b3cSmrg    XorCursor (ctx);
1272145b7b3cSmrg    RemoveFail (ctx);
1273145b7b3cSmrg    ctx->login.state = DONE;
1274145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
1275145b7b3cSmrg    XorCursor (ctx);
1276145b7b3cSmrg}
1277145b7b3cSmrg
1278145b7b3cSmrg/*ARGSUSED*/
1279145b7b3cSmrgstatic void
1280145b7b3cSmrgAbortSession (
1281145b7b3cSmrg    Widget	ctxw,
1282145b7b3cSmrg    XEvent	*event,
1283145b7b3cSmrg    String	*params,
1284145b7b3cSmrg    Cardinal	*num_params)
1285145b7b3cSmrg{
1286145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1287145b7b3cSmrg
1288145b7b3cSmrg    XorCursor (ctx);
1289145b7b3cSmrg    RemoveFail (ctx);
1290145b7b3cSmrg    ctx->login.state = DONE;
1291145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
1292145b7b3cSmrg    XorCursor (ctx);
1293145b7b3cSmrg}
1294145b7b3cSmrg
1295145b7b3cSmrg/*ARGSUSED*/
1296145b7b3cSmrgstatic void
1297145b7b3cSmrgAbortDisplay (
1298145b7b3cSmrg    Widget	ctxw,
1299145b7b3cSmrg    XEvent	*event,
1300145b7b3cSmrg    String	*params,
1301145b7b3cSmrg    Cardinal	*num_params)
1302145b7b3cSmrg{
1303145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1304145b7b3cSmrg
1305145b7b3cSmrg    XorCursor (ctx);
1306145b7b3cSmrg    RemoveFail (ctx);
1307145b7b3cSmrg    ctx->login.state = DONE;
1308145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
1309145b7b3cSmrg    XorCursor (ctx);
1310145b7b3cSmrg}
1311145b7b3cSmrg
1312145b7b3cSmrgstatic void
1313145b7b3cSmrgResetLogin (LoginWidget w)
1314145b7b3cSmrg{
1315145b7b3cSmrg    int i;
1316145b7b3cSmrg
1317145b7b3cSmrg    for (i = 0; i < NUM_PROMPTS ; i++) {
1318145b7b3cSmrg	EraseValue(w, 0, i);
1319145b7b3cSmrg	bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i));
1320145b7b3cSmrg	VALUE_SHOW_START(w, i) = 0;
1321145b7b3cSmrg	PROMPT_CURSOR(w, i) = 0;
1322145b7b3cSmrg    }
1323145b7b3cSmrg    w->login.state = PROMPTING;
1324145b7b3cSmrg    w->login.activePrompt = 0;
1325145b7b3cSmrg}
1326145b7b3cSmrg
1327145b7b3cSmrgstatic void
1328145b7b3cSmrgInitI18N(Widget ctxw)
1329145b7b3cSmrg{
1330145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1331145b7b3cSmrg    XIM         xim = (XIM) NULL;
1332145b7b3cSmrg    char *p;
1333145b7b3cSmrg
1334145b7b3cSmrg    ctx->login.xic = (XIC) NULL;
1335145b7b3cSmrg
1336145b7b3cSmrg    if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
1337145b7b3cSmrg	xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL);
1338145b7b3cSmrg
1339145b7b3cSmrg    if (!xim) {
1340145b7b3cSmrg	LogError("Failed to open input method\n");
1341145b7b3cSmrg	return;
1342145b7b3cSmrg    }
1343145b7b3cSmrg
1344145b7b3cSmrg    ctx->login.xic = XCreateIC(xim,
1345145b7b3cSmrg	XNInputStyle, (XIMPreeditNothing|XIMStatusNothing),
1346145b7b3cSmrg	XNClientWindow, ctx->core.window,
1347145b7b3cSmrg	XNFocusWindow,  ctx->core.window, NULL);
1348145b7b3cSmrg
1349145b7b3cSmrg    if (!ctx->login.xic) {
1350145b7b3cSmrg	LogError("Failed to create input context\n");
1351145b7b3cSmrg	XCloseIM(xim);
1352145b7b3cSmrg    }
1353145b7b3cSmrg    return;
1354145b7b3cSmrg}
1355145b7b3cSmrg
1356145b7b3cSmrg/* ARGSUSED */
1357145b7b3cSmrgstatic void
1358145b7b3cSmrgInsertChar (
1359145b7b3cSmrg    Widget	ctxw,
1360145b7b3cSmrg    XEvent	*event,
1361145b7b3cSmrg    String	*params,
1362145b7b3cSmrg    Cardinal	*num_params)
1363145b7b3cSmrg{
1364145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1365145b7b3cSmrg
1366145b7b3cSmrg    char strbuf[128];
1367145b7b3cSmrg    int  len, promptNum = ctx->login.activePrompt;
1368145b7b3cSmrg    KeySym  keysym = 0;
1369145b7b3cSmrg
1370145b7b3cSmrg    if (ctx->login.xic) {
1371145b7b3cSmrg	static Status status;
1372145b7b3cSmrg	len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf,
1373145b7b3cSmrg			      sizeof (strbuf), &keysym, &status);
1374145b7b3cSmrg    } else {
1375145b7b3cSmrg	static XComposeStatus compose_status = {NULL, 0};
1376145b7b3cSmrg	len = XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1377145b7b3cSmrg			     &keysym, &compose_status);
1378145b7b3cSmrg    }
1379145b7b3cSmrg    strbuf[len] = '\0';
1380145b7b3cSmrg
1381145b7b3cSmrg    /*
1382145b7b3cSmrg     * Note: You can override this default key handling
1383145b7b3cSmrg     * by the settings in the translation table
1384145b7b3cSmrg     * loginActionsTable at the end of this file.
1385145b7b3cSmrg     */
1386145b7b3cSmrg    switch (keysym) {
1387145b7b3cSmrg    case XK_Return:
1388145b7b3cSmrg    case XK_KP_Enter:
1389145b7b3cSmrg    case XK_Linefeed:
1390145b7b3cSmrg    case XK_Execute:
1391145b7b3cSmrg	FinishField(ctxw, event, params, num_params);
1392145b7b3cSmrg	return;
1393145b7b3cSmrg    case XK_BackSpace:
1394145b7b3cSmrg	DeleteBackwardChar(ctxw, event, params, num_params);
1395145b7b3cSmrg	return;
1396145b7b3cSmrg    case XK_Delete:
1397145b7b3cSmrg    case XK_KP_Delete:
1398145b7b3cSmrg    case DXK_Remove:
1399145b7b3cSmrg	/* Sorry, it's not a telex machine, it's a terminal */
1400145b7b3cSmrg	DeleteForwardChar(ctxw, event, params, num_params);
1401145b7b3cSmrg	return;
1402145b7b3cSmrg    case XK_Left:
1403145b7b3cSmrg    case XK_KP_Left:
1404145b7b3cSmrg	MoveBackwardChar(ctxw, event, params, num_params);
1405145b7b3cSmrg	return;
1406145b7b3cSmrg    case XK_Right:
1407145b7b3cSmrg    case XK_KP_Right:
1408145b7b3cSmrg	MoveForwardChar(ctxw, event, params, num_params);
1409145b7b3cSmrg	return;
1410145b7b3cSmrg    case XK_End:
1411145b7b3cSmrg    case XK_KP_End:
1412145b7b3cSmrg	MoveToEnd(ctxw, event, params, num_params);
1413145b7b3cSmrg	return;
1414145b7b3cSmrg    case XK_Home:
1415145b7b3cSmrg    case XK_KP_Home:
1416145b7b3cSmrg	MoveToBegining(ctxw, event, params, num_params);
1417145b7b3cSmrg	return;
1418145b7b3cSmrg    default:
1419145b7b3cSmrg	if (len == 0) {
1420145b7b3cSmrg	    if (!IsModifierKey(keysym))  /* it's not a modifier */
1421145b7b3cSmrg		XBell(XtDisplay(ctxw), 60);
1422145b7b3cSmrg	    return;
1423145b7b3cSmrg	} else
1424145b7b3cSmrg	    break;
1425145b7b3cSmrg    }
1426145b7b3cSmrg
1427578741aaSmrg    if (ctx->login.state == PROMPTING) {
1428145b7b3cSmrg	if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >=
1429145b7b3cSmrg	     (VALUE_TEXT_MAX(ctx,promptNum) - 1))) {
1430145b7b3cSmrg	    len = VALUE_TEXT_MAX(ctx,promptNum) -
1431145b7b3cSmrg		strlen(VALUE_TEXT(ctx, promptNum)) - 2;
1432145b7b3cSmrg	}
1433145b7b3cSmrg    }
1434145b7b3cSmrg    EraseCursor (ctx);
1435145b7b3cSmrg    RemoveFail (ctx);
1436145b7b3cSmrg    if (len != 0)
1437145b7b3cSmrg    {
1438145b7b3cSmrg	if (ctx->login.state == PROMPTING) {
1439145b7b3cSmrg	    EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1440145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len,
1441145b7b3cSmrg		    VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1442145b7b3cSmrg		    strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1);
1443145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1444145b7b3cSmrg		     strbuf, len);
1445145b7b3cSmrg	    DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1446145b7b3cSmrg	    PROMPT_CURSOR(ctx, promptNum) += len;
1447145b7b3cSmrg	}
1448145b7b3cSmrg    }
1449145b7b3cSmrg    XorCursor (ctx);
1450145b7b3cSmrg}
1451145b7b3cSmrg
1452145b7b3cSmrg
1453145b7b3cSmrg/**** Copied from xclock.c - original author: Keith Packard ****/
1454145b7b3cSmrg#ifdef USE_XFT
1455145b7b3cSmrgstatic XtConvertArgRec xftColorConvertArgs[] = {
1456145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1457145b7b3cSmrg     sizeof(Screen *)},
1458145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
1459145b7b3cSmrg     sizeof(Colormap)}
1460145b7b3cSmrg};
1461145b7b3cSmrg
1462578741aaSmrg# define	donestr(type, value, tstr) \
1463145b7b3cSmrg	{							\
1464145b7b3cSmrg	    if (toVal->addr != NULL) {				\
1465145b7b3cSmrg		if (toVal->size < sizeof(type)) {		\
1466145b7b3cSmrg		    toVal->size = sizeof(type);			\
1467145b7b3cSmrg		    XtDisplayStringConversionWarning(dpy, 	\
1468145b7b3cSmrg			(char*) fromVal->addr, tstr);		\
1469145b7b3cSmrg		    return False;				\
1470145b7b3cSmrg		}						\
1471145b7b3cSmrg		*(type*)(toVal->addr) = (value);		\
1472145b7b3cSmrg	    }							\
1473145b7b3cSmrg	    else {						\
1474145b7b3cSmrg		static type static_val;				\
1475145b7b3cSmrg		static_val = (value);				\
1476145b7b3cSmrg		toVal->addr = (XPointer)&static_val;		\
1477145b7b3cSmrg	    }							\
1478145b7b3cSmrg	    toVal->size = sizeof(type);				\
1479145b7b3cSmrg	    return True;					\
1480145b7b3cSmrg	}
1481145b7b3cSmrg
1482145b7b3cSmrgstatic void
1483145b7b3cSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1484145b7b3cSmrg		 XrmValuePtr args, Cardinal *num_args)
1485145b7b3cSmrg{
1486145b7b3cSmrg    Screen	*screen;
1487145b7b3cSmrg    Colormap	colormap;
1488145b7b3cSmrg    XftColor	*color;
1489578741aaSmrg
1490145b7b3cSmrg    if (*num_args != 2)
1491145b7b3cSmrg    {
1492145b7b3cSmrg	XtAppErrorMsg (app,
1493145b7b3cSmrg		       "freeXftColor", "wrongParameters",
1494145b7b3cSmrg		       "XtToolkitError",
1495145b7b3cSmrg		       "Freeing an XftColor requires screen and colormap arguments",
1496145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1497145b7b3cSmrg	return;
1498145b7b3cSmrg    }
1499145b7b3cSmrg
1500145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1501145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1502145b7b3cSmrg    color = (XftColor *) toVal->addr;
1503145b7b3cSmrg    XftColorFree (DisplayOfScreen (screen),
1504145b7b3cSmrg		  DefaultVisual (DisplayOfScreen (screen),
1505145b7b3cSmrg				 XScreenNumberOfScreen (screen)),
1506145b7b3cSmrg		  colormap, color);
1507145b7b3cSmrg}
1508578741aaSmrg
1509145b7b3cSmrgstatic Boolean
1510145b7b3cSmrgXmuCvtStringToXftColor(Display *dpy,
1511145b7b3cSmrg		       XrmValue *args, Cardinal *num_args,
1512145b7b3cSmrg		       XrmValue *fromVal, XrmValue *toVal,
1513145b7b3cSmrg		       XtPointer *converter_data)
1514145b7b3cSmrg{
1515145b7b3cSmrg    char	    *spec;
1516145b7b3cSmrg    XRenderColor    renderColor;
1517145b7b3cSmrg    XftColor	    xftColor;
1518145b7b3cSmrg    Screen	    *screen;
1519145b7b3cSmrg    Colormap	    colormap;
1520578741aaSmrg
1521145b7b3cSmrg    if (*num_args != 2)
1522145b7b3cSmrg    {
1523145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1524145b7b3cSmrg		       "cvtStringToXftColor", "wrongParameters",
1525145b7b3cSmrg		       "XtToolkitError",
1526145b7b3cSmrg		       "String to render color conversion needs screen and colormap arguments",
1527145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1528145b7b3cSmrg	return False;
1529145b7b3cSmrg    }
1530145b7b3cSmrg
1531145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1532145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1533145b7b3cSmrg
1534145b7b3cSmrg    spec = (char *) fromVal->addr;
1535145b7b3cSmrg    if (strcasecmp (spec, XtDefaultForeground) == 0)
1536145b7b3cSmrg    {
1537145b7b3cSmrg	renderColor.red = 0;
1538145b7b3cSmrg	renderColor.green = 0;
1539145b7b3cSmrg	renderColor.blue = 0;
1540145b7b3cSmrg	renderColor.alpha = 0xffff;
1541145b7b3cSmrg    }
1542145b7b3cSmrg    else if (strcasecmp (spec, XtDefaultBackground) == 0)
1543145b7b3cSmrg    {
1544145b7b3cSmrg	renderColor.red = 0xffff;
1545145b7b3cSmrg	renderColor.green = 0xffff;
1546145b7b3cSmrg	renderColor.blue = 0xffff;
1547145b7b3cSmrg	renderColor.alpha = 0xffff;
1548145b7b3cSmrg    }
1549145b7b3cSmrg    else if (!XRenderParseColor (dpy, spec, &renderColor))
1550145b7b3cSmrg	return False;
1551578741aaSmrg    if (!XftColorAllocValue (dpy,
1552145b7b3cSmrg			     DefaultVisual (dpy,
1553145b7b3cSmrg					    XScreenNumberOfScreen (screen)),
1554145b7b3cSmrg			     colormap,
1555145b7b3cSmrg			     &renderColor,
1556145b7b3cSmrg			     &xftColor))
1557145b7b3cSmrg	return False;
1558578741aaSmrg
1559145b7b3cSmrg    donestr (XftColor, xftColor, XtRXftColor);
1560145b7b3cSmrg}
1561145b7b3cSmrg
1562145b7b3cSmrgstatic void
1563145b7b3cSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1564145b7b3cSmrg		XrmValuePtr args, Cardinal *num_args)
1565145b7b3cSmrg{
1566145b7b3cSmrg    Screen  *screen;
1567145b7b3cSmrg    XftFont *font;
1568578741aaSmrg
1569145b7b3cSmrg    if (*num_args != 1)
1570145b7b3cSmrg    {
1571145b7b3cSmrg	XtAppErrorMsg (app,
1572145b7b3cSmrg		       "freeXftFont", "wrongParameters",
1573145b7b3cSmrg		       "XtToolkitError",
1574145b7b3cSmrg		       "Freeing an XftFont requires screen argument",
1575145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1576145b7b3cSmrg	return;
1577145b7b3cSmrg    }
1578145b7b3cSmrg
1579145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1580145b7b3cSmrg    font = *((XftFont **) toVal->addr);
1581145b7b3cSmrg    if (font)
1582145b7b3cSmrg	XftFontClose (DisplayOfScreen (screen), font);
1583145b7b3cSmrg}
1584145b7b3cSmrg
1585145b7b3cSmrgstatic Boolean
1586145b7b3cSmrgXmuCvtStringToXftFont(Display *dpy,
1587145b7b3cSmrg		      XrmValue *args, Cardinal *num_args,
1588145b7b3cSmrg		      XrmValue *fromVal, XrmValue *toVal,
1589145b7b3cSmrg		      XtPointer *converter_data)
1590145b7b3cSmrg{
1591145b7b3cSmrg    char    *name;
1592145b7b3cSmrg    XftFont *font;
1593145b7b3cSmrg    Screen  *screen;
1594578741aaSmrg
1595145b7b3cSmrg    if (*num_args != 1)
1596145b7b3cSmrg    {
1597145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1598145b7b3cSmrg		       "cvtStringToXftFont", "wrongParameters",
1599145b7b3cSmrg		       "XtToolkitError",
1600145b7b3cSmrg		       "String to XftFont conversion needs screen argument",
1601145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1602145b7b3cSmrg	return False;
1603145b7b3cSmrg    }
1604145b7b3cSmrg
1605145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1606145b7b3cSmrg    name = (char *) fromVal->addr;
1607578741aaSmrg
1608145b7b3cSmrg    font = XftFontOpenName (dpy,
1609145b7b3cSmrg			    XScreenNumberOfScreen (screen),
1610145b7b3cSmrg			    name);
1611145b7b3cSmrg    if (font)
1612145b7b3cSmrg    {
1613145b7b3cSmrg	donestr (XftFont *, font, XtRXftFont);
1614145b7b3cSmrg    }
1615145b7b3cSmrg    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
1616145b7b3cSmrg    return False;
1617145b7b3cSmrg}
1618145b7b3cSmrg
1619145b7b3cSmrgstatic XtConvertArgRec xftFontConvertArgs[] = {
1620145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1621145b7b3cSmrg     sizeof(Screen *)},
1622145b7b3cSmrg};
1623145b7b3cSmrg
1624145b7b3cSmrg
1625145b7b3cSmrgstatic int
1626145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len)
1627145b7b3cSmrg{
1628145b7b3cSmrg    XGlyphInfo  extents;
1629145b7b3cSmrg
1630145b7b3cSmrg    XftTextExtents8 (dpy, font, string, len, &extents);
1631145b7b3cSmrg
1632145b7b3cSmrg    return extents.xOff;
1633145b7b3cSmrg}
1634145b7b3cSmrg
1635145b7b3cSmrg#endif /* USE_XFT */
1636145b7b3cSmrg
1637578741aaSmrgstatic void
1638145b7b3cSmrgClassInitialize(void)
1639145b7b3cSmrg{
1640145b7b3cSmrg#ifdef USE_XFT
1641578741aaSmrg    XtSetTypeConverter (XtRString, XtRXftColor,
1642578741aaSmrg			XmuCvtStringToXftColor,
1643145b7b3cSmrg			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
1644145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftColor);
1645145b7b3cSmrg    XtSetTypeConverter (XtRString, XtRXftFont,
1646145b7b3cSmrg			XmuCvtStringToXftFont,
1647145b7b3cSmrg			xftFontConvertArgs, XtNumber(xftFontConvertArgs),
1648145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftFont);
1649145b7b3cSmrg#endif /* USE_XFT */
1650145b7b3cSmrg}
1651145b7b3cSmrg/**** End of portion borrowed from xclock ****/
1652145b7b3cSmrg
1653145b7b3cSmrg/* ARGSUSED */
1654145b7b3cSmrgstatic void Initialize (
1655145b7b3cSmrg    Widget greq,
1656145b7b3cSmrg    Widget gnew,
1657145b7b3cSmrg    ArgList args,
1658145b7b3cSmrg    Cardinal *num_args)
1659145b7b3cSmrg{
1660145b7b3cSmrg    LoginWidget w = (LoginWidget)gnew;
1661145b7b3cSmrg    XtGCMask	valuemask, xvaluemask;
1662145b7b3cSmrg    XGCValues	myXGCV;
1663145b7b3cSmrg    Arg		position[2];
1664145b7b3cSmrg    Position	x, y;
1665145b7b3cSmrg#ifdef USE_XINERAMA
1666145b7b3cSmrg    XineramaScreenInfo *screens;
1667145b7b3cSmrg    int                 s_num;
1668145b7b3cSmrg#endif
1669145b7b3cSmrg    int 	rv = 0;
1670578741aaSmrg
1671145b7b3cSmrg    myXGCV.foreground = w->login.hipixel;
1672145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1673145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1674145b7b3cSmrg    w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV);
1675145b7b3cSmrg
1676145b7b3cSmrg    myXGCV.foreground = w->login.shdpixel;
1677145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1678145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1679145b7b3cSmrg    w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV);
1680145b7b3cSmrg
1681145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text);
1682145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1683145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1684145b7b3cSmrg#ifndef USE_XFT
1685145b7b3cSmrg    if (w->login.textFont) {
1686145b7b3cSmrg	myXGCV.font = w->login.textFont->fid;
1687145b7b3cSmrg	valuemask |= GCFont;
1688145b7b3cSmrg    }
1689578741aaSmrg#endif
1690145b7b3cSmrg    w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
1691145b7b3cSmrg    myXGCV.foreground = w->core.background_pixel;
1692145b7b3cSmrg    w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
1693145b7b3cSmrg
1694145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text) ^ w->core.background_pixel;
1695145b7b3cSmrg    myXGCV.function = GXxor;
1696145b7b3cSmrg    xvaluemask = valuemask | GCFunction;
1697145b7b3cSmrg    w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1698145b7b3cSmrg
1699145b7b3cSmrg#ifndef USE_XFT
1700145b7b3cSmrg    /*
1701145b7b3cSmrg     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
1702145b7b3cSmrg     * returns the curently contained font.
1703145b7b3cSmrg     */
1704145b7b3cSmrg
1705145b7b3cSmrg    if (w->login.textFont == NULL)
1706145b7b3cSmrg	w->login.textFont = XQueryFont (XtDisplay (w),
1707145b7b3cSmrg		XGContextFromGC (XDefaultGCOfScreen (XtScreen (w))));
1708145b7b3cSmrg
1709145b7b3cSmrg    xvaluemask = valuemask;
1710145b7b3cSmrg    if (w->login.promptFont == NULL)
1711145b7b3cSmrg        w->login.promptFont = w->login.textFont;
1712145b7b3cSmrg    else
1713145b7b3cSmrg	xvaluemask |= GCFont;
1714145b7b3cSmrg
1715145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(prompt);
1716145b7b3cSmrg    myXGCV.font = w->login.promptFont->fid;
1717145b7b3cSmrg    w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1718145b7b3cSmrg
1719145b7b3cSmrg    xvaluemask = valuemask;
1720145b7b3cSmrg    if (w->login.greetFont == NULL)
1721629baa8cSmrg	w->login.greetFont = w->login.textFont;
1722145b7b3cSmrg    else
1723145b7b3cSmrg	xvaluemask |= GCFont;
1724145b7b3cSmrg
1725145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(greet);
1726145b7b3cSmrg    myXGCV.font = w->login.greetFont->fid;
1727145b7b3cSmrg    w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1728145b7b3cSmrg
1729145b7b3cSmrg    xvaluemask = valuemask;
1730145b7b3cSmrg    if (w->login.failFont == NULL)
1731145b7b3cSmrg	w->login.failFont = w->login.textFont;
1732145b7b3cSmrg    else
1733145b7b3cSmrg	xvaluemask |= GCFont;
1734145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(fail);
1735145b7b3cSmrg    myXGCV.font = w->login.failFont->fid;
1736145b7b3cSmrg    w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1737145b7b3cSmrg#endif /* USE_XFT */
1738145b7b3cSmrg
1739145b7b3cSmrg#ifdef XPM
1740145b7b3cSmrg    w->login.logoValid = False;
1741145b7b3cSmrg
1742145b7b3cSmrg    if (NULL != w->login.logoFileName)
1743145b7b3cSmrg    {
1744145b7b3cSmrg        XpmAttributes myAttributes = { 0 };
1745145b7b3cSmrg        Window tmpWindow = { 0 };
1746145b7b3cSmrg        struct stat myBuffer = { 0 };
1747145b7b3cSmrg        unsigned int myPixmapDepth = 0;
1748145b7b3cSmrg
1749145b7b3cSmrg        if (0 != stat(w->login.logoFileName, &myBuffer))
1750145b7b3cSmrg        {
1751145b7b3cSmrg            LogError("Unable to stat() pixmap file %s\n",
1752145b7b3cSmrg                w->login.logoFileName);
1753145b7b3cSmrg            w->login.logoValid = False;
1754145b7b3cSmrg            goto SkipXpmLoad;
1755145b7b3cSmrg        }
1756145b7b3cSmrg
1757145b7b3cSmrg        myAttributes.valuemask |= XpmReturnPixels;
1758145b7b3cSmrg        myAttributes.valuemask |= XpmReturnExtensions;
1759145b7b3cSmrg
1760145b7b3cSmrg        rv = XpmReadFileToPixmap(XtDisplay(w),		/* display */
1761145b7b3cSmrg	     RootWindowOfScreen(XtScreen(w)),		/* window */
1762145b7b3cSmrg	     w->login.logoFileName,			/* XPM filename */
1763145b7b3cSmrg	     &(w->login.logoPixmap),			/* pixmap */
1764145b7b3cSmrg	     &(w->login.logoMask),			/* pixmap mask */
1765145b7b3cSmrg	     &myAttributes);				/* XPM attributes */
1766578741aaSmrg
1767145b7b3cSmrg	if ( rv < 0 )
1768145b7b3cSmrg	{
1769145b7b3cSmrg	    LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName,
1770145b7b3cSmrg		     XpmGetErrorString(rv));
1771145b7b3cSmrg	    goto SkipXpmLoad;
1772145b7b3cSmrg	}
1773145b7b3cSmrg
1774145b7b3cSmrg	w->login.logoValid = True;
1775145b7b3cSmrg
1776145b7b3cSmrg        XGetGeometry(XtDisplay(w), w->login.logoPixmap,
1777145b7b3cSmrg            &tmpWindow,
1778145b7b3cSmrg            &(w->login.logoX),
1779145b7b3cSmrg            &(w->login.logoY),
1780145b7b3cSmrg            &(w->login.logoWidth),
1781145b7b3cSmrg            &(w->login.logoHeight),
1782145b7b3cSmrg            &(w->login.logoBorderWidth),
1783145b7b3cSmrg            &myPixmapDepth);
1784145b7b3cSmrg    } else {
1785145b7b3cSmrg	w->login.logoX = 0;
1786145b7b3cSmrg	w->login.logoY = 0;
1787145b7b3cSmrg	w->login.logoWidth = 0;
1788145b7b3cSmrg	w->login.logoHeight = 0;
1789145b7b3cSmrg	w->login.logoBorderWidth = 0;
1790145b7b3cSmrg    }
1791145b7b3cSmrg
1792145b7b3cSmrg
1793145b7b3cSmrgSkipXpmLoad:
1794145b7b3cSmrg#endif /* XPM */
1795145b7b3cSmrg    w->login.data.name[0] = '\0';
1796145b7b3cSmrg    w->login.data.passwd[0] = '\0';
1797145b7b3cSmrg    w->login.state = INITIALIZING;
1798145b7b3cSmrg    w->login.activePrompt = LOGIN_PROMPT_USERNAME;
1799145b7b3cSmrg    w->login.failUp = 0;
1800145b7b3cSmrg    w->login.fail = (char *) w->login.failMsg;
1801145b7b3cSmrg
1802145b7b3cSmrg    /* Set prompt defaults */
1803145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= NULL;
1804145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.namePrompt;
1805145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.data.name;
1806145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME)	= sizeof(w->login.data.name);
1807145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME)	= 0;
1808578741aaSmrg
1809145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= NULL;
1810145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.passwdPrompt;
1811145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.data.passwd;
1812145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD)	= sizeof(w->login.data.passwd);
1813145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD)	= 0;
1814145b7b3cSmrg
1815145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False);
1816145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False);
1817578741aaSmrg
1818145b7b3cSmrg    if (w->core.width == 0)
1819145b7b3cSmrg	w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
1820145b7b3cSmrg    if (w->core.height == 0) {
1821145b7b3cSmrg	int fy = FAIL_Y(w);
1822145b7b3cSmrg	int pady = PAD_Y(w);
1823145b7b3cSmrg
1824145b7b3cSmrg#ifndef XPM
1825145b7b3cSmrg	w->core.height = fy + pady;	/* for stupid compilers */
1826145b7b3cSmrg#else
1827145b7b3cSmrg/*	w->core.height = fy + pady;	* for stupid compilers */
1828145b7b3cSmrg
1829145b7b3cSmrg        w->core.height = max(fy + pady,
1830145b7b3cSmrg            (w->login.logoHeight + (2*w->login.logoPadding)) + pady);
1831578741aaSmrg
1832145b7b3cSmrg#endif /* XPM */
1833145b7b3cSmrg    }
1834145b7b3cSmrg#ifdef USE_XINERAMA
1835145b7b3cSmrg    if (
1836145b7b3cSmrg	XineramaIsActive(XtDisplay(w)) &&
1837145b7b3cSmrg	(screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL
1838145b7b3cSmrg       )
1839145b7b3cSmrg    {
1840145b7b3cSmrg	if ((x = w->core.x) == -1)
1841145b7b3cSmrg	    x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2;
1842145b7b3cSmrg	if ((y = w->core.y) == -1)
1843145b7b3cSmrg	    y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3;
1844578741aaSmrg
1845145b7b3cSmrg	XFree(screens);
1846145b7b3cSmrg    }
1847145b7b3cSmrg    else
1848145b7b3cSmrg#endif
1849145b7b3cSmrg    {
1850145b7b3cSmrg	if ((x = w->core.x) == -1)
1851145b7b3cSmrg	    x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2;
1852145b7b3cSmrg	if ((y = w->core.y) == -1)
1853145b7b3cSmrg	    y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3;
1854145b7b3cSmrg    }
1855145b7b3cSmrg    XtSetArg (position[0], XtNx, x);
1856145b7b3cSmrg    XtSetArg (position[1], XtNy, y);
1857145b7b3cSmrg    XtSetValues (XtParent (w), position, (Cardinal) 2);
1858145b7b3cSmrg
1859145b7b3cSmrg    w->login.state = PROMPTING;
1860145b7b3cSmrg}
1861145b7b3cSmrg
1862578741aaSmrg
1863145b7b3cSmrgstatic void Realize (
1864145b7b3cSmrg     Widget gw,
1865145b7b3cSmrg     XtValueMask *valueMask,
1866145b7b3cSmrg     XSetWindowAttributes *attrs)
1867145b7b3cSmrg{
1868145b7b3cSmrg    LoginWidget	w = (LoginWidget) gw;
1869145b7b3cSmrg    Cursor cursor;
1870145b7b3cSmrg
1871145b7b3cSmrg    XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
1872145b7b3cSmrg		     *valueMask, attrs );
1873145b7b3cSmrg    InitI18N(gw);
1874145b7b3cSmrg
1875145b7b3cSmrg#ifdef USE_XFT
1876145b7b3cSmrg    w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w),
1877145b7b3cSmrg	   DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))),
1878145b7b3cSmrg				   w->core.colormap);
1879145b7b3cSmrg
1880145b7b3cSmrg#endif
1881145b7b3cSmrg
1882145b7b3cSmrg    cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr);
1883145b7b3cSmrg    XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor);
1884145b7b3cSmrg
1885145b7b3cSmrg#ifdef XPM
1886578741aaSmrg    /*
1887145b7b3cSmrg     * Check if Pixmap was valid
1888145b7b3cSmrg     */
1889145b7b3cSmrg    if (True == w->login.logoValid)
1890145b7b3cSmrg    {
1891145b7b3cSmrg        /*
1892578741aaSmrg         * Create pixmap window
1893145b7b3cSmrg         */
1894145b7b3cSmrg        {
1895629baa8cSmrg            XSetWindowAttributes windowAttributes = {
1896629baa8cSmrg                .background_pixel = w->core.background_pixel,
1897629baa8cSmrg                .background_pixmap = None
1898629baa8cSmrg            };
1899145b7b3cSmrg
1900145b7b3cSmrg            w->login.logoWindow = XCreateWindow(XtDisplay(w),
1901145b7b3cSmrg                XtWindow(w),
1902145b7b3cSmrg                w->core.width - w->login.outframewidth -
1903145b7b3cSmrg                    w->login.logoWidth - w->login.logoPadding,
1904145b7b3cSmrg                (w->core.height - w->login.logoHeight) /2,
1905145b7b3cSmrg                w->login.logoWidth, w->login.logoHeight, 0,
1906145b7b3cSmrg                CopyFromParent, InputOutput, CopyFromParent,
1907629baa8cSmrg                CWBackPixel | CWBackPixmap, &windowAttributes);
1908145b7b3cSmrg        }
1909145b7b3cSmrg
1910145b7b3cSmrg        /*
1911145b7b3cSmrg         * check if we can use shape extension
1912145b7b3cSmrg         */
1913145b7b3cSmrg        if (True == w->login.useShape)
1914145b7b3cSmrg        {
1915145b7b3cSmrg            int foo, bar;
1916145b7b3cSmrg
1917145b7b3cSmrg            if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE)
1918145b7b3cSmrg            {
1919145b7b3cSmrg                XShapeCombineMask(XtDisplay(w), w->login.logoWindow,
1920145b7b3cSmrg                    ShapeBounding, w->login.logoX, w->login.logoY,
1921145b7b3cSmrg                    w->login.logoMask, ShapeSet);
1922145b7b3cSmrg            }
1923145b7b3cSmrg        }
1924145b7b3cSmrg
1925145b7b3cSmrg        XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow,
1926145b7b3cSmrg            w->login.logoPixmap);
1927145b7b3cSmrg        XMapWindow(XtDisplay(w), w->login.logoWindow);
1928145b7b3cSmrg    }
1929145b7b3cSmrg#endif /* XPM */
1930145b7b3cSmrg}
1931145b7b3cSmrg
1932145b7b3cSmrgstatic void Destroy (Widget gw)
1933145b7b3cSmrg{
1934145b7b3cSmrg    LoginWidget w = (LoginWidget)gw;
1935145b7b3cSmrg    bzero (w->login.data.name, NAME_LEN);
1936145b7b3cSmrg    bzero (w->login.data.passwd, PASSWORD_LEN);
1937145b7b3cSmrg
1938145b7b3cSmrg    if (PROMPT_TEXT(w,0) != NULL)
1939145b7b3cSmrg	XtFree(PROMPT_TEXT(w,0));
1940145b7b3cSmrg    if (PROMPT_TEXT(w,1) != NULL)
1941145b7b3cSmrg	XtFree(PROMPT_TEXT(w,1));
1942145b7b3cSmrg
1943145b7b3cSmrg#ifdef USE_XFT
1944145b7b3cSmrg    if (w->login.draw) {
1945145b7b3cSmrg	XftDrawDestroy(w->login.draw);
1946145b7b3cSmrg	w->login.draw = NULL;
1947145b7b3cSmrg    }
1948578741aaSmrg#endif
1949578741aaSmrg
1950145b7b3cSmrg    XtReleaseGC(gw, w->login.textGC);
1951145b7b3cSmrg    XtReleaseGC(gw, w->login.bgGC);
1952145b7b3cSmrg    XtReleaseGC(gw, w->login.xorGC);
1953145b7b3cSmrg#ifndef USE_XFT
1954145b7b3cSmrg    XtReleaseGC(gw, w->login.promptGC);
1955145b7b3cSmrg    XtReleaseGC(gw, w->login.greetGC);
1956145b7b3cSmrg    XtReleaseGC(gw, w->login.failGC);
1957145b7b3cSmrg#endif
1958145b7b3cSmrg    XtReleaseGC(gw, w->login.hiGC);
1959145b7b3cSmrg    XtReleaseGC(gw, w->login.shdGC);
1960145b7b3cSmrg
1961145b7b3cSmrg#ifdef XPM
1962145b7b3cSmrg    if (True == w->login.logoValid)
1963145b7b3cSmrg    {
1964145b7b3cSmrg        if (w->login.logoPixmap != 0)
1965145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoPixmap);
1966145b7b3cSmrg
1967145b7b3cSmrg        if (w->login.logoMask != 0)
1968145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoMask);
1969145b7b3cSmrg    }
1970145b7b3cSmrg#endif /* XPM */
1971145b7b3cSmrg}
1972145b7b3cSmrg
1973145b7b3cSmrg/* ARGSUSED */
1974145b7b3cSmrgstatic void Redisplay(
1975145b7b3cSmrg     Widget gw,
1976145b7b3cSmrg     XEvent *event,
1977145b7b3cSmrg     Region region)
1978145b7b3cSmrg{
1979145b7b3cSmrg    draw_it ((LoginWidget) gw);
1980145b7b3cSmrg}
1981145b7b3cSmrg
1982145b7b3cSmrg/*ARGSUSED*/
1983145b7b3cSmrgstatic Boolean SetValues (
1984145b7b3cSmrg    Widget  current,
1985145b7b3cSmrg    Widget  request,
1986145b7b3cSmrg    Widget  new,
1987145b7b3cSmrg    ArgList args,
1988145b7b3cSmrg    Cardinal *num_args)
1989145b7b3cSmrg{
1990145b7b3cSmrg    LoginWidget currentL, newL;
1991578741aaSmrg
1992145b7b3cSmrg    currentL = (LoginWidget) current;
1993145b7b3cSmrg    newL = (LoginWidget) new;
1994145b7b3cSmrg    if (GREETING (currentL) != GREETING (newL))
1995145b7b3cSmrg	return True;
1996145b7b3cSmrg    return False;
1997145b7b3cSmrg}
1998145b7b3cSmrg
1999145b7b3cSmrgstatic
2000145b7b3cSmrgchar defaultLoginTranslations [] =
2001145b7b3cSmrg"Ctrl<Key>H:	delete-previous-character() \n"
2002145b7b3cSmrg"Ctrl<Key>D:	delete-character() \n"
2003145b7b3cSmrg"Ctrl<Key>B:	move-backward-character() \n"
2004145b7b3cSmrg"Ctrl<Key>F:	move-forward-character() \n"
2005145b7b3cSmrg"Ctrl<Key>A:	move-to-begining() \n"
2006145b7b3cSmrg"Ctrl<Key>E:	move-to-end() \n"
2007145b7b3cSmrg"Ctrl<Key>K:	erase-to-end-of-line() \n"
2008145b7b3cSmrg"Ctrl<Key>U:	erase-line() \n"
2009145b7b3cSmrg"Ctrl<Key>X:	erase-line() \n"
2010145b7b3cSmrg"Ctrl<Key>C:	restart-session() \n"
2011145b7b3cSmrg"Ctrl<Key>\\\\:	abort-session() \n"
2012145b7b3cSmrg":Ctrl<Key>plus:	allow-all-access() \n"
2013145b7b3cSmrg"<Key>BackSpace:	delete-previous-character() \n"
2014145b7b3cSmrg#ifdef linux
2015145b7b3cSmrg"<Key>Delete:	delete-character() \n"
2016145b7b3cSmrg#else
2017145b7b3cSmrg"<Key>Delete:	delete-previous-character() \n"
2018145b7b3cSmrg#endif
2019145b7b3cSmrg"<Key>Return:	finish-field() \n"
2020145b7b3cSmrg"<Key>Tab:	tab-field() \n"
2021145b7b3cSmrg"<KeyPress>:	insert-char()"
2022145b7b3cSmrg;
2023145b7b3cSmrg
2024145b7b3cSmrgstatic
2025145b7b3cSmrgXtActionsRec loginActionsTable [] = {
2026145b7b3cSmrg  {"delete-previous-character",	DeleteBackwardChar},
2027145b7b3cSmrg  {"delete-character",		DeleteForwardChar},
2028145b7b3cSmrg  {"move-backward-character",	MoveBackwardChar},
2029145b7b3cSmrg  {"move-forward-character",	MoveForwardChar},
2030145b7b3cSmrg  {"move-to-begining",		MoveToBegining},
2031145b7b3cSmrg  {"move-to-end",		MoveToEnd},
2032145b7b3cSmrg  {"erase-to-end-of-line",	EraseToEndOfLine},
2033145b7b3cSmrg  {"erase-line",		EraseLine},
2034145b7b3cSmrg  {"finish-field", 		FinishField},
2035145b7b3cSmrg  {"tab-field", 		TabField},
2036145b7b3cSmrg  {"abort-session",		AbortSession},
2037145b7b3cSmrg  {"abort-display",		AbortDisplay},
2038145b7b3cSmrg  {"restart-session",		RestartSession},
2039145b7b3cSmrg  {"insert-char", 		InsertChar},
2040145b7b3cSmrg  {"set-session-argument",	SetSessionArgument},
2041145b7b3cSmrg  {"allow-all-access",		AllowAccess},
2042145b7b3cSmrg};
2043145b7b3cSmrg
2044145b7b3cSmrgLoginClassRec loginClassRec = {
2045145b7b3cSmrg    { /* core fields */
2046145b7b3cSmrg    /* superclass		*/	&widgetClassRec,
2047145b7b3cSmrg    /* class_name		*/	"Login",
2048145b7b3cSmrg    /* size			*/	sizeof(LoginRec),
2049145b7b3cSmrg    /* class_initialize		*/	ClassInitialize,
2050145b7b3cSmrg    /* class_part_initialize	*/	NULL,
2051145b7b3cSmrg    /* class_inited		*/	FALSE,
2052145b7b3cSmrg    /* initialize		*/	Initialize,
2053145b7b3cSmrg    /* initialize_hook		*/	NULL,
2054145b7b3cSmrg    /* realize			*/	Realize,
2055145b7b3cSmrg    /* actions			*/	loginActionsTable,
2056145b7b3cSmrg    /* num_actions		*/	XtNumber (loginActionsTable),
2057145b7b3cSmrg    /* resources		*/	resources,
2058145b7b3cSmrg    /* num_resources		*/	XtNumber(resources),
2059145b7b3cSmrg    /* xrm_class		*/	NULLQUARK,
2060145b7b3cSmrg    /* compress_motion		*/	TRUE,
2061145b7b3cSmrg    /* compress_exposure	*/	TRUE,
2062145b7b3cSmrg    /* compress_enterleave	*/	TRUE,
2063145b7b3cSmrg    /* visible_interest		*/	FALSE,
2064145b7b3cSmrg    /* destroy			*/	Destroy,
2065145b7b3cSmrg    /* resize			*/	NULL,
2066145b7b3cSmrg    /* expose			*/	Redisplay,
2067145b7b3cSmrg    /* set_values		*/	SetValues,
2068145b7b3cSmrg    /* set_values_hook		*/	NULL,
2069145b7b3cSmrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
2070145b7b3cSmrg    /* get_values_hook		*/	NULL,
2071145b7b3cSmrg    /* accept_focus		*/	NULL,
2072145b7b3cSmrg    /* version			*/	XtVersion,
2073145b7b3cSmrg    /* callback_private		*/	NULL,
2074145b7b3cSmrg    /* tm_table			*/	defaultLoginTranslations,
2075145b7b3cSmrg    /* query_geometry		*/	XtInheritQueryGeometry,
2076145b7b3cSmrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
2077145b7b3cSmrg    /* extension		*/	NULL
2078145b7b3cSmrg    }
2079145b7b3cSmrg};
2080145b7b3cSmrg
2081145b7b3cSmrgWidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
2082