Login.c revision 026e32a9
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
247026e32a9Smlelstv#define PROMPT_X_INC(w)		F_MAX_WIDTH(prompt)
248026e32a9Smlelstv#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
256026e32a9Smlelstv#define Y_ASCENT(w)	max (F_ASCENT(prompt), F_ASCENT(text))
257026e32a9Smlelstv#define Y_DESCENT(w)	max (F_DESCENT(prompt), F_DESCENT(text))
258026e32a9Smlelstv#define Y_INC(w)	(Y_ASCENT(w) + Y_DESCENT(w))
259145b7b3cSmrg
260026e32a9Smlelstv#define CURSOR_W	5
261145b7b3cSmrg
262578741aaSmrg#define PROMPT_TEXT(w,n) 	((w)->login.prompts[n].promptText)
263578741aaSmrg#define DEF_PROMPT_TEXT(w,n) 	((w)->login.prompts[n].defaultPrompt)
264578741aaSmrg#define VALUE_TEXT(w,n) 	((w)->login.prompts[n].valueText)
265578741aaSmrg#define VALUE_TEXT_MAX(w,n)	((w)->login.prompts[n].valueTextMax)
266578741aaSmrg#define VALUE_SHOW_START(w,n)	((w)->login.prompts[n].valueShownStart)
267578741aaSmrg#define VALUE_SHOW_END(w,n)	((w)->login.prompts[n].valueShownEnd)
268578741aaSmrg#define PROMPT_STATE(w,n) 	((w)->login.prompts[n].state)
269578741aaSmrg#define PROMPT_CURSOR(w,n)	((w)->login.prompts[n].cursor)
270145b7b3cSmrg
271578741aaSmrg#define CUR_PROMPT_CURSOR(w)	PROMPT_CURSOR(w,w->login.activePrompt)
272145b7b3cSmrg
273578741aaSmrg#define CUR_PROMPT_TEXT(w, n)	(PROMPT_TEXT(w,n) != NULL ? \
274145b7b3cSmrg				 PROMPT_TEXT(w,n) : DEF_PROMPT_TEXT(w,n))
275145b7b3cSmrg
276145b7b3cSmrg#ifdef USE_XFT
277145b7b3cSmrg
278145b7b3cSmrgstatic int
279145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len);
280145b7b3cSmrg
281026e32a9Smlelstv# define TEXT_COLOR(f)		(w->login.f##color.pixel)
282026e32a9Smlelstv# define TEXT_WIDTH(f, m, l) 	XmuXftTextWidth(XtDisplay (w), \
283026e32a9Smlelstv				w->login.f##Face, (FcChar8 *) m, l)
284145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
285145b7b3cSmrg	/* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \
286145b7b3cSmrg	XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \
287145b7b3cSmrg			x, y, (FcChar8 *) m, l)
288145b7b3cSmrg
289145b7b3cSmrg#else
290145b7b3cSmrg
291145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##pixel)
292145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	(XTextWidth (w->login.f##Font, m, l))
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
303026e32a9Smlelstv# define LOGO_PAD(w)   ((w)->login.logoPadding)
304026e32a9Smlelstv# define LOGO_W(w)     ((w)->login.logoWidth + (LOGO_PAD(w) * 2))
305629baa8cSmrg#else
306026e32a9Smlelstv# define LOGO_PAD(w)   0
307629baa8cSmrg# define LOGO_W(w)     0
308629baa8cSmrg#endif
309145b7b3cSmrg
310578741aaSmrg#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth)
311145b7b3cSmrg
312026e32a9Smlelstv#define DEF_PROMPT_W(w,n)	TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt)
313026e32a9Smlelstv#define MAX_DEF_PROMPT_W(w)	(max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1)))
314026e32a9Smlelstv#define CUR_PROMPT_W(w,n)	(max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \
315026e32a9Smlelstv					TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0))
316145b7b3cSmrg
317578741aaSmrg#define GREETING(w)	((w)->login.secure_session  && !(w)->login.allow_access ?\
318145b7b3cSmrg				(w)->login.greeting : (w)->login.unsecure_greet)
319578741aaSmrg#define GREET_X(w)	((int)((w->core.width - \
320145b7b3cSmrg			     	STRING_WIDTH (greet, GREETING(w))) / 2))
321578741aaSmrg#define GREET_Y(w)	(GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
322629baa8cSmrg#define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
323026e32a9Smlelstv			      STRING_WIDTH (greet, w->login.unsecure_greet)))
324026e32a9Smlelstv
325026e32a9Smlelstv#define SEP_X(w)	((w)->login.outframewidth + LOGO_PAD(w))
326026e32a9Smlelstv#define SEP_Y(w)	(GREET_Y(w) + GREET_Y_INC(w))
327026e32a9Smlelstv#define SEP_W(w)	((w)->core.width - 2*(w->login.outframewidth) - LOGO_W(w) - LOGO_PAD(w))
328026e32a9Smlelstv#define SEP_H(w)	((w)->login.inframeswidth * 2)
329629baa8cSmrg
330578741aaSmrg#define PROMPT_X(w)	(2 * PROMPT_X_INC(w))
331026e32a9Smlelstv#define PROMPT_Y(w,n) 	((SEP_Y(w) + ((n)+1) * GREET_Y_INC(w) + 2 * (w)->login.inframeswidth))
332026e32a9Smlelstv#define PROMPT_W(w)	(w->core.width - PROMPT_X(w) - 2 * TEXT_X_INC(w) - LOGO_W(w))
333026e32a9Smlelstv#define PROMPT_H(w)	Y_INC(w)
334026e32a9Smlelstv
335578741aaSmrg#define VALUE_X(w,n)	(PROMPT_X(w) + CUR_PROMPT_W(w,n))
336026e32a9Smlelstv#define VALUE_Y(w,n)	(PROMPT_Y(w,n))
337026e32a9Smlelstv#define VALUE_W(w,n)	(PROMPT_W(w) - VALUE_X(w,n) + PROMPT_X(w) - CURSOR_W)
338026e32a9Smlelstv#define VALUE_H(w,n)	Y_INC(w)
339145b7b3cSmrg
340b7d26471Smrg#define ERROR_X(w,m)	((int)(w->core.width - LOGO_W(w) - STRING_WIDTH (fail, m)) / 2)
341629baa8cSmrg#define ERROR_W(w,m)	(STRING_WIDTH (fail, m) + LOGO_W(w))
342145b7b3cSmrg
343026e32a9Smlelstv#define FAIL_X(w)	ERROR_X(w, w->login.fail)
344026e32a9Smlelstv#define FAIL_Y(w)	(PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail))
345578741aaSmrg#define FAIL_W(w)	max(ERROR_W(w, w->login.failMsg), \
346145b7b3cSmrg			    ERROR_W(w, w->login.passwdChangeMsg))
347145b7b3cSmrg
348578741aaSmrg#define PAD_X(w)	(2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w))))
349578741aaSmrg#define PAD_Y(w)	(max (max (Y_INC(w), GREET_Y_INC(w)),\
350145b7b3cSmrg			     FAIL_Y_INC(w)))
351578741aaSmrg
352145b7b3cSmrg#ifndef max
353145b7b3cSmrgstatic inline int max (int a, int b) { return a > b ? a : b; }
354145b7b3cSmrg#endif
355145b7b3cSmrg
356145b7b3cSmrgstatic void
357145b7b3cSmrgrealizeValue (LoginWidget w, int cursor, int promptNum, GC gc)
358145b7b3cSmrg{
3595ffd6003Smrg    loginPromptState state = PROMPT_STATE(w, promptNum);
360145b7b3cSmrg    char *text = VALUE_TEXT(w, promptNum);
361026e32a9Smlelstv    int	x, y, height, width, curoff, offset, textlen;
362145b7b3cSmrg
363145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
364145b7b3cSmrg
3655ffd6003Smrg    /* replace all password characters with asterisks */
3665ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
3675ffd6003Smrg    {
3685ffd6003Smrg	Cardinal length = strlen(text);
3695ffd6003Smrg	Cardinal i = 0;
3705ffd6003Smrg
3715ffd6003Smrg	text = XtMalloc(length + 1);
3725ffd6003Smrg
3735ffd6003Smrg	if (text == NULL)
3745ffd6003Smrg	{
3755ffd6003Smrg	    LogOutOfMem("realizeValue");
3765ffd6003Smrg	    return;
3775ffd6003Smrg	}
3785ffd6003Smrg
3795ffd6003Smrg	while (i < length)
3805ffd6003Smrg	{
381629baa8cSmrg	    text[i++] = w->login.echo_passwd_char[0];
3825ffd6003Smrg	}
3835ffd6003Smrg
3845ffd6003Smrg	text[i] = 0;
3855ffd6003Smrg    }
3865ffd6003Smrg
387145b7b3cSmrg    x = VALUE_X (w,promptNum);
388026e32a9Smlelstv    y = VALUE_Y (w,promptNum);
389145b7b3cSmrg
390026e32a9Smlelstv    height = Y_INC(w);
391026e32a9Smlelstv    width = VALUE_W(w,promptNum);
392145b7b3cSmrg
393026e32a9Smlelstv    offset = VALUE_SHOW_START(w, promptNum);
394026e32a9Smlelstv    if (cursor > offset)
395026e32a9Smlelstv	curoff = TEXT_WIDTH (text, text + offset, cursor - offset);
396145b7b3cSmrg    else
397145b7b3cSmrg	curoff = 0;
398145b7b3cSmrg
399145b7b3cSmrg    if (gc == w->login.bgGC) {
400145b7b3cSmrg	if (curoff < width) {
401145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
402026e32a9Smlelstv			    x + curoff, y - Y_ASCENT(w),
403145b7b3cSmrg			    width - curoff, height);
404145b7b3cSmrg	}
4055ffd6003Smrg    } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) ||
4065ffd6003Smrg	       ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)))
4075ffd6003Smrg    {
408026e32a9Smlelstv	offset = max(cursor, VALUE_SHOW_START(w, promptNum));
409026e32a9Smlelstv	textlen = strlen (text + offset);
410578741aaSmrg
411629baa8cSmrg	if (TEXT_WIDTH (text, text + offset, textlen) > (width - curoff)) {
412145b7b3cSmrg	    /* Recalculate amount of text that can fit in field */
413145b7b3cSmrg	    offset = VALUE_SHOW_START(w, promptNum);
414145b7b3cSmrg	    textlen = strlen (text + offset);
415145b7b3cSmrg
416629baa8cSmrg	    while ((textlen > 0) &&
417629baa8cSmrg		   (TEXT_WIDTH (text, text + offset, textlen) > width))
418145b7b3cSmrg	    {
419145b7b3cSmrg		if (offset < PROMPT_CURSOR(w, promptNum)) {
420145b7b3cSmrg		    offset++;
421145b7b3cSmrg		}
422145b7b3cSmrg		textlen--;
423578741aaSmrg	    }
424145b7b3cSmrg
425145b7b3cSmrg	    VALUE_SHOW_START(w, promptNum) = offset;
426145b7b3cSmrg	    VALUE_SHOW_END(w, promptNum) = offset + textlen;
427145b7b3cSmrg
428145b7b3cSmrg	    /* Erase old string */
429145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC,
430026e32a9Smlelstv			    x, y - Y_ASCENT(w), width, height);
431145b7b3cSmrg
432145b7b3cSmrg	    DRAW_STRING(text, x, y, text + offset, textlen);
433145b7b3cSmrg	} else {
434145b7b3cSmrg	    DRAW_STRING(text, x + curoff, y, text + offset, textlen);
435145b7b3cSmrg	}
436145b7b3cSmrg    }
4375ffd6003Smrg    /* free memory */
4385ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
4395ffd6003Smrg    {
4405ffd6003Smrg	XtFree(text);
4415ffd6003Smrg    }
442145b7b3cSmrg}
443145b7b3cSmrg
444145b7b3cSmrgstatic void
445145b7b3cSmrgEraseValue (LoginWidget w, int cursor, int promptNum)
446145b7b3cSmrg{
447145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.bgGC);
448145b7b3cSmrg}
449145b7b3cSmrg
450145b7b3cSmrgstatic void
451145b7b3cSmrgDrawValue (LoginWidget w, int cursor, int promptNum)
452145b7b3cSmrg{
453145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.textGC);
454145b7b3cSmrg#ifdef DANCING
455145b7b3cSmrg    /*as good a place as any Caolan begin*/
456145b7b3cSmrg    w->login.lastEventTime = time(NULL);
457145b7b3cSmrg    /*as good a place as any Caolan end*/
458145b7b3cSmrg#endif /* DANCING */
459145b7b3cSmrg}
460145b7b3cSmrg
461145b7b3cSmrgstatic void
462145b7b3cSmrgrealizeCursor (LoginWidget w, GC gc)
463145b7b3cSmrg{
464145b7b3cSmrg    int	x, y;
465026e32a9Smlelstv    int ascent, descent;
466145b7b3cSmrg
467145b7b3cSmrg    if (w->login.state != PROMPTING) {
468145b7b3cSmrg	return;
469145b7b3cSmrg    }
470578741aaSmrg
471145b7b3cSmrg    x = VALUE_X (w, w->login.activePrompt);
472026e32a9Smlelstv    y = VALUE_Y (w, w->login.activePrompt);
473026e32a9Smlelstv    ascent = F_ASCENT(text);
474026e32a9Smlelstv    descent = F_DESCENT(text);
475145b7b3cSmrg
476145b7b3cSmrg    switch (PROMPT_STATE(w, w->login.activePrompt)) {
477145b7b3cSmrg    case LOGIN_PROMPT_NOT_SHOWN:
478145b7b3cSmrg    case LOGIN_TEXT_INFO:
479145b7b3cSmrg	return;
480145b7b3cSmrg    case LOGIN_PROMPT_ECHO_ON:
481145b7b3cSmrg	if (CUR_PROMPT_CURSOR(w) > 0) {
482145b7b3cSmrg	    x += TEXT_WIDTH (text,
483145b7b3cSmrg			     VALUE_TEXT(w, w->login.activePrompt)
484145b7b3cSmrg			     + VALUE_SHOW_START(w, w->login.activePrompt),
485145b7b3cSmrg			     PROMPT_CURSOR(w, w->login.activePrompt)
486145b7b3cSmrg			     - VALUE_SHOW_START(w, w->login.activePrompt) );
487145b7b3cSmrg	}
488145b7b3cSmrg	break;
489145b7b3cSmrg    case LOGIN_PROMPT_ECHO_OFF:
4905ffd6003Smrg	if (w->login.echo_passwd == True) {
491629baa8cSmrg	    if (w->login.echo_passwd_char[0] != 0) {
492629baa8cSmrg		int len = PROMPT_CURSOR(w, w->login.activePrompt) -
493629baa8cSmrg		    VALUE_SHOW_START(w, w->login.activePrompt);
4945ffd6003Smrg
495629baa8cSmrg		x += len*TEXT_WIDTH(text, w->login.echo_passwd_char, 1);
496629baa8cSmrg	    } else {
497629baa8cSmrg		/* Move cursor one pixel per character to give some feedback
498629baa8cSmrg		   without giving away the password length */
499629baa8cSmrg		if (PROMPT_CURSOR(w, w->login.activePrompt) <
500026e32a9Smlelstv		    VALUE_W(w, w->login.activePrompt))
501629baa8cSmrg		    x += PROMPT_CURSOR(w, w->login.activePrompt);
502629baa8cSmrg		else
503026e32a9Smlelstv		    x += VALUE_W(w, w->login.activePrompt);
504629baa8cSmrg	    }
5055ffd6003Smrg	}
506145b7b3cSmrg	break;
507145b7b3cSmrg    }
508578741aaSmrg
509145b7b3cSmrg    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
510026e32a9Smlelstv		    x, y - ascent + 1, 1, ascent + descent - 2);
511026e32a9Smlelstv
512145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
513026e32a9Smlelstv		    x-1 , y - ascent);
514145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
515026e32a9Smlelstv		    x+1 , y - ascent);
516145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
517026e32a9Smlelstv		    x-1 , y + descent - 1);
518145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
519026e32a9Smlelstv		    x+1 , y - descent - 1);
520026e32a9Smlelstv
521145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
522026e32a9Smlelstv		    x-2 , y - ascent);
523145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
524026e32a9Smlelstv		    x+2 , y - ascent);
525145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
526026e32a9Smlelstv		    x-2 , y + descent - 1);
527145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
528026e32a9Smlelstv		    x+2 , y + descent - 1);
529145b7b3cSmrg
530578741aaSmrg    XFlush (XtDisplay(w));
531145b7b3cSmrg}
532145b7b3cSmrg
533145b7b3cSmrgstatic void
534145b7b3cSmrgEraseFail (LoginWidget w)
535145b7b3cSmrg{
536578741aaSmrg#ifdef USE_XFT
537145b7b3cSmrg    w->login.failUp = 0;
538145b7b3cSmrg    RedrawFail(w);
539578741aaSmrg#else
540145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
541145b7b3cSmrg			w->core.background_pixel);
542145b7b3cSmrg    RedrawFail(w);
543145b7b3cSmrg    w->login.failUp = 0;
544145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
545145b7b3cSmrg			TEXT_COLOR(fail));
546578741aaSmrg#endif
547145b7b3cSmrg}
548145b7b3cSmrg
549145b7b3cSmrgstatic void
550145b7b3cSmrgXorCursor (LoginWidget w)
551145b7b3cSmrg{
552145b7b3cSmrg    realizeCursor (w, w->login.xorGC);
553145b7b3cSmrg}
554145b7b3cSmrg
555145b7b3cSmrgstatic void
556145b7b3cSmrgRemoveFail (LoginWidget w)
557145b7b3cSmrg{
558145b7b3cSmrg    if (w->login.failUp)
559145b7b3cSmrg	EraseFail (w);
560145b7b3cSmrg}
561145b7b3cSmrg
562145b7b3cSmrgstatic void
563145b7b3cSmrgEraseCursor (LoginWidget w)
564145b7b3cSmrg{
565145b7b3cSmrg    realizeCursor (w, w->login.bgGC);
566145b7b3cSmrg}
567145b7b3cSmrg
568145b7b3cSmrg/*ARGSUSED*/
569145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id)
570145b7b3cSmrg{
571145b7b3cSmrg    LoginWidget	w = (LoginWidget)client_data;
572145b7b3cSmrg
573145b7b3cSmrg    Debug ("failTimeout\n");
574145b7b3cSmrg    w->login.interval_id = 0;
575145b7b3cSmrg    EraseFail (w);
576145b7b3cSmrg}
577145b7b3cSmrg
578145b7b3cSmrg_X_INTERNAL
579145b7b3cSmrgvoid
580145b7b3cSmrgDrawFail (Widget ctx)
581145b7b3cSmrg{
582145b7b3cSmrg    LoginWidget	w;
583145b7b3cSmrg
584145b7b3cSmrg    w = (LoginWidget) ctx;
585145b7b3cSmrg    XorCursor (w);
586145b7b3cSmrg    ResetLogin (w);
587145b7b3cSmrg    XorCursor (w);
588145b7b3cSmrg    ErrorMessage(ctx, w->login.failMsg, True);
589145b7b3cSmrg}
590145b7b3cSmrg
591145b7b3cSmrgstatic void
592145b7b3cSmrgRedrawFail (LoginWidget w)
593145b7b3cSmrg{
594145b7b3cSmrg    int x = FAIL_X(w);
595145b7b3cSmrg    int y = FAIL_Y(w);
596145b7b3cSmrg    int maxw = w->core.width - PAD_X(w);
597145b7b3cSmrg
598578741aaSmrg#ifndef USE_XFT
599145b7b3cSmrg    if (w->login.failUp)
600578741aaSmrg#endif
601145b7b3cSmrg    {
602145b7b3cSmrg	Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp);
603145b7b3cSmrg	if (ERROR_W(w, w->login.fail) > maxw) {
604145b7b3cSmrg	    /* Too long to fit on one line, break into multiple lines */
605145b7b3cSmrg	    char *tempCopy = strdup(w->login.fail);
606145b7b3cSmrg	    if (tempCopy != NULL) {
607145b7b3cSmrg		char *start, *next;
608578741aaSmrg		char lastspace = ' ';
609145b7b3cSmrg
610145b7b3cSmrg		y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w));
611578741aaSmrg
612145b7b3cSmrg		for (start = next = tempCopy; start != NULL ; start = next) {
613145b7b3cSmrg		    /* search for longest string broken by whitespace that
614145b7b3cSmrg		       will fit on a single line */
615145b7b3cSmrg		    do {
616145b7b3cSmrg			if (next != start) {
617145b7b3cSmrg			    *next = lastspace;
618145b7b3cSmrg			}
619145b7b3cSmrg			for (next = next + 1;
620145b7b3cSmrg			     (*next != '\0') && !isspace(*next) ; next++)
621145b7b3cSmrg			{
622145b7b3cSmrg			    /* this loop intentionally left blank */
623145b7b3cSmrg			}
624145b7b3cSmrg			if (*next != '\0') {
625145b7b3cSmrg			    lastspace = *next;
626145b7b3cSmrg			    *next = '\0';
627145b7b3cSmrg			} else {
628145b7b3cSmrg			    next = NULL;
629145b7b3cSmrg			}
630145b7b3cSmrg		    } while ((next != NULL) && ERROR_W(w, start) < maxw);
631578741aaSmrg
632145b7b3cSmrg		    x = ERROR_X(w, start);
633145b7b3cSmrg#ifdef USE_XFT
634145b7b3cSmrg		    if (w->login.failUp == 0) {
6355ffd6003Smrg			XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
636145b7b3cSmrg				   ERROR_W(w, start), FAIL_Y_INC(w), False);
637145b7b3cSmrg		    } else
638578741aaSmrg#endif
639145b7b3cSmrg			DRAW_STRING (fail, x, y, start, strlen(start));
640145b7b3cSmrg
641145b7b3cSmrg		    if (next != NULL) {
642145b7b3cSmrg			next++;
643145b7b3cSmrg			y += FAIL_Y_INC(w);
644145b7b3cSmrg		    }
645145b7b3cSmrg		}
646145b7b3cSmrg		free(tempCopy);
647145b7b3cSmrg		return;
648145b7b3cSmrg	    }
649145b7b3cSmrg	    /* if strdup failed, fall through to draw all at once, even
650145b7b3cSmrg	       though we know it can't all fit */
651145b7b3cSmrg	    LogOutOfMem("RedrawFail");
652145b7b3cSmrg	}
653145b7b3cSmrg
654145b7b3cSmrg#ifdef USE_XFT
655145b7b3cSmrg	if (w->login.failUp == 0) {
6565ffd6003Smrg	    XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
657145b7b3cSmrg		       ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False);
658145b7b3cSmrg	} else
659578741aaSmrg#endif
660145b7b3cSmrg	    DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail));
661145b7b3cSmrg    }
662145b7b3cSmrg}
663145b7b3cSmrg
664145b7b3cSmrg_X_INTERNAL
665145b7b3cSmrgvoid
666145b7b3cSmrgErrorMessage(Widget ctx, const char *message, Bool timeout)
667145b7b3cSmrg{
668145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
669145b7b3cSmrg
670145b7b3cSmrg/*  Debug("ErrorMessage: %s\n", message);   */
671145b7b3cSmrg    if (w->login.interval_id != 0) {
672145b7b3cSmrg	XtRemoveTimeOut(w->login.interval_id);
673145b7b3cSmrg	w->login.interval_id = 0;
674145b7b3cSmrg    }
675145b7b3cSmrg    RemoveFail(w);
676145b7b3cSmrg    if (w->login.fail != w->login.failMsg)
677145b7b3cSmrg	free(w->login.fail);
678145b7b3cSmrg    w->login.fail = strdup(message);
679145b7b3cSmrg    if (w->login.fail == NULL)
680145b7b3cSmrg	w->login.fail = (char *) w->login.failMsg;
681145b7b3cSmrg    w->login.failUp = 1;
682145b7b3cSmrg    RedrawFail (w);
683145b7b3cSmrg    if (timeout && (w->login.failTimeout > 0)) {
684145b7b3cSmrg	Debug ("failTimeout: %d\n", w->login.failTimeout);
685145b7b3cSmrg	w->login.interval_id =
686145b7b3cSmrg	    XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w),
687145b7b3cSmrg			    w->login.failTimeout * 1000,
688145b7b3cSmrg			    failTimeout, (XtPointer) w);
689145b7b3cSmrg    }
690145b7b3cSmrg}
691145b7b3cSmrg
692145b7b3cSmrg_X_INTERNAL
693145b7b3cSmrgvoid
694145b7b3cSmrgShowChangePasswdMessage(Widget ctx)
695145b7b3cSmrg{
696145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
697145b7b3cSmrg
698145b7b3cSmrg    ErrorMessage(ctx, w->login.passwdChangeMsg, False);
699145b7b3cSmrg}
700145b7b3cSmrg
701145b7b3cSmrgstatic void
702145b7b3cSmrgdraw_it (LoginWidget w)
703145b7b3cSmrg{
704145b7b3cSmrg    int p;
705145b7b3cSmrg    int i;
706145b7b3cSmrg    int gr_line_x, gr_line_y, gr_line_w;
707145b7b3cSmrg
708145b7b3cSmrg    EraseCursor (w);
709145b7b3cSmrg
7105ffd6003Smrg    /* draw window borders */
711145b7b3cSmrg    for(i=1;i<=(w->login.outframewidth);i++)
712145b7b3cSmrg    {
713145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
714629baa8cSmrg		i-1,i-1,w->core.width-i,i-1);
715145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
716629baa8cSmrg		i-1,i-1,i-1,w->core.height-i);
717145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
718629baa8cSmrg		w->core.width-i,i-1,w->core.width-i,w->core.height-i);
719145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
720629baa8cSmrg		i-1,w->core.height-i,w->core.width-i,w->core.height-i);
721145b7b3cSmrg    }
722578741aaSmrg
723145b7b3cSmrg    /* make separator line */
724026e32a9Smlelstv    gr_line_x = SEP_X(w);
725026e32a9Smlelstv    gr_line_y = SEP_Y(w);
726026e32a9Smlelstv    gr_line_w = SEP_W(w);
727145b7b3cSmrg
728145b7b3cSmrg    for(i=1;i<=(w->login.sepwidth);i++)
729145b7b3cSmrg    {
730145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
731145b7b3cSmrg        gr_line_x,           gr_line_y + i-1,
732145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + i-1);
733145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
734026e32a9Smlelstv        gr_line_x,           gr_line_y + SEP_H(w) -i,
735026e32a9Smlelstv        gr_line_x+gr_line_w, gr_line_y + SEP_H(w) -i);
736145b7b3cSmrg    }
737145b7b3cSmrg
738145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++)
739145b7b3cSmrg    {
740026e32a9Smlelstv	int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth;
741026e32a9Smlelstv	int in_frame_y = VALUE_Y(w,p) - Y_ASCENT(w) - w->login.inframeswidth;
742578741aaSmrg
743026e32a9Smlelstv	int in_width = VALUE_W(w,p) + CURSOR_W + 2 * w->login.inframeswidth;
744026e32a9Smlelstv	int in_height = Y_INC(w) + 2 * w->login.inframeswidth;
745578741aaSmrg
746b7d26471Smrg	GC topLeftGC, botRightGC, inpGC;
747145b7b3cSmrg
748145b7b3cSmrg	if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) ||
749145b7b3cSmrg	    (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) {
750145b7b3cSmrg	    topLeftGC = w->login.shdGC;
751145b7b3cSmrg	    botRightGC = w->login.hiGC;
752b7d26471Smrg	    inpGC = w->login.inpGC;
753145b7b3cSmrg	} else {
754b7d26471Smrg	    topLeftGC = botRightGC = inpGC = w->login.bgGC;
755145b7b3cSmrg	}
756145b7b3cSmrg
7575ffd6003Smrg	/* draw borders of editboxes */
758145b7b3cSmrg	for (i=1; i<=(w->login.inframeswidth); i++)
759145b7b3cSmrg	{
760145b7b3cSmrg	    /* Make top/left sides */
761145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
762145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
763578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1);
764145b7b3cSmrg
765145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
766145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
767578741aaSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i);
768145b7b3cSmrg
769145b7b3cSmrg	    /* Make bottom/right sides */
770145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
771145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1,
772578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
773145b7b3cSmrg
774145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
775145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i,
776145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
777145b7b3cSmrg	}
778b7d26471Smrg	XFillRectangle(XtDisplay (w), XtWindow (w), inpGC,
779b7d26471Smrg	    in_frame_x + w->login.inframeswidth,
780b7d26471Smrg	    in_frame_y + w->login.inframeswidth,
781b7d26471Smrg	    in_width - 2*w->login.inframeswidth,
782b7d26471Smrg	    in_height - 2*w->login.inframeswidth);
783145b7b3cSmrg    }
784145b7b3cSmrg
785145b7b3cSmrg    if (GREETING(w)[0]) {
786145b7b3cSmrg	int gx = GREET_X(w);
787145b7b3cSmrg
788145b7b3cSmrg#ifdef XPM
789145b7b3cSmrg	gx -= ((w->login.logoWidth/2) + w->login.logoPadding);
790578741aaSmrg#endif
791145b7b3cSmrg	DRAW_STRING (greet, gx, GREET_Y(w), GREETING(w), strlen (GREETING(w)));
792145b7b3cSmrg    }
793145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++) {
794145b7b3cSmrg	if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) {
795145b7b3cSmrg	    DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p),
796145b7b3cSmrg			 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p)));
797145b7b3cSmrg	    DrawValue (w, 0, p);
798145b7b3cSmrg	}
799145b7b3cSmrg    }
800145b7b3cSmrg    RedrawFail (w);
801145b7b3cSmrg    XorCursor (w);
8025ffd6003Smrg    XSetInputFocus (XtDisplay (w), XtWindow (w),
8035ffd6003Smrg		    RevertToPointerRoot, CurrentTime);
804145b7b3cSmrg}
805145b7b3cSmrg
806145b7b3cSmrg/* Returns 0 on success, -1 on failure */
807145b7b3cSmrg_X_INTERNAL
808145b7b3cSmrgint
809145b7b3cSmrgSetPrompt (Widget ctx, int promptNum, const char *message,
810145b7b3cSmrg	   loginPromptState state, Boolean minimumTime)
811145b7b3cSmrg{
812145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
813145b7b3cSmrg    char *prompt;
814145b7b3cSmrg    int messageLen, e;
815145b7b3cSmrg    const char *stateNames[4] = {
816145b7b3cSmrg	"LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON",
817145b7b3cSmrg	"LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" };
818145b7b3cSmrg    loginPromptState priorState;
819578741aaSmrg
820145b7b3cSmrg    Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum,
821145b7b3cSmrg	  message ? message : "<NULL>", stateNames[state], state);
822145b7b3cSmrg
823145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
824578741aaSmrg
825145b7b3cSmrg    if (PROMPT_TEXT(w, promptNum) != NULL) {
826145b7b3cSmrg	XtFree(PROMPT_TEXT(w, promptNum));
827145b7b3cSmrg	PROMPT_TEXT(w, promptNum) = NULL;
828145b7b3cSmrg    }
829145b7b3cSmrg
830145b7b3cSmrg    priorState = PROMPT_STATE(w, promptNum);
831145b7b3cSmrg    PROMPT_STATE(w, promptNum) = state;
832145b7b3cSmrg
833145b7b3cSmrg    if (state == LOGIN_PROMPT_NOT_SHOWN) {
834145b7b3cSmrg	return 0;
835145b7b3cSmrg    }
836145b7b3cSmrg
837145b7b3cSmrg    if (message == NULL) {
838145b7b3cSmrg	message = DEF_PROMPT_TEXT(w, promptNum);
839145b7b3cSmrg    }
840145b7b3cSmrg
841145b7b3cSmrg    messageLen = strlen(message);
842578741aaSmrg
843145b7b3cSmrg    prompt = XtMalloc(messageLen + 3);
844145b7b3cSmrg    if (prompt == NULL) {
845145b7b3cSmrg	LogOutOfMem ("SetPrompt");
846145b7b3cSmrg	return -1;
847145b7b3cSmrg    }
848578741aaSmrg
849145b7b3cSmrg    strncpy(prompt, message, messageLen);
850578741aaSmrg
851145b7b3cSmrg    /* Make sure text prompts have at least two spaces at end */
852145b7b3cSmrg    e = messageLen;
853578741aaSmrg
854145b7b3cSmrg    if (!isspace(message[messageLen - 2])) {
855145b7b3cSmrg	prompt[e] = ' ';
856145b7b3cSmrg	e++;
857145b7b3cSmrg    }
858145b7b3cSmrg    if (!isspace(message[messageLen - 1])) {
859145b7b3cSmrg	prompt[e] = ' ';
860145b7b3cSmrg	e++;
861145b7b3cSmrg    }
862145b7b3cSmrg    prompt[e] = '\0';
863145b7b3cSmrg
864145b7b3cSmrg    PROMPT_TEXT(w, promptNum) = prompt;
865145b7b3cSmrg
866145b7b3cSmrg    if (w->login.state == INITIALIZING) {
867145b7b3cSmrg	return 0;
868145b7b3cSmrg    }
869578741aaSmrg
870145b7b3cSmrg    if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) {
871145b7b3cSmrg	time_t now = time(NULL);
872145b7b3cSmrg	int timeleft = w->login.msgTimeout - now;
873578741aaSmrg
874145b7b3cSmrg	if (timeleft > 0) {
875145b7b3cSmrg	    sleep(timeleft);
876145b7b3cSmrg	}
877145b7b3cSmrg	w->login.msgTimeout = 0;
878145b7b3cSmrg    }
879145b7b3cSmrg
880145b7b3cSmrg    if (state == LOGIN_TEXT_INFO) {
881145b7b3cSmrg	if (minimumTime) {
882145b7b3cSmrg	    time_t now = time(NULL);
883145b7b3cSmrg	    w->login.msgTimeout = now + w->login.failTimeout;
884145b7b3cSmrg	}
885145b7b3cSmrg	w->login.state = SHOW_MESSAGE;
886145b7b3cSmrg    } else {
887145b7b3cSmrg	w->login.activePrompt = promptNum;
888145b7b3cSmrg	w->login.state = PROMPTING;
889145b7b3cSmrg    }
890578741aaSmrg
891145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
892145b7b3cSmrg    XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE);
893145b7b3cSmrg    draw_it(w);
894145b7b3cSmrg    return 0;
895145b7b3cSmrg}
896145b7b3cSmrg
897145b7b3cSmrg_X_INTERNAL
898145b7b3cSmrgconst char *
899145b7b3cSmrgGetPrompt(Widget ctx, int promptNum)
900145b7b3cSmrg{
901145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
902145b7b3cSmrg
903145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
904578741aaSmrg
905145b7b3cSmrg    return CUR_PROMPT_TEXT(w,promptNum);
906145b7b3cSmrg}
907145b7b3cSmrg
908145b7b3cSmrg_X_INTERNAL
909145b7b3cSmrgint
910145b7b3cSmrgSetValue(Widget ctx, int promptNum, char *value)
911145b7b3cSmrg{
912145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
913145b7b3cSmrg
914145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
915578741aaSmrg
916145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
917145b7b3cSmrg	return -1;
918145b7b3cSmrg
919145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
920578741aaSmrg
921145b7b3cSmrg    if (VALUE_TEXT(w, promptNum) == NULL)
922145b7b3cSmrg	return -1;
923145b7b3cSmrg
924145b7b3cSmrg    if (value == NULL) {
925145b7b3cSmrg	bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum));
926145b7b3cSmrg    } else {
927145b7b3cSmrg	strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum));
928145b7b3cSmrg	VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0';
929145b7b3cSmrg    }
930145b7b3cSmrg
931145b7b3cSmrg    VALUE_SHOW_START(w, promptNum) = 0;
932145b7b3cSmrg    VALUE_SHOW_END(w, promptNum) = 0;
933145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
934578741aaSmrg
935145b7b3cSmrg    return 0;
936145b7b3cSmrg}
937145b7b3cSmrg
938145b7b3cSmrg_X_INTERNAL
939145b7b3cSmrgconst char *
940145b7b3cSmrgGetValue(Widget ctx, int promptNum)
941145b7b3cSmrg{
942145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
943145b7b3cSmrg
944145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
945578741aaSmrg
946145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
947145b7b3cSmrg	return NULL;
948145b7b3cSmrg
949145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
950145b7b3cSmrg
951145b7b3cSmrg    return VALUE_TEXT(w, promptNum);
952145b7b3cSmrg}
953145b7b3cSmrg
954145b7b3cSmrg
955145b7b3cSmrgstatic void
956145b7b3cSmrgrealizeDeleteChar (LoginWidget ctx)
957145b7b3cSmrg{
958145b7b3cSmrg    if (ctx->login.state == PROMPTING) {
959145b7b3cSmrg	int promptNum = ctx->login.activePrompt;
960145b7b3cSmrg	int redrawFrom = PROMPT_CURSOR(ctx, promptNum);
961578741aaSmrg
962145b7b3cSmrg	if (PROMPT_CURSOR(ctx,promptNum) <  (int)strlen(VALUE_TEXT(ctx,promptNum))) {
963026e32a9Smlelstv	    if (redrawFrom <= VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
964026e32a9Smlelstv		if (redrawFrom > 0)
965026e32a9Smlelstv			redrawFrom--;
966026e32a9Smlelstv		EraseValue (ctx, 0, promptNum);
967026e32a9Smlelstv		VALUE_SHOW_START(ctx, ctx->login.activePrompt) = redrawFrom;
968145b7b3cSmrg	    } else {
969145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
970145b7b3cSmrg	    }
971145b7b3cSmrg	    strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
972145b7b3cSmrg		   VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1);
973145b7b3cSmrg	    DrawValue (ctx, redrawFrom, promptNum);
974145b7b3cSmrg	}
975145b7b3cSmrg    }
976145b7b3cSmrg}
977145b7b3cSmrg
978145b7b3cSmrg/*ARGSUSED*/
979145b7b3cSmrgstatic void
980145b7b3cSmrgDeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
981145b7b3cSmrg{
982145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
983145b7b3cSmrg
984145b7b3cSmrg    RemoveFail (ctx);
985145b7b3cSmrg
986145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
987145b7b3cSmrg	return;
988145b7b3cSmrg    }
989145b7b3cSmrg
990145b7b3cSmrg    XorCursor (ctx);
991145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0) {
992145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
993145b7b3cSmrg	realizeDeleteChar(ctx);
994145b7b3cSmrg    }
995578741aaSmrg    XorCursor (ctx);
996145b7b3cSmrg}
997145b7b3cSmrg
998145b7b3cSmrg/*ARGSUSED*/
999145b7b3cSmrgstatic void
1000145b7b3cSmrgDeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1001145b7b3cSmrg{
1002145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1003145b7b3cSmrg
1004145b7b3cSmrg    RemoveFail (ctx);
1005145b7b3cSmrg
1006145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1007145b7b3cSmrg	return;
1008145b7b3cSmrg    }
1009145b7b3cSmrg
1010145b7b3cSmrg    XorCursor (ctx);
1011145b7b3cSmrg    realizeDeleteChar(ctx);
1012578741aaSmrg    XorCursor (ctx);
1013145b7b3cSmrg}
1014145b7b3cSmrg
1015145b7b3cSmrg/*ARGSUSED*/
1016145b7b3cSmrgstatic void
1017145b7b3cSmrgMoveBackwardChar (
1018145b7b3cSmrg    Widget	ctxw,
1019145b7b3cSmrg    XEvent	*event,
1020145b7b3cSmrg    String	*params,
1021145b7b3cSmrg    Cardinal	*num_params)
1022145b7b3cSmrg{
1023145b7b3cSmrg    LoginWidget	ctx = (LoginWidget)ctxw;
1024145b7b3cSmrg
1025145b7b3cSmrg    RemoveFail (ctx);
1026145b7b3cSmrg
1027145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1028145b7b3cSmrg	return;
1029145b7b3cSmrg    }
1030145b7b3cSmrg
1031145b7b3cSmrg    XorCursor (ctx);
1032145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0)
1033145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
1034145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
1035145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1036145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt)
1037145b7b3cSmrg	    = CUR_PROMPT_CURSOR(ctx);
1038145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1039145b7b3cSmrg    }
1040145b7b3cSmrg    XorCursor (ctx);
1041145b7b3cSmrg}
1042145b7b3cSmrg
1043145b7b3cSmrg/*ARGSUSED*/
1044145b7b3cSmrgstatic void
1045145b7b3cSmrgMoveForwardChar (
1046145b7b3cSmrg    Widget	ctxw,
1047145b7b3cSmrg    XEvent	*event,
1048145b7b3cSmrg    String	*params,
1049145b7b3cSmrg    Cardinal	*num_params)
1050145b7b3cSmrg{
1051145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1052145b7b3cSmrg
1053145b7b3cSmrg    RemoveFail (ctx);
1054145b7b3cSmrg
1055145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1056145b7b3cSmrg	return;
1057145b7b3cSmrg    }
1058145b7b3cSmrg
1059145b7b3cSmrg    XorCursor (ctx);
1060145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) <
1061145b7b3cSmrg	(int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) {
1062145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) += 1;
1063145b7b3cSmrg	if (VALUE_SHOW_END(ctx, ctx->login.activePrompt)
1064145b7b3cSmrg	    < CUR_PROMPT_CURSOR(ctx)) {
1065145b7b3cSmrg	    EraseValue(ctx, 0, ctx->login.activePrompt);
1066145b7b3cSmrg	    DrawValue(ctx, 0, ctx->login.activePrompt);
1067145b7b3cSmrg	}
1068145b7b3cSmrg    }
1069145b7b3cSmrg    XorCursor (ctx);
1070145b7b3cSmrg}
1071145b7b3cSmrg
1072145b7b3cSmrg/*ARGSUSED*/
1073145b7b3cSmrgstatic void
1074145b7b3cSmrgMoveToBegining (
1075145b7b3cSmrg    Widget	ctxw,
1076145b7b3cSmrg    XEvent	*event,
1077145b7b3cSmrg    String	*params,
1078145b7b3cSmrg    Cardinal	*num_params)
1079145b7b3cSmrg{
1080145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1081145b7b3cSmrg
1082145b7b3cSmrg    RemoveFail (ctx);
1083145b7b3cSmrg
1084145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1085145b7b3cSmrg	return;
1086145b7b3cSmrg    }
1087145b7b3cSmrg
1088145b7b3cSmrg    XorCursor (ctx);
1089145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = 0;
1090145b7b3cSmrg    if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) {
1091145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1092145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0;
1093145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1094145b7b3cSmrg    }
1095145b7b3cSmrg    XorCursor (ctx);
1096145b7b3cSmrg}
1097145b7b3cSmrg
1098145b7b3cSmrg/*ARGSUSED*/
1099145b7b3cSmrgstatic void
1100145b7b3cSmrgMoveToEnd (
1101145b7b3cSmrg    Widget	ctxw,
1102145b7b3cSmrg    XEvent	*event,
1103145b7b3cSmrg    String	*params,
1104145b7b3cSmrg    Cardinal	*num_params)
1105145b7b3cSmrg{
1106145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1107145b7b3cSmrg
1108145b7b3cSmrg    RemoveFail (ctx);
1109145b7b3cSmrg
1110145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1111145b7b3cSmrg	return;
1112145b7b3cSmrg    }
1113145b7b3cSmrg
1114145b7b3cSmrg    XorCursor (ctx);
1115145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt));
1116145b7b3cSmrg    if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) {
1117145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1118145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1119145b7b3cSmrg    }
1120145b7b3cSmrg    XorCursor (ctx);
1121145b7b3cSmrg}
1122145b7b3cSmrg
1123145b7b3cSmrg/*ARGSUSED*/
1124145b7b3cSmrgstatic void
1125145b7b3cSmrgEraseToEndOfLine (
1126145b7b3cSmrg    Widget	ctxw,
1127145b7b3cSmrg    XEvent	*event,
1128145b7b3cSmrg    String	*params,
1129145b7b3cSmrg    Cardinal	*num_params)
1130145b7b3cSmrg{
1131145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1132145b7b3cSmrg
1133145b7b3cSmrg    RemoveFail (ctx);
1134145b7b3cSmrg
1135145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1136145b7b3cSmrg	return;
1137145b7b3cSmrg    }
1138145b7b3cSmrg
1139145b7b3cSmrg    XorCursor (ctx);
1140145b7b3cSmrg    EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt);
1141145b7b3cSmrg    bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) +
1142145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx),
1143145b7b3cSmrg	  VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) -
1144145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx));
1145145b7b3cSmrg    XorCursor (ctx);
1146145b7b3cSmrg}
1147145b7b3cSmrg
1148145b7b3cSmrg/*ARGSUSED*/
1149145b7b3cSmrgstatic void
1150145b7b3cSmrgEraseLine (
1151145b7b3cSmrg    Widget	ctxw,
1152145b7b3cSmrg    XEvent	*event,
1153145b7b3cSmrg    String	*params,
1154145b7b3cSmrg    Cardinal	*num_params)
1155145b7b3cSmrg{
1156145b7b3cSmrg    MoveToBegining (ctxw, event, params, num_params);
1157145b7b3cSmrg    EraseToEndOfLine (ctxw, event, params, num_params);
1158145b7b3cSmrg}
1159145b7b3cSmrg
1160145b7b3cSmrg/*ARGSUSED*/
1161145b7b3cSmrgstatic void
1162145b7b3cSmrgFinishField (
1163145b7b3cSmrg    Widget	ctxw,
1164145b7b3cSmrg    XEvent	*event,
1165145b7b3cSmrg    String	*params,
1166145b7b3cSmrg    Cardinal	*num_params)
1167145b7b3cSmrg{
1168145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1169145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1170145b7b3cSmrg    int nextPrompt;
1171145b7b3cSmrg
1172145b7b3cSmrg    RemoveFail (ctx);
1173145b7b3cSmrg
1174145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1175145b7b3cSmrg	return;
1176145b7b3cSmrg    }
1177145b7b3cSmrg
1178145b7b3cSmrg    XorCursor (ctx);
1179145b7b3cSmrg
1180145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) {
1181145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1182145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1183145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1184145b7b3cSmrg	    break;
1185145b7b3cSmrg	}
1186145b7b3cSmrg    }
1187145b7b3cSmrg    if (nextPrompt > LAST_PROMPT) {
1188145b7b3cSmrg	ctx->login.state = DONE;
1189145b7b3cSmrg	(*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
1190145b7b3cSmrg	Debug("FinishField #%d: now DONE\n", promptNum);
1191145b7b3cSmrg    } else {
1192145b7b3cSmrg	Debug("FinishField #%d: %d next\n", promptNum, nextPrompt);
1193145b7b3cSmrg    }
1194145b7b3cSmrg
1195145b7b3cSmrg    XorCursor (ctx);
1196145b7b3cSmrg}
1197145b7b3cSmrg
1198145b7b3cSmrg/*ARGSUSED*/
1199145b7b3cSmrgstatic void
1200145b7b3cSmrgTabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1201145b7b3cSmrg{
1202145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1203145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1204145b7b3cSmrg    int nextPrompt;
1205145b7b3cSmrg
1206145b7b3cSmrg    RemoveFail (ctx);
1207145b7b3cSmrg
1208145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1209145b7b3cSmrg	return;
1210145b7b3cSmrg    }
1211145b7b3cSmrg
1212145b7b3cSmrg    XorCursor (ctx);
1213145b7b3cSmrg
1214145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) {
1215145b7b3cSmrg	if (nextPrompt > LAST_PROMPT) {
1216145b7b3cSmrg	    nextPrompt = 0;
1217145b7b3cSmrg	}
1218578741aaSmrg
1219145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1220145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1221145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1222145b7b3cSmrg	    break;
1223145b7b3cSmrg	}
1224145b7b3cSmrg    }
1225145b7b3cSmrg    XorCursor (ctx);
1226145b7b3cSmrg}
1227145b7b3cSmrg
1228145b7b3cSmrg/*ARGSUSED*/
1229145b7b3cSmrgstatic void
1230145b7b3cSmrgAllowAccess (
1231145b7b3cSmrg    Widget	ctxw,
1232145b7b3cSmrg    XEvent	*event,
1233145b7b3cSmrg    String	*params,
1234145b7b3cSmrg    Cardinal	*num_params)
1235145b7b3cSmrg{
1236145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1237145b7b3cSmrg    Arg	arglist[1];
1238145b7b3cSmrg    Boolean allow;
1239145b7b3cSmrg
1240145b7b3cSmrg    RemoveFail (ctx);
1241145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
1242145b7b3cSmrg    XtGetValues ((Widget) ctx, arglist, 1);
1243145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, !allow);
1244145b7b3cSmrg    XtSetValues ((Widget) ctx, arglist, 1);
1245145b7b3cSmrg}
1246145b7b3cSmrg
1247145b7b3cSmrg/*ARGSUSED*/
1248145b7b3cSmrgstatic void
1249145b7b3cSmrgSetSessionArgument (
1250145b7b3cSmrg    Widget	ctxw,
1251145b7b3cSmrg    XEvent	*event,
1252145b7b3cSmrg    String	*params,
1253145b7b3cSmrg    Cardinal	*num_params)
1254145b7b3cSmrg{
1255145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1256145b7b3cSmrg
1257145b7b3cSmrg    RemoveFail (ctx);
1258145b7b3cSmrg    if (ctx->login.sessionArg)
1259145b7b3cSmrg	XtFree (ctx->login.sessionArg);
1260145b7b3cSmrg    ctx->login.sessionArg = NULL;
1261145b7b3cSmrg    if (*num_params > 0) {
1262145b7b3cSmrg	ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
1263145b7b3cSmrg	if (ctx->login.sessionArg)
1264145b7b3cSmrg	    strcpy (ctx->login.sessionArg, params[0]);
1265145b7b3cSmrg	else
1266145b7b3cSmrg	    LogOutOfMem ("set session argument");
1267145b7b3cSmrg    }
1268145b7b3cSmrg}
1269145b7b3cSmrg
1270145b7b3cSmrg/*ARGSUSED*/
1271145b7b3cSmrgstatic void
1272145b7b3cSmrgRestartSession (
1273145b7b3cSmrg    Widget	ctxw,
1274145b7b3cSmrg    XEvent	*event,
1275145b7b3cSmrg    String	*params,
1276145b7b3cSmrg    Cardinal	*num_params)
1277145b7b3cSmrg{
1278145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1279145b7b3cSmrg
1280145b7b3cSmrg    XorCursor (ctx);
1281145b7b3cSmrg    RemoveFail (ctx);
1282145b7b3cSmrg    ctx->login.state = DONE;
1283145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
1284145b7b3cSmrg    XorCursor (ctx);
1285145b7b3cSmrg}
1286145b7b3cSmrg
1287145b7b3cSmrg/*ARGSUSED*/
1288145b7b3cSmrgstatic void
1289145b7b3cSmrgAbortSession (
1290145b7b3cSmrg    Widget	ctxw,
1291145b7b3cSmrg    XEvent	*event,
1292145b7b3cSmrg    String	*params,
1293145b7b3cSmrg    Cardinal	*num_params)
1294145b7b3cSmrg{
1295145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1296145b7b3cSmrg
1297145b7b3cSmrg    XorCursor (ctx);
1298145b7b3cSmrg    RemoveFail (ctx);
1299145b7b3cSmrg    ctx->login.state = DONE;
1300145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
1301145b7b3cSmrg    XorCursor (ctx);
1302145b7b3cSmrg}
1303145b7b3cSmrg
1304145b7b3cSmrg/*ARGSUSED*/
1305145b7b3cSmrgstatic void
1306145b7b3cSmrgAbortDisplay (
1307145b7b3cSmrg    Widget	ctxw,
1308145b7b3cSmrg    XEvent	*event,
1309145b7b3cSmrg    String	*params,
1310145b7b3cSmrg    Cardinal	*num_params)
1311145b7b3cSmrg{
1312145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1313145b7b3cSmrg
1314145b7b3cSmrg    XorCursor (ctx);
1315145b7b3cSmrg    RemoveFail (ctx);
1316145b7b3cSmrg    ctx->login.state = DONE;
1317145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
1318145b7b3cSmrg    XorCursor (ctx);
1319145b7b3cSmrg}
1320145b7b3cSmrg
1321145b7b3cSmrgstatic void
1322145b7b3cSmrgResetLogin (LoginWidget w)
1323145b7b3cSmrg{
1324145b7b3cSmrg    int i;
1325145b7b3cSmrg
1326145b7b3cSmrg    for (i = 0; i < NUM_PROMPTS ; i++) {
1327145b7b3cSmrg	EraseValue(w, 0, i);
1328145b7b3cSmrg	bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i));
1329145b7b3cSmrg	VALUE_SHOW_START(w, i) = 0;
1330145b7b3cSmrg	PROMPT_CURSOR(w, i) = 0;
1331145b7b3cSmrg    }
1332145b7b3cSmrg    w->login.state = PROMPTING;
1333145b7b3cSmrg    w->login.activePrompt = 0;
1334145b7b3cSmrg}
1335145b7b3cSmrg
1336145b7b3cSmrgstatic void
1337145b7b3cSmrgInitI18N(Widget ctxw)
1338145b7b3cSmrg{
1339145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1340145b7b3cSmrg    XIM         xim = (XIM) NULL;
1341145b7b3cSmrg    char *p;
1342145b7b3cSmrg
1343145b7b3cSmrg    ctx->login.xic = (XIC) NULL;
1344145b7b3cSmrg
1345145b7b3cSmrg    if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
1346145b7b3cSmrg	xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL);
1347145b7b3cSmrg
1348145b7b3cSmrg    if (!xim) {
1349145b7b3cSmrg	LogError("Failed to open input method\n");
1350145b7b3cSmrg	return;
1351145b7b3cSmrg    }
1352145b7b3cSmrg
1353145b7b3cSmrg    ctx->login.xic = XCreateIC(xim,
1354145b7b3cSmrg	XNInputStyle, (XIMPreeditNothing|XIMStatusNothing),
1355145b7b3cSmrg	XNClientWindow, ctx->core.window,
1356145b7b3cSmrg	XNFocusWindow,  ctx->core.window, NULL);
1357145b7b3cSmrg
1358145b7b3cSmrg    if (!ctx->login.xic) {
1359145b7b3cSmrg	LogError("Failed to create input context\n");
1360145b7b3cSmrg	XCloseIM(xim);
1361145b7b3cSmrg    }
1362145b7b3cSmrg    return;
1363145b7b3cSmrg}
1364145b7b3cSmrg
1365145b7b3cSmrg/* ARGSUSED */
1366145b7b3cSmrgstatic void
1367145b7b3cSmrgInsertChar (
1368145b7b3cSmrg    Widget	ctxw,
1369145b7b3cSmrg    XEvent	*event,
1370145b7b3cSmrg    String	*params,
1371145b7b3cSmrg    Cardinal	*num_params)
1372145b7b3cSmrg{
1373145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1374145b7b3cSmrg
1375145b7b3cSmrg    char strbuf[128];
1376145b7b3cSmrg    int  len, promptNum = ctx->login.activePrompt;
1377145b7b3cSmrg    KeySym  keysym = 0;
1378145b7b3cSmrg
1379145b7b3cSmrg    if (ctx->login.xic) {
1380145b7b3cSmrg	static Status status;
1381145b7b3cSmrg	len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf,
1382145b7b3cSmrg			      sizeof (strbuf), &keysym, &status);
1383145b7b3cSmrg    } else {
1384145b7b3cSmrg	static XComposeStatus compose_status = {NULL, 0};
1385145b7b3cSmrg	len = XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1386145b7b3cSmrg			     &keysym, &compose_status);
1387145b7b3cSmrg    }
1388145b7b3cSmrg    strbuf[len] = '\0';
1389145b7b3cSmrg
1390145b7b3cSmrg    /*
1391145b7b3cSmrg     * Note: You can override this default key handling
1392145b7b3cSmrg     * by the settings in the translation table
1393145b7b3cSmrg     * loginActionsTable at the end of this file.
1394145b7b3cSmrg     */
1395145b7b3cSmrg    switch (keysym) {
1396145b7b3cSmrg    case XK_Return:
1397145b7b3cSmrg    case XK_KP_Enter:
1398145b7b3cSmrg    case XK_Linefeed:
1399145b7b3cSmrg    case XK_Execute:
1400145b7b3cSmrg	FinishField(ctxw, event, params, num_params);
1401145b7b3cSmrg	return;
1402145b7b3cSmrg    case XK_BackSpace:
1403145b7b3cSmrg	DeleteBackwardChar(ctxw, event, params, num_params);
1404145b7b3cSmrg	return;
1405145b7b3cSmrg    case XK_Delete:
1406145b7b3cSmrg    case XK_KP_Delete:
1407145b7b3cSmrg    case DXK_Remove:
1408145b7b3cSmrg	/* Sorry, it's not a telex machine, it's a terminal */
1409145b7b3cSmrg	DeleteForwardChar(ctxw, event, params, num_params);
1410145b7b3cSmrg	return;
1411145b7b3cSmrg    case XK_Left:
1412145b7b3cSmrg    case XK_KP_Left:
1413145b7b3cSmrg	MoveBackwardChar(ctxw, event, params, num_params);
1414145b7b3cSmrg	return;
1415145b7b3cSmrg    case XK_Right:
1416145b7b3cSmrg    case XK_KP_Right:
1417145b7b3cSmrg	MoveForwardChar(ctxw, event, params, num_params);
1418145b7b3cSmrg	return;
1419145b7b3cSmrg    case XK_End:
1420145b7b3cSmrg    case XK_KP_End:
1421145b7b3cSmrg	MoveToEnd(ctxw, event, params, num_params);
1422145b7b3cSmrg	return;
1423145b7b3cSmrg    case XK_Home:
1424145b7b3cSmrg    case XK_KP_Home:
1425145b7b3cSmrg	MoveToBegining(ctxw, event, params, num_params);
1426145b7b3cSmrg	return;
1427145b7b3cSmrg    default:
1428145b7b3cSmrg	if (len == 0) {
1429145b7b3cSmrg	    if (!IsModifierKey(keysym))  /* it's not a modifier */
1430145b7b3cSmrg		XBell(XtDisplay(ctxw), 60);
1431145b7b3cSmrg	    return;
1432145b7b3cSmrg	} else
1433145b7b3cSmrg	    break;
1434145b7b3cSmrg    }
1435145b7b3cSmrg
1436578741aaSmrg    if (ctx->login.state == PROMPTING) {
1437145b7b3cSmrg	if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >=
1438145b7b3cSmrg	     (VALUE_TEXT_MAX(ctx,promptNum) - 1))) {
1439145b7b3cSmrg	    len = VALUE_TEXT_MAX(ctx,promptNum) -
1440145b7b3cSmrg		strlen(VALUE_TEXT(ctx, promptNum)) - 2;
1441145b7b3cSmrg	}
1442145b7b3cSmrg    }
1443145b7b3cSmrg    EraseCursor (ctx);
1444145b7b3cSmrg    RemoveFail (ctx);
1445145b7b3cSmrg    if (len != 0)
1446145b7b3cSmrg    {
1447145b7b3cSmrg	if (ctx->login.state == PROMPTING) {
1448145b7b3cSmrg	    EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1449145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len,
1450145b7b3cSmrg		    VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1451145b7b3cSmrg		    strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1);
1452145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1453145b7b3cSmrg		     strbuf, len);
1454145b7b3cSmrg	    DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1455145b7b3cSmrg	    PROMPT_CURSOR(ctx, promptNum) += len;
1456145b7b3cSmrg	}
1457145b7b3cSmrg    }
1458145b7b3cSmrg    XorCursor (ctx);
1459145b7b3cSmrg}
1460145b7b3cSmrg
1461145b7b3cSmrg
1462145b7b3cSmrg/**** Copied from xclock.c - original author: Keith Packard ****/
1463145b7b3cSmrg#ifdef USE_XFT
1464145b7b3cSmrgstatic XtConvertArgRec xftColorConvertArgs[] = {
1465145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1466145b7b3cSmrg     sizeof(Screen *)},
1467145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
1468145b7b3cSmrg     sizeof(Colormap)}
1469145b7b3cSmrg};
1470145b7b3cSmrg
1471578741aaSmrg# define	donestr(type, value, tstr) \
1472145b7b3cSmrg	{							\
1473145b7b3cSmrg	    if (toVal->addr != NULL) {				\
1474145b7b3cSmrg		if (toVal->size < sizeof(type)) {		\
1475145b7b3cSmrg		    toVal->size = sizeof(type);			\
1476145b7b3cSmrg		    XtDisplayStringConversionWarning(dpy, 	\
1477145b7b3cSmrg			(char*) fromVal->addr, tstr);		\
1478145b7b3cSmrg		    return False;				\
1479145b7b3cSmrg		}						\
1480145b7b3cSmrg		*(type*)(toVal->addr) = (value);		\
1481145b7b3cSmrg	    }							\
1482145b7b3cSmrg	    else {						\
1483145b7b3cSmrg		static type static_val;				\
1484145b7b3cSmrg		static_val = (value);				\
1485145b7b3cSmrg		toVal->addr = (XPointer)&static_val;		\
1486145b7b3cSmrg	    }							\
1487145b7b3cSmrg	    toVal->size = sizeof(type);				\
1488145b7b3cSmrg	    return True;					\
1489145b7b3cSmrg	}
1490145b7b3cSmrg
1491145b7b3cSmrgstatic void
1492145b7b3cSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1493145b7b3cSmrg		 XrmValuePtr args, Cardinal *num_args)
1494145b7b3cSmrg{
1495145b7b3cSmrg    Screen	*screen;
1496145b7b3cSmrg    Colormap	colormap;
1497145b7b3cSmrg    XftColor	*color;
1498578741aaSmrg
1499145b7b3cSmrg    if (*num_args != 2)
1500145b7b3cSmrg    {
1501145b7b3cSmrg	XtAppErrorMsg (app,
1502145b7b3cSmrg		       "freeXftColor", "wrongParameters",
1503145b7b3cSmrg		       "XtToolkitError",
1504145b7b3cSmrg		       "Freeing an XftColor requires screen and colormap arguments",
1505145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1506145b7b3cSmrg	return;
1507145b7b3cSmrg    }
1508145b7b3cSmrg
1509145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1510145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1511145b7b3cSmrg    color = (XftColor *) toVal->addr;
1512145b7b3cSmrg    XftColorFree (DisplayOfScreen (screen),
1513145b7b3cSmrg		  DefaultVisual (DisplayOfScreen (screen),
1514145b7b3cSmrg				 XScreenNumberOfScreen (screen)),
1515145b7b3cSmrg		  colormap, color);
1516145b7b3cSmrg}
1517578741aaSmrg
1518145b7b3cSmrgstatic Boolean
1519145b7b3cSmrgXmuCvtStringToXftColor(Display *dpy,
1520145b7b3cSmrg		       XrmValue *args, Cardinal *num_args,
1521145b7b3cSmrg		       XrmValue *fromVal, XrmValue *toVal,
1522145b7b3cSmrg		       XtPointer *converter_data)
1523145b7b3cSmrg{
1524145b7b3cSmrg    char	    *spec;
1525145b7b3cSmrg    XRenderColor    renderColor;
1526145b7b3cSmrg    XftColor	    xftColor;
1527145b7b3cSmrg    Screen	    *screen;
1528145b7b3cSmrg    Colormap	    colormap;
1529578741aaSmrg
1530145b7b3cSmrg    if (*num_args != 2)
1531145b7b3cSmrg    {
1532145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1533145b7b3cSmrg		       "cvtStringToXftColor", "wrongParameters",
1534145b7b3cSmrg		       "XtToolkitError",
1535145b7b3cSmrg		       "String to render color conversion needs screen and colormap arguments",
1536145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1537145b7b3cSmrg	return False;
1538145b7b3cSmrg    }
1539145b7b3cSmrg
1540145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1541145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1542145b7b3cSmrg
1543145b7b3cSmrg    spec = (char *) fromVal->addr;
1544145b7b3cSmrg    if (strcasecmp (spec, XtDefaultForeground) == 0)
1545145b7b3cSmrg    {
1546145b7b3cSmrg	renderColor.red = 0;
1547145b7b3cSmrg	renderColor.green = 0;
1548145b7b3cSmrg	renderColor.blue = 0;
1549145b7b3cSmrg	renderColor.alpha = 0xffff;
1550145b7b3cSmrg    }
1551145b7b3cSmrg    else if (strcasecmp (spec, XtDefaultBackground) == 0)
1552145b7b3cSmrg    {
1553145b7b3cSmrg	renderColor.red = 0xffff;
1554145b7b3cSmrg	renderColor.green = 0xffff;
1555145b7b3cSmrg	renderColor.blue = 0xffff;
1556145b7b3cSmrg	renderColor.alpha = 0xffff;
1557145b7b3cSmrg    }
1558145b7b3cSmrg    else if (!XRenderParseColor (dpy, spec, &renderColor))
1559145b7b3cSmrg	return False;
1560578741aaSmrg    if (!XftColorAllocValue (dpy,
1561145b7b3cSmrg			     DefaultVisual (dpy,
1562145b7b3cSmrg					    XScreenNumberOfScreen (screen)),
1563145b7b3cSmrg			     colormap,
1564145b7b3cSmrg			     &renderColor,
1565145b7b3cSmrg			     &xftColor))
1566145b7b3cSmrg	return False;
1567578741aaSmrg
1568145b7b3cSmrg    donestr (XftColor, xftColor, XtRXftColor);
1569145b7b3cSmrg}
1570145b7b3cSmrg
1571145b7b3cSmrgstatic void
1572145b7b3cSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1573145b7b3cSmrg		XrmValuePtr args, Cardinal *num_args)
1574145b7b3cSmrg{
1575145b7b3cSmrg    Screen  *screen;
1576145b7b3cSmrg    XftFont *font;
1577578741aaSmrg
1578145b7b3cSmrg    if (*num_args != 1)
1579145b7b3cSmrg    {
1580145b7b3cSmrg	XtAppErrorMsg (app,
1581145b7b3cSmrg		       "freeXftFont", "wrongParameters",
1582145b7b3cSmrg		       "XtToolkitError",
1583145b7b3cSmrg		       "Freeing an XftFont requires screen argument",
1584145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1585145b7b3cSmrg	return;
1586145b7b3cSmrg    }
1587145b7b3cSmrg
1588145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1589145b7b3cSmrg    font = *((XftFont **) toVal->addr);
1590145b7b3cSmrg    if (font)
1591145b7b3cSmrg	XftFontClose (DisplayOfScreen (screen), font);
1592145b7b3cSmrg}
1593145b7b3cSmrg
1594145b7b3cSmrgstatic Boolean
1595145b7b3cSmrgXmuCvtStringToXftFont(Display *dpy,
1596145b7b3cSmrg		      XrmValue *args, Cardinal *num_args,
1597145b7b3cSmrg		      XrmValue *fromVal, XrmValue *toVal,
1598145b7b3cSmrg		      XtPointer *converter_data)
1599145b7b3cSmrg{
1600145b7b3cSmrg    char    *name;
1601145b7b3cSmrg    XftFont *font;
1602145b7b3cSmrg    Screen  *screen;
1603578741aaSmrg
1604145b7b3cSmrg    if (*num_args != 1)
1605145b7b3cSmrg    {
1606145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1607145b7b3cSmrg		       "cvtStringToXftFont", "wrongParameters",
1608145b7b3cSmrg		       "XtToolkitError",
1609145b7b3cSmrg		       "String to XftFont conversion needs screen argument",
1610145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1611145b7b3cSmrg	return False;
1612145b7b3cSmrg    }
1613145b7b3cSmrg
1614145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1615145b7b3cSmrg    name = (char *) fromVal->addr;
1616578741aaSmrg
1617145b7b3cSmrg    font = XftFontOpenName (dpy,
1618145b7b3cSmrg			    XScreenNumberOfScreen (screen),
1619145b7b3cSmrg			    name);
1620145b7b3cSmrg    if (font)
1621145b7b3cSmrg    {
1622145b7b3cSmrg	donestr (XftFont *, font, XtRXftFont);
1623145b7b3cSmrg    }
1624145b7b3cSmrg    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
1625145b7b3cSmrg    return False;
1626145b7b3cSmrg}
1627145b7b3cSmrg
1628145b7b3cSmrgstatic XtConvertArgRec xftFontConvertArgs[] = {
1629145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1630145b7b3cSmrg     sizeof(Screen *)},
1631145b7b3cSmrg};
1632145b7b3cSmrg
1633145b7b3cSmrg
1634145b7b3cSmrgstatic int
1635145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len)
1636145b7b3cSmrg{
1637145b7b3cSmrg    XGlyphInfo  extents;
1638145b7b3cSmrg
1639145b7b3cSmrg    XftTextExtents8 (dpy, font, string, len, &extents);
1640145b7b3cSmrg
1641145b7b3cSmrg    return extents.xOff;
1642145b7b3cSmrg}
1643145b7b3cSmrg
1644145b7b3cSmrg#endif /* USE_XFT */
1645145b7b3cSmrg
1646578741aaSmrgstatic void
1647145b7b3cSmrgClassInitialize(void)
1648145b7b3cSmrg{
1649145b7b3cSmrg#ifdef USE_XFT
1650578741aaSmrg    XtSetTypeConverter (XtRString, XtRXftColor,
1651578741aaSmrg			XmuCvtStringToXftColor,
1652145b7b3cSmrg			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
1653145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftColor);
1654145b7b3cSmrg    XtSetTypeConverter (XtRString, XtRXftFont,
1655145b7b3cSmrg			XmuCvtStringToXftFont,
1656145b7b3cSmrg			xftFontConvertArgs, XtNumber(xftFontConvertArgs),
1657145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftFont);
1658145b7b3cSmrg#endif /* USE_XFT */
1659145b7b3cSmrg}
1660145b7b3cSmrg/**** End of portion borrowed from xclock ****/
1661145b7b3cSmrg
1662145b7b3cSmrg/* ARGSUSED */
1663145b7b3cSmrgstatic void Initialize (
1664145b7b3cSmrg    Widget greq,
1665145b7b3cSmrg    Widget gnew,
1666145b7b3cSmrg    ArgList args,
1667145b7b3cSmrg    Cardinal *num_args)
1668145b7b3cSmrg{
1669145b7b3cSmrg    LoginWidget w = (LoginWidget)gnew;
1670145b7b3cSmrg    XtGCMask	valuemask, xvaluemask;
1671145b7b3cSmrg    XGCValues	myXGCV;
1672145b7b3cSmrg    Arg		position[2];
1673145b7b3cSmrg    Position	x, y;
1674145b7b3cSmrg#ifdef USE_XINERAMA
1675145b7b3cSmrg    XineramaScreenInfo *screens;
1676145b7b3cSmrg    int                 s_num;
1677145b7b3cSmrg#endif
1678145b7b3cSmrg    int 	rv = 0;
1679578741aaSmrg
1680145b7b3cSmrg    myXGCV.foreground = w->login.hipixel;
1681145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1682145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1683145b7b3cSmrg    w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV);
1684145b7b3cSmrg
1685145b7b3cSmrg    myXGCV.foreground = w->login.shdpixel;
1686145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1687145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1688145b7b3cSmrg    w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV);
1689145b7b3cSmrg
1690b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1691b7d26471Smrg    myXGCV.background = w->core.background_pixel;
1692b7d26471Smrg    valuemask = GCForeground | GCBackground;
1693b7d26471Smrg    w->login.inpGC = XtGetGC(gnew, valuemask, &myXGCV);
1694b7d26471Smrg
1695145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text);
1696145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1697145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1698145b7b3cSmrg#ifndef USE_XFT
1699145b7b3cSmrg    if (w->login.textFont) {
1700145b7b3cSmrg	myXGCV.font = w->login.textFont->fid;
1701145b7b3cSmrg	valuemask |= GCFont;
1702145b7b3cSmrg    }
1703578741aaSmrg#endif
1704145b7b3cSmrg    w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
1705b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1706145b7b3cSmrg    w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
1707145b7b3cSmrg
1708b7d26471Smrg    myXGCV.foreground = TEXT_COLOR(text) ^ w->login.inppixel;
1709145b7b3cSmrg    myXGCV.function = GXxor;
1710145b7b3cSmrg    xvaluemask = valuemask | GCFunction;
1711145b7b3cSmrg    w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1712145b7b3cSmrg
1713145b7b3cSmrg#ifndef USE_XFT
1714145b7b3cSmrg    /*
1715145b7b3cSmrg     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
1716145b7b3cSmrg     * returns the curently contained font.
1717145b7b3cSmrg     */
1718145b7b3cSmrg
1719145b7b3cSmrg    if (w->login.textFont == NULL)
1720145b7b3cSmrg	w->login.textFont = XQueryFont (XtDisplay (w),
1721145b7b3cSmrg		XGContextFromGC (XDefaultGCOfScreen (XtScreen (w))));
1722145b7b3cSmrg
1723145b7b3cSmrg    xvaluemask = valuemask;
1724145b7b3cSmrg    if (w->login.promptFont == NULL)
1725145b7b3cSmrg        w->login.promptFont = w->login.textFont;
1726145b7b3cSmrg    else
1727145b7b3cSmrg	xvaluemask |= GCFont;
1728145b7b3cSmrg
1729145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(prompt);
1730145b7b3cSmrg    myXGCV.font = w->login.promptFont->fid;
1731145b7b3cSmrg    w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1732145b7b3cSmrg
1733145b7b3cSmrg    xvaluemask = valuemask;
1734145b7b3cSmrg    if (w->login.greetFont == NULL)
1735629baa8cSmrg	w->login.greetFont = w->login.textFont;
1736145b7b3cSmrg    else
1737145b7b3cSmrg	xvaluemask |= GCFont;
1738145b7b3cSmrg
1739145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(greet);
1740145b7b3cSmrg    myXGCV.font = w->login.greetFont->fid;
1741145b7b3cSmrg    w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1742145b7b3cSmrg
1743145b7b3cSmrg    xvaluemask = valuemask;
1744145b7b3cSmrg    if (w->login.failFont == NULL)
1745145b7b3cSmrg	w->login.failFont = w->login.textFont;
1746145b7b3cSmrg    else
1747145b7b3cSmrg	xvaluemask |= GCFont;
1748145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(fail);
1749145b7b3cSmrg    myXGCV.font = w->login.failFont->fid;
1750145b7b3cSmrg    w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1751145b7b3cSmrg#endif /* USE_XFT */
1752145b7b3cSmrg
1753145b7b3cSmrg#ifdef XPM
1754145b7b3cSmrg    w->login.logoValid = False;
1755145b7b3cSmrg
1756145b7b3cSmrg    if (NULL != w->login.logoFileName)
1757145b7b3cSmrg    {
1758145b7b3cSmrg        XpmAttributes myAttributes = { 0 };
1759145b7b3cSmrg        Window tmpWindow = { 0 };
1760145b7b3cSmrg        struct stat myBuffer = { 0 };
1761145b7b3cSmrg        unsigned int myPixmapDepth = 0;
1762145b7b3cSmrg
1763145b7b3cSmrg        if (0 != stat(w->login.logoFileName, &myBuffer))
1764145b7b3cSmrg        {
1765145b7b3cSmrg            LogError("Unable to stat() pixmap file %s\n",
1766145b7b3cSmrg                w->login.logoFileName);
1767145b7b3cSmrg            w->login.logoValid = False;
1768145b7b3cSmrg            goto SkipXpmLoad;
1769145b7b3cSmrg        }
1770145b7b3cSmrg
1771145b7b3cSmrg        myAttributes.valuemask |= XpmReturnPixels;
1772145b7b3cSmrg        myAttributes.valuemask |= XpmReturnExtensions;
1773145b7b3cSmrg
1774145b7b3cSmrg        rv = XpmReadFileToPixmap(XtDisplay(w),		/* display */
1775145b7b3cSmrg	     RootWindowOfScreen(XtScreen(w)),		/* window */
1776145b7b3cSmrg	     w->login.logoFileName,			/* XPM filename */
1777145b7b3cSmrg	     &(w->login.logoPixmap),			/* pixmap */
1778145b7b3cSmrg	     &(w->login.logoMask),			/* pixmap mask */
1779145b7b3cSmrg	     &myAttributes);				/* XPM attributes */
1780578741aaSmrg
1781145b7b3cSmrg	if ( rv < 0 )
1782145b7b3cSmrg	{
1783145b7b3cSmrg	    LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName,
1784145b7b3cSmrg		     XpmGetErrorString(rv));
1785145b7b3cSmrg	    goto SkipXpmLoad;
1786145b7b3cSmrg	}
1787145b7b3cSmrg
1788145b7b3cSmrg	w->login.logoValid = True;
1789145b7b3cSmrg
1790145b7b3cSmrg        XGetGeometry(XtDisplay(w), w->login.logoPixmap,
1791145b7b3cSmrg            &tmpWindow,
1792145b7b3cSmrg            &(w->login.logoX),
1793145b7b3cSmrg            &(w->login.logoY),
1794145b7b3cSmrg            &(w->login.logoWidth),
1795145b7b3cSmrg            &(w->login.logoHeight),
1796145b7b3cSmrg            &(w->login.logoBorderWidth),
1797145b7b3cSmrg            &myPixmapDepth);
1798145b7b3cSmrg    } else {
1799145b7b3cSmrg	w->login.logoX = 0;
1800145b7b3cSmrg	w->login.logoY = 0;
1801145b7b3cSmrg	w->login.logoWidth = 0;
1802145b7b3cSmrg	w->login.logoHeight = 0;
1803145b7b3cSmrg	w->login.logoBorderWidth = 0;
1804145b7b3cSmrg    }
1805145b7b3cSmrg
1806145b7b3cSmrg
1807145b7b3cSmrgSkipXpmLoad:
1808145b7b3cSmrg#endif /* XPM */
1809145b7b3cSmrg    w->login.data.name[0] = '\0';
1810145b7b3cSmrg    w->login.data.passwd[0] = '\0';
1811145b7b3cSmrg    w->login.state = INITIALIZING;
1812145b7b3cSmrg    w->login.activePrompt = LOGIN_PROMPT_USERNAME;
1813145b7b3cSmrg    w->login.failUp = 0;
1814145b7b3cSmrg    w->login.fail = (char *) w->login.failMsg;
1815145b7b3cSmrg
1816145b7b3cSmrg    /* Set prompt defaults */
1817145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= NULL;
1818145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.namePrompt;
1819145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.data.name;
1820145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME)	= sizeof(w->login.data.name);
1821145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME)	= 0;
1822578741aaSmrg
1823145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= NULL;
1824145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.passwdPrompt;
1825145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.data.passwd;
1826145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD)	= sizeof(w->login.data.passwd);
1827145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD)	= 0;
1828145b7b3cSmrg
1829145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False);
1830145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False);
1831578741aaSmrg
1832145b7b3cSmrg    if (w->core.width == 0)
1833145b7b3cSmrg	w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
1834145b7b3cSmrg    if (w->core.height == 0) {
1835145b7b3cSmrg	int fy = FAIL_Y(w);
1836145b7b3cSmrg	int pady = PAD_Y(w);
1837145b7b3cSmrg
1838145b7b3cSmrg#ifndef XPM
1839145b7b3cSmrg	w->core.height = fy + pady;	/* for stupid compilers */
1840145b7b3cSmrg#else
1841145b7b3cSmrg/*	w->core.height = fy + pady;	* for stupid compilers */
1842145b7b3cSmrg
1843145b7b3cSmrg        w->core.height = max(fy + pady,
1844145b7b3cSmrg            (w->login.logoHeight + (2*w->login.logoPadding)) + pady);
1845578741aaSmrg
1846145b7b3cSmrg#endif /* XPM */
1847145b7b3cSmrg    }
1848145b7b3cSmrg#ifdef USE_XINERAMA
1849145b7b3cSmrg    if (
1850145b7b3cSmrg	XineramaIsActive(XtDisplay(w)) &&
1851145b7b3cSmrg	(screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL
1852145b7b3cSmrg       )
1853145b7b3cSmrg    {
1854145b7b3cSmrg	if ((x = w->core.x) == -1)
1855145b7b3cSmrg	    x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2;
1856145b7b3cSmrg	if ((y = w->core.y) == -1)
1857145b7b3cSmrg	    y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3;
1858578741aaSmrg
1859145b7b3cSmrg	XFree(screens);
1860145b7b3cSmrg    }
1861145b7b3cSmrg    else
1862145b7b3cSmrg#endif
1863145b7b3cSmrg    {
1864145b7b3cSmrg	if ((x = w->core.x) == -1)
1865145b7b3cSmrg	    x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2;
1866145b7b3cSmrg	if ((y = w->core.y) == -1)
1867145b7b3cSmrg	    y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3;
1868145b7b3cSmrg    }
1869145b7b3cSmrg    XtSetArg (position[0], XtNx, x);
1870145b7b3cSmrg    XtSetArg (position[1], XtNy, y);
1871145b7b3cSmrg    XtSetValues (XtParent (w), position, (Cardinal) 2);
1872145b7b3cSmrg
1873145b7b3cSmrg    w->login.state = PROMPTING;
1874145b7b3cSmrg}
1875145b7b3cSmrg
1876578741aaSmrg
1877145b7b3cSmrgstatic void Realize (
1878145b7b3cSmrg     Widget gw,
1879145b7b3cSmrg     XtValueMask *valueMask,
1880145b7b3cSmrg     XSetWindowAttributes *attrs)
1881145b7b3cSmrg{
1882145b7b3cSmrg    LoginWidget	w = (LoginWidget) gw;
1883145b7b3cSmrg    Cursor cursor;
1884145b7b3cSmrg
1885145b7b3cSmrg    XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
1886145b7b3cSmrg		     *valueMask, attrs );
1887145b7b3cSmrg    InitI18N(gw);
1888145b7b3cSmrg
1889145b7b3cSmrg#ifdef USE_XFT
1890145b7b3cSmrg    w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w),
1891145b7b3cSmrg	   DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))),
1892145b7b3cSmrg				   w->core.colormap);
1893145b7b3cSmrg
1894145b7b3cSmrg#endif
1895145b7b3cSmrg
1896145b7b3cSmrg    cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr);
1897145b7b3cSmrg    XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor);
1898145b7b3cSmrg
1899145b7b3cSmrg#ifdef XPM
1900578741aaSmrg    /*
1901145b7b3cSmrg     * Check if Pixmap was valid
1902145b7b3cSmrg     */
1903145b7b3cSmrg    if (True == w->login.logoValid)
1904145b7b3cSmrg    {
1905145b7b3cSmrg        /*
1906578741aaSmrg         * Create pixmap window
1907145b7b3cSmrg         */
1908145b7b3cSmrg        {
1909629baa8cSmrg            XSetWindowAttributes windowAttributes = {
1910629baa8cSmrg                .background_pixel = w->core.background_pixel,
1911629baa8cSmrg                .background_pixmap = None
1912629baa8cSmrg            };
1913145b7b3cSmrg
1914145b7b3cSmrg            w->login.logoWindow = XCreateWindow(XtDisplay(w),
1915145b7b3cSmrg                XtWindow(w),
1916145b7b3cSmrg                w->core.width - w->login.outframewidth -
1917145b7b3cSmrg                    w->login.logoWidth - w->login.logoPadding,
1918145b7b3cSmrg                (w->core.height - w->login.logoHeight) /2,
1919145b7b3cSmrg                w->login.logoWidth, w->login.logoHeight, 0,
1920145b7b3cSmrg                CopyFromParent, InputOutput, CopyFromParent,
1921629baa8cSmrg                CWBackPixel | CWBackPixmap, &windowAttributes);
1922145b7b3cSmrg        }
1923145b7b3cSmrg
1924145b7b3cSmrg        /*
1925145b7b3cSmrg         * check if we can use shape extension
1926145b7b3cSmrg         */
1927145b7b3cSmrg        if (True == w->login.useShape)
1928145b7b3cSmrg        {
1929145b7b3cSmrg            int foo, bar;
1930145b7b3cSmrg
1931145b7b3cSmrg            if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE)
1932145b7b3cSmrg            {
1933145b7b3cSmrg                XShapeCombineMask(XtDisplay(w), w->login.logoWindow,
1934145b7b3cSmrg                    ShapeBounding, w->login.logoX, w->login.logoY,
1935145b7b3cSmrg                    w->login.logoMask, ShapeSet);
1936145b7b3cSmrg            }
1937145b7b3cSmrg        }
1938145b7b3cSmrg
1939145b7b3cSmrg        XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow,
1940145b7b3cSmrg            w->login.logoPixmap);
1941145b7b3cSmrg        XMapWindow(XtDisplay(w), w->login.logoWindow);
1942145b7b3cSmrg    }
1943145b7b3cSmrg#endif /* XPM */
1944145b7b3cSmrg}
1945145b7b3cSmrg
1946145b7b3cSmrgstatic void Destroy (Widget gw)
1947145b7b3cSmrg{
1948145b7b3cSmrg    LoginWidget w = (LoginWidget)gw;
1949145b7b3cSmrg    bzero (w->login.data.name, NAME_LEN);
1950145b7b3cSmrg    bzero (w->login.data.passwd, PASSWORD_LEN);
1951145b7b3cSmrg
1952145b7b3cSmrg    if (PROMPT_TEXT(w,0) != NULL)
1953145b7b3cSmrg	XtFree(PROMPT_TEXT(w,0));
1954145b7b3cSmrg    if (PROMPT_TEXT(w,1) != NULL)
1955145b7b3cSmrg	XtFree(PROMPT_TEXT(w,1));
1956145b7b3cSmrg
1957145b7b3cSmrg#ifdef USE_XFT
1958145b7b3cSmrg    if (w->login.draw) {
1959145b7b3cSmrg	XftDrawDestroy(w->login.draw);
1960145b7b3cSmrg	w->login.draw = NULL;
1961145b7b3cSmrg    }
1962578741aaSmrg#endif
1963578741aaSmrg
1964145b7b3cSmrg    XtReleaseGC(gw, w->login.textGC);
1965145b7b3cSmrg    XtReleaseGC(gw, w->login.bgGC);
1966145b7b3cSmrg    XtReleaseGC(gw, w->login.xorGC);
1967145b7b3cSmrg#ifndef USE_XFT
1968145b7b3cSmrg    XtReleaseGC(gw, w->login.promptGC);
1969145b7b3cSmrg    XtReleaseGC(gw, w->login.greetGC);
1970145b7b3cSmrg    XtReleaseGC(gw, w->login.failGC);
1971145b7b3cSmrg#endif
1972145b7b3cSmrg    XtReleaseGC(gw, w->login.hiGC);
1973145b7b3cSmrg    XtReleaseGC(gw, w->login.shdGC);
1974b7d26471Smrg    XtReleaseGC(gw, w->login.inpGC);
1975145b7b3cSmrg
1976145b7b3cSmrg#ifdef XPM
1977145b7b3cSmrg    if (True == w->login.logoValid)
1978145b7b3cSmrg    {
1979145b7b3cSmrg        if (w->login.logoPixmap != 0)
1980145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoPixmap);
1981145b7b3cSmrg
1982145b7b3cSmrg        if (w->login.logoMask != 0)
1983145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoMask);
1984145b7b3cSmrg    }
1985145b7b3cSmrg#endif /* XPM */
1986145b7b3cSmrg}
1987145b7b3cSmrg
1988145b7b3cSmrg/* ARGSUSED */
1989145b7b3cSmrgstatic void Redisplay(
1990145b7b3cSmrg     Widget gw,
1991145b7b3cSmrg     XEvent *event,
1992145b7b3cSmrg     Region region)
1993145b7b3cSmrg{
1994145b7b3cSmrg    draw_it ((LoginWidget) gw);
1995145b7b3cSmrg}
1996145b7b3cSmrg
1997145b7b3cSmrg/*ARGSUSED*/
1998145b7b3cSmrgstatic Boolean SetValues (
1999145b7b3cSmrg    Widget  current,
2000145b7b3cSmrg    Widget  request,
2001145b7b3cSmrg    Widget  new,
2002145b7b3cSmrg    ArgList args,
2003145b7b3cSmrg    Cardinal *num_args)
2004145b7b3cSmrg{
2005145b7b3cSmrg    LoginWidget currentL, newL;
2006578741aaSmrg
2007145b7b3cSmrg    currentL = (LoginWidget) current;
2008145b7b3cSmrg    newL = (LoginWidget) new;
2009145b7b3cSmrg    if (GREETING (currentL) != GREETING (newL))
2010145b7b3cSmrg	return True;
2011145b7b3cSmrg    return False;
2012145b7b3cSmrg}
2013145b7b3cSmrg
2014145b7b3cSmrgstatic
2015145b7b3cSmrgchar defaultLoginTranslations [] =
2016145b7b3cSmrg"Ctrl<Key>H:	delete-previous-character() \n"
2017145b7b3cSmrg"Ctrl<Key>D:	delete-character() \n"
2018145b7b3cSmrg"Ctrl<Key>B:	move-backward-character() \n"
2019145b7b3cSmrg"Ctrl<Key>F:	move-forward-character() \n"
2020145b7b3cSmrg"Ctrl<Key>A:	move-to-begining() \n"
2021145b7b3cSmrg"Ctrl<Key>E:	move-to-end() \n"
2022145b7b3cSmrg"Ctrl<Key>K:	erase-to-end-of-line() \n"
2023145b7b3cSmrg"Ctrl<Key>U:	erase-line() \n"
2024145b7b3cSmrg"Ctrl<Key>X:	erase-line() \n"
2025145b7b3cSmrg"Ctrl<Key>C:	restart-session() \n"
2026145b7b3cSmrg"Ctrl<Key>\\\\:	abort-session() \n"
2027145b7b3cSmrg":Ctrl<Key>plus:	allow-all-access() \n"
2028145b7b3cSmrg"<Key>BackSpace:	delete-previous-character() \n"
2029145b7b3cSmrg#ifdef linux
2030145b7b3cSmrg"<Key>Delete:	delete-character() \n"
2031145b7b3cSmrg#else
2032145b7b3cSmrg"<Key>Delete:	delete-previous-character() \n"
2033145b7b3cSmrg#endif
2034145b7b3cSmrg"<Key>Return:	finish-field() \n"
2035145b7b3cSmrg"<Key>Tab:	tab-field() \n"
2036145b7b3cSmrg"<KeyPress>:	insert-char()"
2037145b7b3cSmrg;
2038145b7b3cSmrg
2039145b7b3cSmrgstatic
2040145b7b3cSmrgXtActionsRec loginActionsTable [] = {
2041145b7b3cSmrg  {"delete-previous-character",	DeleteBackwardChar},
2042145b7b3cSmrg  {"delete-character",		DeleteForwardChar},
2043145b7b3cSmrg  {"move-backward-character",	MoveBackwardChar},
2044145b7b3cSmrg  {"move-forward-character",	MoveForwardChar},
2045145b7b3cSmrg  {"move-to-begining",		MoveToBegining},
2046145b7b3cSmrg  {"move-to-end",		MoveToEnd},
2047145b7b3cSmrg  {"erase-to-end-of-line",	EraseToEndOfLine},
2048145b7b3cSmrg  {"erase-line",		EraseLine},
2049145b7b3cSmrg  {"finish-field", 		FinishField},
2050145b7b3cSmrg  {"tab-field", 		TabField},
2051145b7b3cSmrg  {"abort-session",		AbortSession},
2052145b7b3cSmrg  {"abort-display",		AbortDisplay},
2053145b7b3cSmrg  {"restart-session",		RestartSession},
2054145b7b3cSmrg  {"insert-char", 		InsertChar},
2055145b7b3cSmrg  {"set-session-argument",	SetSessionArgument},
2056145b7b3cSmrg  {"allow-all-access",		AllowAccess},
2057145b7b3cSmrg};
2058145b7b3cSmrg
2059145b7b3cSmrgLoginClassRec loginClassRec = {
2060145b7b3cSmrg    { /* core fields */
2061145b7b3cSmrg    /* superclass		*/	&widgetClassRec,
2062145b7b3cSmrg    /* class_name		*/	"Login",
2063145b7b3cSmrg    /* size			*/	sizeof(LoginRec),
2064145b7b3cSmrg    /* class_initialize		*/	ClassInitialize,
2065145b7b3cSmrg    /* class_part_initialize	*/	NULL,
2066145b7b3cSmrg    /* class_inited		*/	FALSE,
2067145b7b3cSmrg    /* initialize		*/	Initialize,
2068145b7b3cSmrg    /* initialize_hook		*/	NULL,
2069145b7b3cSmrg    /* realize			*/	Realize,
2070145b7b3cSmrg    /* actions			*/	loginActionsTable,
2071145b7b3cSmrg    /* num_actions		*/	XtNumber (loginActionsTable),
2072145b7b3cSmrg    /* resources		*/	resources,
2073145b7b3cSmrg    /* num_resources		*/	XtNumber(resources),
2074145b7b3cSmrg    /* xrm_class		*/	NULLQUARK,
2075145b7b3cSmrg    /* compress_motion		*/	TRUE,
2076145b7b3cSmrg    /* compress_exposure	*/	TRUE,
2077145b7b3cSmrg    /* compress_enterleave	*/	TRUE,
2078145b7b3cSmrg    /* visible_interest		*/	FALSE,
2079145b7b3cSmrg    /* destroy			*/	Destroy,
2080145b7b3cSmrg    /* resize			*/	NULL,
2081145b7b3cSmrg    /* expose			*/	Redisplay,
2082145b7b3cSmrg    /* set_values		*/	SetValues,
2083145b7b3cSmrg    /* set_values_hook		*/	NULL,
2084145b7b3cSmrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
2085145b7b3cSmrg    /* get_values_hook		*/	NULL,
2086145b7b3cSmrg    /* accept_focus		*/	NULL,
2087145b7b3cSmrg    /* version			*/	XtVersion,
2088145b7b3cSmrg    /* callback_private		*/	NULL,
2089145b7b3cSmrg    /* tm_table			*/	defaultLoginTranslations,
2090145b7b3cSmrg    /* query_geometry		*/	XtInheritQueryGeometry,
2091145b7b3cSmrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
2092145b7b3cSmrg    /* extension		*/	NULL
2093145b7b3cSmrg    }
2094145b7b3cSmrg};
2095145b7b3cSmrg
2096145b7b3cSmrgWidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
2097