Login.c revision c06e8ac6
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/*
29c06e8ac6Smrg * Copyright (c) 2006, Oracle and/or its affiliates.
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))
2581cacedb1Smlelstv#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
278329eaa64Smrg# define TEXT_COLOR(f)		(w->login.f##color.pixel)
279329eaa64Smrg
280329eaa64Smrg# define TEXT_WIDTH(f, m, l) 	XmuXftTextWidth(XtDisplay (w), \
281329eaa64Smrg					w->login.f##Face, (FcChar8 *) (m), l)
282145b7b3cSmrgstatic int
283145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len);
284145b7b3cSmrg
285145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
286145b7b3cSmrg	/* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \
287145b7b3cSmrg	XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \
288329eaa64Smrg			x, y, (FcChar8 *) (m), l)
289145b7b3cSmrg
290145b7b3cSmrg#else
291145b7b3cSmrg
292145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##pixel)
293145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	(XTextWidth (w->login.f##Font, m, l))
294145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
295145b7b3cSmrg	XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l)
296145b7b3cSmrg
297145b7b3cSmrg#endif
298145b7b3cSmrg
299145b7b3cSmrg
300578741aaSmrg#define STRING_WIDTH(f, s) 	TEXT_WIDTH (f, s, strlen(s))
301145b7b3cSmrg
302629baa8cSmrg/* Padded width of logo image, if compiled with XPM support */
303629baa8cSmrg#ifdef XPM
304026e32a9Smlelstv# define LOGO_PAD(w)   ((w)->login.logoPadding)
305026e32a9Smlelstv# define LOGO_W(w)     ((w)->login.logoWidth + (LOGO_PAD(w) * 2))
306629baa8cSmrg#else
307026e32a9Smlelstv# define LOGO_PAD(w)   0
308629baa8cSmrg# define LOGO_W(w)     0
309629baa8cSmrg#endif
310145b7b3cSmrg
311578741aaSmrg#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth)
312145b7b3cSmrg
313026e32a9Smlelstv#define DEF_PROMPT_W(w,n)	TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt)
314026e32a9Smlelstv#define MAX_DEF_PROMPT_W(w)	(max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1)))
315026e32a9Smlelstv#define CUR_PROMPT_W(w,n)	(max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \
316026e32a9Smlelstv					TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0))
317145b7b3cSmrg
318578741aaSmrg#define GREETING(w)	((w)->login.secure_session  && !(w)->login.allow_access ?\
319145b7b3cSmrg				(w)->login.greeting : (w)->login.unsecure_greet)
3201cacedb1Smlelstv#define GREET_X(w)	((int)((w->core.width - LOGO_W(w) + LOGO_PAD(w) - \
321145b7b3cSmrg			     	STRING_WIDTH (greet, GREETING(w))) / 2))
322578741aaSmrg#define GREET_Y(w)	(GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
323629baa8cSmrg#define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
324026e32a9Smlelstv			      STRING_WIDTH (greet, w->login.unsecure_greet)))
325026e32a9Smlelstv
326026e32a9Smlelstv#define SEP_X(w)	((w)->login.outframewidth + LOGO_PAD(w))
327026e32a9Smlelstv#define SEP_Y(w)	(GREET_Y(w) + GREET_Y_INC(w))
328026e32a9Smlelstv#define SEP_W(w)	((w)->core.width - 2*(w->login.outframewidth) - LOGO_W(w) - LOGO_PAD(w))
329026e32a9Smlelstv#define SEP_H(w)	((w)->login.inframeswidth * 2)
330629baa8cSmrg
331578741aaSmrg#define PROMPT_X(w)	(2 * PROMPT_X_INC(w))
3326cc8c0d3Smlelstv#define PROMPT_Y(w,n) 	(SEP_Y(w) + GREET_Y_INC(w) + (n) * Y_INC(w) + (2*(n)+1) * ((w)->login.inframeswidth + VALUE_VPAD(w,n)))
333026e32a9Smlelstv#define PROMPT_W(w)	(w->core.width - PROMPT_X(w) - 2 * TEXT_X_INC(w) - LOGO_W(w))
334026e32a9Smlelstv#define PROMPT_H(w)	Y_INC(w)
335026e32a9Smlelstv
33609dea964Smlelstv#define VALUE_HPAD(w,n)	(TEXT_X_INC(w)/8)
3371cacedb1Smlelstv#define VALUE_VPAD(w,n)	((Y_INC(w)+3)/4)
33809dea964Smlelstv#define VALUE_X(w,n)	(PROMPT_X(w) + CUR_PROMPT_W(w,n) + VALUE_HPAD(w,n))
339026e32a9Smlelstv#define VALUE_Y(w,n)	(PROMPT_Y(w,n))
340026e32a9Smlelstv#define VALUE_W(w,n)	(PROMPT_W(w) - VALUE_X(w,n) + PROMPT_X(w) - CURSOR_W)
341026e32a9Smlelstv#define VALUE_H(w,n)	Y_INC(w)
342145b7b3cSmrg
343b7d26471Smrg#define ERROR_X(w,m)	((int)(w->core.width - LOGO_W(w) - STRING_WIDTH (fail, m)) / 2)
344629baa8cSmrg#define ERROR_W(w,m)	(STRING_WIDTH (fail, m) + LOGO_W(w))
345145b7b3cSmrg
346026e32a9Smlelstv#define FAIL_X(w)	ERROR_X(w, w->login.fail)
347026e32a9Smlelstv#define FAIL_Y(w)	(PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail))
348578741aaSmrg#define FAIL_W(w)	max(ERROR_W(w, w->login.failMsg), \
349145b7b3cSmrg			    ERROR_W(w, w->login.passwdChangeMsg))
350145b7b3cSmrg
351d44fbef5Smlelstv#define PAD_X(w)	(2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w)) + 4*w->login.outframewidth))
352578741aaSmrg#define PAD_Y(w)	(max (max (Y_INC(w), GREET_Y_INC(w)),\
353145b7b3cSmrg			     FAIL_Y_INC(w)))
354578741aaSmrg
355145b7b3cSmrg#ifndef max
356145b7b3cSmrgstatic inline int max (int a, int b) { return a > b ? a : b; }
357145b7b3cSmrg#endif
358145b7b3cSmrg
359145b7b3cSmrgstatic void
360145b7b3cSmrgrealizeValue (LoginWidget w, int cursor, int promptNum, GC gc)
361145b7b3cSmrg{
3625ffd6003Smrg    loginPromptState state = PROMPT_STATE(w, promptNum);
363145b7b3cSmrg    char *text = VALUE_TEXT(w, promptNum);
364026e32a9Smlelstv    int	x, y, height, width, curoff, offset, textlen;
365145b7b3cSmrg
366145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
367145b7b3cSmrg
3685ffd6003Smrg    /* replace all password characters with asterisks */
3695ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
3705ffd6003Smrg    {
3715ffd6003Smrg	Cardinal length = strlen(text);
3725ffd6003Smrg	Cardinal i = 0;
3735ffd6003Smrg
3745ffd6003Smrg	text = XtMalloc(length + 1);
3755ffd6003Smrg
3765ffd6003Smrg	if (text == NULL)
3775ffd6003Smrg	{
3785ffd6003Smrg	    LogOutOfMem("realizeValue");
3795ffd6003Smrg	    return;
3805ffd6003Smrg	}
3815ffd6003Smrg
3825ffd6003Smrg	while (i < length)
3835ffd6003Smrg	{
384629baa8cSmrg	    text[i++] = w->login.echo_passwd_char[0];
3855ffd6003Smrg	}
3865ffd6003Smrg
3875ffd6003Smrg	text[i] = 0;
3885ffd6003Smrg    }
3895ffd6003Smrg
39009dea964Smlelstv    x = VALUE_X (w,promptNum) + VALUE_HPAD(w,promptNum);
391026e32a9Smlelstv    y = VALUE_Y (w,promptNum);
392145b7b3cSmrg
3931cacedb1Smlelstv    height = VALUE_H(w,promptNum);
394026e32a9Smlelstv    width = VALUE_W(w,promptNum);
395145b7b3cSmrg
396026e32a9Smlelstv    offset = VALUE_SHOW_START(w, promptNum);
397026e32a9Smlelstv    if (cursor > offset)
398026e32a9Smlelstv	curoff = TEXT_WIDTH (text, text + offset, cursor - offset);
399145b7b3cSmrg    else
400145b7b3cSmrg	curoff = 0;
401145b7b3cSmrg
402145b7b3cSmrg    if (gc == w->login.bgGC) {
403145b7b3cSmrg	if (curoff < width) {
404145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
405026e32a9Smlelstv			    x + curoff, y - Y_ASCENT(w),
406145b7b3cSmrg			    width - curoff, height);
407145b7b3cSmrg	}
4085ffd6003Smrg    } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) ||
4095ffd6003Smrg	       ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)))
4105ffd6003Smrg    {
411026e32a9Smlelstv	offset = max(cursor, VALUE_SHOW_START(w, promptNum));
412026e32a9Smlelstv	textlen = strlen (text + offset);
413578741aaSmrg
414629baa8cSmrg	if (TEXT_WIDTH (text, text + offset, textlen) > (width - curoff)) {
415145b7b3cSmrg	    /* Recalculate amount of text that can fit in field */
416145b7b3cSmrg	    offset = VALUE_SHOW_START(w, promptNum);
417145b7b3cSmrg	    textlen = strlen (text + offset);
418145b7b3cSmrg
419629baa8cSmrg	    while ((textlen > 0) &&
420629baa8cSmrg		   (TEXT_WIDTH (text, text + offset, textlen) > width))
421145b7b3cSmrg	    {
422145b7b3cSmrg		if (offset < PROMPT_CURSOR(w, promptNum)) {
423145b7b3cSmrg		    offset++;
424145b7b3cSmrg		}
425145b7b3cSmrg		textlen--;
426578741aaSmrg	    }
427145b7b3cSmrg
428145b7b3cSmrg	    VALUE_SHOW_START(w, promptNum) = offset;
429145b7b3cSmrg	    VALUE_SHOW_END(w, promptNum) = offset + textlen;
430145b7b3cSmrg
431145b7b3cSmrg	    /* Erase old string */
432145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC,
433026e32a9Smlelstv			    x, y - Y_ASCENT(w), width, height);
434145b7b3cSmrg
435145b7b3cSmrg	    DRAW_STRING(text, x, y, text + offset, textlen);
436145b7b3cSmrg	} else {
437145b7b3cSmrg	    DRAW_STRING(text, x + curoff, y, text + offset, textlen);
438145b7b3cSmrg	}
439145b7b3cSmrg    }
4405ffd6003Smrg    /* free memory */
4415ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
4425ffd6003Smrg    {
4435ffd6003Smrg	XtFree(text);
4445ffd6003Smrg    }
445145b7b3cSmrg}
446145b7b3cSmrg
447145b7b3cSmrgstatic void
448145b7b3cSmrgEraseValue (LoginWidget w, int cursor, int promptNum)
449145b7b3cSmrg{
450145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.bgGC);
451145b7b3cSmrg}
452145b7b3cSmrg
453145b7b3cSmrgstatic void
454145b7b3cSmrgDrawValue (LoginWidget w, int cursor, int promptNum)
455145b7b3cSmrg{
456145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.textGC);
457145b7b3cSmrg#ifdef DANCING
458145b7b3cSmrg    /*as good a place as any Caolan begin*/
459145b7b3cSmrg    w->login.lastEventTime = time(NULL);
460145b7b3cSmrg    /*as good a place as any Caolan end*/
461145b7b3cSmrg#endif /* DANCING */
462145b7b3cSmrg}
463145b7b3cSmrg
464145b7b3cSmrgstatic void
465145b7b3cSmrgrealizeCursor (LoginWidget w, GC gc)
466145b7b3cSmrg{
467145b7b3cSmrg    int	x, y;
468026e32a9Smlelstv    int ascent, descent;
469145b7b3cSmrg
470145b7b3cSmrg    if (w->login.state != PROMPTING) {
471145b7b3cSmrg	return;
472145b7b3cSmrg    }
473578741aaSmrg
47409dea964Smlelstv    x = VALUE_X (w, w->login.activePrompt)
47509dea964Smlelstv      + VALUE_HPAD(w, w->login.activePrompt);
476026e32a9Smlelstv    y = VALUE_Y (w, w->login.activePrompt);
477026e32a9Smlelstv    ascent = F_ASCENT(text);
478026e32a9Smlelstv    descent = F_DESCENT(text);
479145b7b3cSmrg
480145b7b3cSmrg    switch (PROMPT_STATE(w, w->login.activePrompt)) {
481145b7b3cSmrg    case LOGIN_PROMPT_NOT_SHOWN:
482145b7b3cSmrg    case LOGIN_TEXT_INFO:
483145b7b3cSmrg	return;
484145b7b3cSmrg    case LOGIN_PROMPT_ECHO_ON:
485145b7b3cSmrg	if (CUR_PROMPT_CURSOR(w) > 0) {
486145b7b3cSmrg	    x += TEXT_WIDTH (text,
487145b7b3cSmrg			     VALUE_TEXT(w, w->login.activePrompt)
488145b7b3cSmrg			     + VALUE_SHOW_START(w, w->login.activePrompt),
489145b7b3cSmrg			     PROMPT_CURSOR(w, w->login.activePrompt)
490145b7b3cSmrg			     - VALUE_SHOW_START(w, w->login.activePrompt) );
491145b7b3cSmrg	}
492145b7b3cSmrg	break;
493145b7b3cSmrg    case LOGIN_PROMPT_ECHO_OFF:
4945ffd6003Smrg	if (w->login.echo_passwd == True) {
495629baa8cSmrg	    if (w->login.echo_passwd_char[0] != 0) {
496629baa8cSmrg		int len = PROMPT_CURSOR(w, w->login.activePrompt) -
497629baa8cSmrg		    VALUE_SHOW_START(w, w->login.activePrompt);
4985ffd6003Smrg
499629baa8cSmrg		x += len*TEXT_WIDTH(text, w->login.echo_passwd_char, 1);
500629baa8cSmrg	    } else {
501629baa8cSmrg		/* Move cursor one pixel per character to give some feedback
502629baa8cSmrg		   without giving away the password length */
503629baa8cSmrg		if (PROMPT_CURSOR(w, w->login.activePrompt) <
504026e32a9Smlelstv		    VALUE_W(w, w->login.activePrompt))
505629baa8cSmrg		    x += PROMPT_CURSOR(w, w->login.activePrompt);
506629baa8cSmrg		else
507026e32a9Smlelstv		    x += VALUE_W(w, w->login.activePrompt);
508629baa8cSmrg	    }
5095ffd6003Smrg	}
510145b7b3cSmrg	break;
511145b7b3cSmrg    }
512578741aaSmrg
5133f10d660Smlelstv    x += 2;
5143f10d660Smlelstv
515145b7b3cSmrg    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
516026e32a9Smlelstv		    x, y - ascent + 1, 1, ascent + descent - 2);
517026e32a9Smlelstv
518145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
519026e32a9Smlelstv		    x-1 , y - ascent);
520145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
521026e32a9Smlelstv		    x+1 , y - ascent);
522145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
523026e32a9Smlelstv		    x-1 , y + descent - 1);
524145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
525026e32a9Smlelstv		    x+1 , y - descent - 1);
526026e32a9Smlelstv
527145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
528026e32a9Smlelstv		    x-2 , y - ascent);
529145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
530026e32a9Smlelstv		    x+2 , y - ascent);
531145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
532026e32a9Smlelstv		    x-2 , y + descent - 1);
533145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
534026e32a9Smlelstv		    x+2 , y + descent - 1);
535145b7b3cSmrg
536578741aaSmrg    XFlush (XtDisplay(w));
537145b7b3cSmrg}
538145b7b3cSmrg
539145b7b3cSmrgstatic void
540145b7b3cSmrgEraseFail (LoginWidget w)
541145b7b3cSmrg{
542578741aaSmrg#ifdef USE_XFT
543145b7b3cSmrg    w->login.failUp = 0;
544145b7b3cSmrg    RedrawFail(w);
545578741aaSmrg#else
546145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
547145b7b3cSmrg			w->core.background_pixel);
548145b7b3cSmrg    RedrawFail(w);
549145b7b3cSmrg    w->login.failUp = 0;
550145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
551145b7b3cSmrg			TEXT_COLOR(fail));
552578741aaSmrg#endif
553145b7b3cSmrg}
554145b7b3cSmrg
555145b7b3cSmrgstatic void
556145b7b3cSmrgXorCursor (LoginWidget w)
557145b7b3cSmrg{
558145b7b3cSmrg    realizeCursor (w, w->login.xorGC);
559145b7b3cSmrg}
560145b7b3cSmrg
561145b7b3cSmrgstatic void
562145b7b3cSmrgRemoveFail (LoginWidget w)
563145b7b3cSmrg{
564145b7b3cSmrg    if (w->login.failUp)
565145b7b3cSmrg	EraseFail (w);
566145b7b3cSmrg}
567145b7b3cSmrg
568145b7b3cSmrgstatic void
569145b7b3cSmrgEraseCursor (LoginWidget w)
570145b7b3cSmrg{
571145b7b3cSmrg    realizeCursor (w, w->login.bgGC);
572145b7b3cSmrg}
573145b7b3cSmrg
574145b7b3cSmrg/*ARGSUSED*/
575145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id)
576145b7b3cSmrg{
577145b7b3cSmrg    LoginWidget	w = (LoginWidget)client_data;
578145b7b3cSmrg
579145b7b3cSmrg    Debug ("failTimeout\n");
580145b7b3cSmrg    w->login.interval_id = 0;
581145b7b3cSmrg    EraseFail (w);
582145b7b3cSmrg}
583145b7b3cSmrg
584145b7b3cSmrg_X_INTERNAL
585145b7b3cSmrgvoid
586145b7b3cSmrgDrawFail (Widget ctx)
587145b7b3cSmrg{
588145b7b3cSmrg    LoginWidget	w;
589145b7b3cSmrg
590145b7b3cSmrg    w = (LoginWidget) ctx;
591145b7b3cSmrg    XorCursor (w);
592145b7b3cSmrg    ResetLogin (w);
593145b7b3cSmrg    XorCursor (w);
594145b7b3cSmrg    ErrorMessage(ctx, w->login.failMsg, True);
595145b7b3cSmrg}
596145b7b3cSmrg
597145b7b3cSmrgstatic void
598145b7b3cSmrgRedrawFail (LoginWidget w)
599145b7b3cSmrg{
600145b7b3cSmrg    int x = FAIL_X(w);
601145b7b3cSmrg    int y = FAIL_Y(w);
602145b7b3cSmrg    int maxw = w->core.width - PAD_X(w);
603145b7b3cSmrg
604578741aaSmrg#ifndef USE_XFT
605145b7b3cSmrg    if (w->login.failUp)
606578741aaSmrg#endif
607145b7b3cSmrg    {
608145b7b3cSmrg	Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp);
609145b7b3cSmrg	if (ERROR_W(w, w->login.fail) > maxw) {
610145b7b3cSmrg	    /* Too long to fit on one line, break into multiple lines */
611145b7b3cSmrg	    char *tempCopy = strdup(w->login.fail);
612145b7b3cSmrg	    if (tempCopy != NULL) {
613145b7b3cSmrg		char *start, *next;
614578741aaSmrg		char lastspace = ' ';
615145b7b3cSmrg
616145b7b3cSmrg		y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w));
617578741aaSmrg
618145b7b3cSmrg		for (start = next = tempCopy; start != NULL ; start = next) {
619145b7b3cSmrg		    /* search for longest string broken by whitespace that
620145b7b3cSmrg		       will fit on a single line */
621145b7b3cSmrg		    do {
622145b7b3cSmrg			if (next != start) {
623145b7b3cSmrg			    *next = lastspace;
624145b7b3cSmrg			}
625145b7b3cSmrg			for (next = next + 1;
626145b7b3cSmrg			     (*next != '\0') && !isspace(*next) ; next++)
627145b7b3cSmrg			{
628145b7b3cSmrg			    /* this loop intentionally left blank */
629145b7b3cSmrg			}
630145b7b3cSmrg			if (*next != '\0') {
631145b7b3cSmrg			    lastspace = *next;
632145b7b3cSmrg			    *next = '\0';
633145b7b3cSmrg			} else {
634145b7b3cSmrg			    next = NULL;
635145b7b3cSmrg			}
636145b7b3cSmrg		    } while ((next != NULL) && ERROR_W(w, start) < maxw);
637578741aaSmrg
638145b7b3cSmrg		    x = ERROR_X(w, start);
639145b7b3cSmrg#ifdef USE_XFT
640145b7b3cSmrg		    if (w->login.failUp == 0) {
6415ffd6003Smrg			XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
642145b7b3cSmrg				   ERROR_W(w, start), FAIL_Y_INC(w), False);
643145b7b3cSmrg		    } else
644578741aaSmrg#endif
645145b7b3cSmrg			DRAW_STRING (fail, x, y, start, strlen(start));
646145b7b3cSmrg
647145b7b3cSmrg		    if (next != NULL) {
648145b7b3cSmrg			next++;
649145b7b3cSmrg			y += FAIL_Y_INC(w);
650145b7b3cSmrg		    }
651145b7b3cSmrg		}
652145b7b3cSmrg		free(tempCopy);
653145b7b3cSmrg		return;
654145b7b3cSmrg	    }
655145b7b3cSmrg	    /* if strdup failed, fall through to draw all at once, even
656145b7b3cSmrg	       though we know it can't all fit */
657145b7b3cSmrg	    LogOutOfMem("RedrawFail");
658145b7b3cSmrg	}
659145b7b3cSmrg
660145b7b3cSmrg#ifdef USE_XFT
661145b7b3cSmrg	if (w->login.failUp == 0) {
6625ffd6003Smrg	    XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
663145b7b3cSmrg		       ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False);
664145b7b3cSmrg	} else
665578741aaSmrg#endif
666145b7b3cSmrg	    DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail));
667145b7b3cSmrg    }
668145b7b3cSmrg}
669145b7b3cSmrg
670145b7b3cSmrg_X_INTERNAL
671145b7b3cSmrgvoid
672145b7b3cSmrgErrorMessage(Widget ctx, const char *message, Bool timeout)
673145b7b3cSmrg{
674145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
675145b7b3cSmrg
676145b7b3cSmrg/*  Debug("ErrorMessage: %s\n", message);   */
677145b7b3cSmrg    if (w->login.interval_id != 0) {
678145b7b3cSmrg	XtRemoveTimeOut(w->login.interval_id);
679145b7b3cSmrg	w->login.interval_id = 0;
680145b7b3cSmrg    }
681145b7b3cSmrg    RemoveFail(w);
682145b7b3cSmrg    if (w->login.fail != w->login.failMsg)
683145b7b3cSmrg	free(w->login.fail);
684145b7b3cSmrg    w->login.fail = strdup(message);
685145b7b3cSmrg    if (w->login.fail == NULL)
686145b7b3cSmrg	w->login.fail = (char *) w->login.failMsg;
687145b7b3cSmrg    w->login.failUp = 1;
688145b7b3cSmrg    RedrawFail (w);
689145b7b3cSmrg    if (timeout && (w->login.failTimeout > 0)) {
690145b7b3cSmrg	Debug ("failTimeout: %d\n", w->login.failTimeout);
691145b7b3cSmrg	w->login.interval_id =
692145b7b3cSmrg	    XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w),
693145b7b3cSmrg			    w->login.failTimeout * 1000,
694145b7b3cSmrg			    failTimeout, (XtPointer) w);
695145b7b3cSmrg    }
696145b7b3cSmrg}
697145b7b3cSmrg
698145b7b3cSmrg_X_INTERNAL
699145b7b3cSmrgvoid
700145b7b3cSmrgShowChangePasswdMessage(Widget ctx)
701145b7b3cSmrg{
702145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
703145b7b3cSmrg
704145b7b3cSmrg    ErrorMessage(ctx, w->login.passwdChangeMsg, False);
705145b7b3cSmrg}
706145b7b3cSmrg
707145b7b3cSmrgstatic void
708145b7b3cSmrgdraw_it (LoginWidget w)
709145b7b3cSmrg{
710145b7b3cSmrg    int p;
711145b7b3cSmrg    int i;
712145b7b3cSmrg    int gr_line_x, gr_line_y, gr_line_w;
713145b7b3cSmrg
714145b7b3cSmrg    EraseCursor (w);
715145b7b3cSmrg
7165ffd6003Smrg    /* draw window borders */
717145b7b3cSmrg    for(i=1;i<=(w->login.outframewidth);i++)
718145b7b3cSmrg    {
719145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
720629baa8cSmrg		i-1,i-1,w->core.width-i,i-1);
721145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
722629baa8cSmrg		i-1,i-1,i-1,w->core.height-i);
723145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
724629baa8cSmrg		w->core.width-i,i-1,w->core.width-i,w->core.height-i);
725145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
726629baa8cSmrg		i-1,w->core.height-i,w->core.width-i,w->core.height-i);
727145b7b3cSmrg    }
728578741aaSmrg
729145b7b3cSmrg    /* make separator line */
730026e32a9Smlelstv    gr_line_x = SEP_X(w);
731026e32a9Smlelstv    gr_line_y = SEP_Y(w);
732026e32a9Smlelstv    gr_line_w = SEP_W(w);
733145b7b3cSmrg
734145b7b3cSmrg    for(i=1;i<=(w->login.sepwidth);i++)
735145b7b3cSmrg    {
736145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
737145b7b3cSmrg        gr_line_x,           gr_line_y + i-1,
738145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + i-1);
739145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
740026e32a9Smlelstv        gr_line_x,           gr_line_y + SEP_H(w) -i,
741026e32a9Smlelstv        gr_line_x+gr_line_w, gr_line_y + SEP_H(w) -i);
742145b7b3cSmrg    }
743145b7b3cSmrg
744145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++)
745145b7b3cSmrg    {
746026e32a9Smlelstv	int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth;
7471cacedb1Smlelstv	int in_frame_y = VALUE_Y(w,p) - Y_ASCENT(w) - w->login.inframeswidth
7481cacedb1Smlelstv		- VALUE_VPAD(w,p);
749578741aaSmrg
75009dea964Smlelstv	int in_width = VALUE_W(w,p) + CURSOR_W + 2 * w->login.inframeswidth
75109dea964Smlelstv		+ 2 * VALUE_HPAD(w,p);
7521cacedb1Smlelstv	int in_height = VALUE_H(w,p) + 2 * w->login.inframeswidth
7531cacedb1Smlelstv		+ 2 * VALUE_VPAD(w,p);
754578741aaSmrg
755b7d26471Smrg	GC topLeftGC, botRightGC, inpGC;
756145b7b3cSmrg
757145b7b3cSmrg	if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) ||
758145b7b3cSmrg	    (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) {
759145b7b3cSmrg	    topLeftGC = w->login.shdGC;
760145b7b3cSmrg	    botRightGC = w->login.hiGC;
761b7d26471Smrg	    inpGC = w->login.inpGC;
762145b7b3cSmrg	} else {
763b7d26471Smrg	    topLeftGC = botRightGC = inpGC = w->login.bgGC;
764145b7b3cSmrg	}
765145b7b3cSmrg
7665ffd6003Smrg	/* draw borders of editboxes */
767145b7b3cSmrg	for (i=1; i<=(w->login.inframeswidth); i++)
768145b7b3cSmrg	{
769145b7b3cSmrg	    /* Make top/left sides */
770145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
771145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
772578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1);
773145b7b3cSmrg
774145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
775145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
776578741aaSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i);
777145b7b3cSmrg
778145b7b3cSmrg	    /* Make bottom/right sides */
779145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
780145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1,
781578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
782145b7b3cSmrg
783145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
784145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i,
785145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
786145b7b3cSmrg	}
787b7d26471Smrg	XFillRectangle(XtDisplay (w), XtWindow (w), inpGC,
788b7d26471Smrg	    in_frame_x + w->login.inframeswidth,
789b7d26471Smrg	    in_frame_y + w->login.inframeswidth,
790b7d26471Smrg	    in_width - 2*w->login.inframeswidth,
791b7d26471Smrg	    in_height - 2*w->login.inframeswidth);
792145b7b3cSmrg    }
793145b7b3cSmrg
794145b7b3cSmrg    if (GREETING(w)[0]) {
7951cacedb1Smlelstv	DRAW_STRING (greet, GREET_X(w), GREET_Y(w),
7961cacedb1Smlelstv		     GREETING(w), strlen (GREETING(w)));
797145b7b3cSmrg    }
798145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++) {
799145b7b3cSmrg	if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) {
800145b7b3cSmrg	    DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p),
801145b7b3cSmrg			 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p)));
802145b7b3cSmrg	    DrawValue (w, 0, p);
803145b7b3cSmrg	}
804145b7b3cSmrg    }
805145b7b3cSmrg    RedrawFail (w);
806145b7b3cSmrg    XorCursor (w);
8075ffd6003Smrg    XSetInputFocus (XtDisplay (w), XtWindow (w),
8085ffd6003Smrg		    RevertToPointerRoot, CurrentTime);
809145b7b3cSmrg}
810145b7b3cSmrg
811145b7b3cSmrg/* Returns 0 on success, -1 on failure */
812145b7b3cSmrg_X_INTERNAL
813145b7b3cSmrgint
814145b7b3cSmrgSetPrompt (Widget ctx, int promptNum, const char *message,
815145b7b3cSmrg	   loginPromptState state, Boolean minimumTime)
816145b7b3cSmrg{
817145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
818145b7b3cSmrg    char *prompt;
819145b7b3cSmrg    int messageLen, e;
820145b7b3cSmrg    const char *stateNames[4] = {
821145b7b3cSmrg	"LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON",
822145b7b3cSmrg	"LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" };
823145b7b3cSmrg    loginPromptState priorState;
824578741aaSmrg
825145b7b3cSmrg    Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum,
826145b7b3cSmrg	  message ? message : "<NULL>", stateNames[state], state);
827145b7b3cSmrg
828145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
829578741aaSmrg
830145b7b3cSmrg    if (PROMPT_TEXT(w, promptNum) != NULL) {
831145b7b3cSmrg	XtFree(PROMPT_TEXT(w, promptNum));
832145b7b3cSmrg	PROMPT_TEXT(w, promptNum) = NULL;
833145b7b3cSmrg    }
834145b7b3cSmrg
835145b7b3cSmrg    priorState = PROMPT_STATE(w, promptNum);
836145b7b3cSmrg    PROMPT_STATE(w, promptNum) = state;
837145b7b3cSmrg
838145b7b3cSmrg    if (state == LOGIN_PROMPT_NOT_SHOWN) {
839145b7b3cSmrg	return 0;
840145b7b3cSmrg    }
841145b7b3cSmrg
842145b7b3cSmrg    if (message == NULL) {
843145b7b3cSmrg	message = DEF_PROMPT_TEXT(w, promptNum);
844145b7b3cSmrg    }
845145b7b3cSmrg
846145b7b3cSmrg    messageLen = strlen(message);
847578741aaSmrg
848145b7b3cSmrg    prompt = XtMalloc(messageLen + 3);
849145b7b3cSmrg    if (prompt == NULL) {
850145b7b3cSmrg	LogOutOfMem ("SetPrompt");
851145b7b3cSmrg	return -1;
852145b7b3cSmrg    }
853578741aaSmrg
854145b7b3cSmrg    strncpy(prompt, message, messageLen);
855578741aaSmrg
856145b7b3cSmrg    /* Make sure text prompts have at least two spaces at end */
857145b7b3cSmrg    e = messageLen;
858578741aaSmrg
859145b7b3cSmrg    if (!isspace(message[messageLen - 2])) {
860145b7b3cSmrg	prompt[e] = ' ';
861145b7b3cSmrg	e++;
862145b7b3cSmrg    }
863145b7b3cSmrg    if (!isspace(message[messageLen - 1])) {
864145b7b3cSmrg	prompt[e] = ' ';
865145b7b3cSmrg	e++;
866145b7b3cSmrg    }
867145b7b3cSmrg    prompt[e] = '\0';
868145b7b3cSmrg
869145b7b3cSmrg    PROMPT_TEXT(w, promptNum) = prompt;
870145b7b3cSmrg
871145b7b3cSmrg    if (w->login.state == INITIALIZING) {
872145b7b3cSmrg	return 0;
873145b7b3cSmrg    }
874578741aaSmrg
875145b7b3cSmrg    if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) {
876145b7b3cSmrg	time_t now = time(NULL);
877145b7b3cSmrg	int timeleft = w->login.msgTimeout - now;
878578741aaSmrg
879145b7b3cSmrg	if (timeleft > 0) {
880145b7b3cSmrg	    sleep(timeleft);
881145b7b3cSmrg	}
882145b7b3cSmrg	w->login.msgTimeout = 0;
883145b7b3cSmrg    }
884145b7b3cSmrg
885145b7b3cSmrg    if (state == LOGIN_TEXT_INFO) {
886145b7b3cSmrg	if (minimumTime) {
887145b7b3cSmrg	    time_t now = time(NULL);
888145b7b3cSmrg	    w->login.msgTimeout = now + w->login.failTimeout;
889145b7b3cSmrg	}
890145b7b3cSmrg	w->login.state = SHOW_MESSAGE;
891145b7b3cSmrg    } else {
892145b7b3cSmrg	w->login.activePrompt = promptNum;
893145b7b3cSmrg	w->login.state = PROMPTING;
894145b7b3cSmrg    }
895578741aaSmrg
896145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
897145b7b3cSmrg    XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE);
898145b7b3cSmrg    draw_it(w);
899145b7b3cSmrg    return 0;
900145b7b3cSmrg}
901145b7b3cSmrg
902145b7b3cSmrg_X_INTERNAL
903145b7b3cSmrgconst char *
904145b7b3cSmrgGetPrompt(Widget ctx, int promptNum)
905145b7b3cSmrg{
906145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
907145b7b3cSmrg
908145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
909578741aaSmrg
910145b7b3cSmrg    return CUR_PROMPT_TEXT(w,promptNum);
911145b7b3cSmrg}
912145b7b3cSmrg
913145b7b3cSmrg_X_INTERNAL
914145b7b3cSmrgint
915c06e8ac6SmrgSetValue(Widget ctx, int promptNum, const char *value)
916145b7b3cSmrg{
917145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
918145b7b3cSmrg
919145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
920578741aaSmrg
921145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
922145b7b3cSmrg	return -1;
923145b7b3cSmrg
924145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
925578741aaSmrg
926145b7b3cSmrg    if (VALUE_TEXT(w, promptNum) == NULL)
927145b7b3cSmrg	return -1;
928145b7b3cSmrg
929145b7b3cSmrg    if (value == NULL) {
930145b7b3cSmrg	bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum));
931145b7b3cSmrg    } else {
932145b7b3cSmrg	strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum));
933145b7b3cSmrg	VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0';
934145b7b3cSmrg    }
935145b7b3cSmrg
936145b7b3cSmrg    VALUE_SHOW_START(w, promptNum) = 0;
937145b7b3cSmrg    VALUE_SHOW_END(w, promptNum) = 0;
938145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
939578741aaSmrg
940145b7b3cSmrg    return 0;
941145b7b3cSmrg}
942145b7b3cSmrg
943145b7b3cSmrg_X_INTERNAL
944145b7b3cSmrgconst char *
945145b7b3cSmrgGetValue(Widget ctx, int promptNum)
946145b7b3cSmrg{
947145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
948145b7b3cSmrg
949145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
950578741aaSmrg
951145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
952145b7b3cSmrg	return NULL;
953145b7b3cSmrg
954145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
955145b7b3cSmrg
956145b7b3cSmrg    return VALUE_TEXT(w, promptNum);
957145b7b3cSmrg}
958145b7b3cSmrg
959145b7b3cSmrg
960145b7b3cSmrgstatic void
961145b7b3cSmrgrealizeDeleteChar (LoginWidget ctx)
962145b7b3cSmrg{
963145b7b3cSmrg    if (ctx->login.state == PROMPTING) {
964145b7b3cSmrg	int promptNum = ctx->login.activePrompt;
965145b7b3cSmrg	int redrawFrom = PROMPT_CURSOR(ctx, promptNum);
966578741aaSmrg
967145b7b3cSmrg	if (PROMPT_CURSOR(ctx,promptNum) <  (int)strlen(VALUE_TEXT(ctx,promptNum))) {
968026e32a9Smlelstv	    if (redrawFrom <= VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
969026e32a9Smlelstv		if (redrawFrom > 0)
970026e32a9Smlelstv			redrawFrom--;
971026e32a9Smlelstv		EraseValue (ctx, 0, promptNum);
972026e32a9Smlelstv		VALUE_SHOW_START(ctx, ctx->login.activePrompt) = redrawFrom;
973145b7b3cSmrg	    } else {
974145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
975145b7b3cSmrg	    }
976145b7b3cSmrg	    strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
977145b7b3cSmrg		   VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1);
978145b7b3cSmrg	    DrawValue (ctx, redrawFrom, promptNum);
979145b7b3cSmrg	}
980145b7b3cSmrg    }
981145b7b3cSmrg}
982145b7b3cSmrg
983145b7b3cSmrg/*ARGSUSED*/
984145b7b3cSmrgstatic void
985145b7b3cSmrgDeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
986145b7b3cSmrg{
987145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
988145b7b3cSmrg
989145b7b3cSmrg    RemoveFail (ctx);
990145b7b3cSmrg
991145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
992145b7b3cSmrg	return;
993145b7b3cSmrg    }
994145b7b3cSmrg
995145b7b3cSmrg    XorCursor (ctx);
996145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0) {
997145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
998145b7b3cSmrg	realizeDeleteChar(ctx);
999145b7b3cSmrg    }
1000578741aaSmrg    XorCursor (ctx);
1001145b7b3cSmrg}
1002145b7b3cSmrg
1003145b7b3cSmrg/*ARGSUSED*/
1004145b7b3cSmrgstatic void
1005145b7b3cSmrgDeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1006145b7b3cSmrg{
1007145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1008145b7b3cSmrg
1009145b7b3cSmrg    RemoveFail (ctx);
1010145b7b3cSmrg
1011145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1012145b7b3cSmrg	return;
1013145b7b3cSmrg    }
1014145b7b3cSmrg
1015145b7b3cSmrg    XorCursor (ctx);
1016145b7b3cSmrg    realizeDeleteChar(ctx);
1017578741aaSmrg    XorCursor (ctx);
1018145b7b3cSmrg}
1019145b7b3cSmrg
1020145b7b3cSmrg/*ARGSUSED*/
1021145b7b3cSmrgstatic void
1022145b7b3cSmrgMoveBackwardChar (
1023145b7b3cSmrg    Widget	ctxw,
1024145b7b3cSmrg    XEvent	*event,
1025145b7b3cSmrg    String	*params,
1026145b7b3cSmrg    Cardinal	*num_params)
1027145b7b3cSmrg{
1028145b7b3cSmrg    LoginWidget	ctx = (LoginWidget)ctxw;
1029145b7b3cSmrg
1030145b7b3cSmrg    RemoveFail (ctx);
1031145b7b3cSmrg
1032145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1033145b7b3cSmrg	return;
1034145b7b3cSmrg    }
1035145b7b3cSmrg
1036145b7b3cSmrg    XorCursor (ctx);
1037145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0)
1038145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
1039145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
1040145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1041145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt)
1042145b7b3cSmrg	    = CUR_PROMPT_CURSOR(ctx);
1043145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1044145b7b3cSmrg    }
1045145b7b3cSmrg    XorCursor (ctx);
1046145b7b3cSmrg}
1047145b7b3cSmrg
1048145b7b3cSmrg/*ARGSUSED*/
1049145b7b3cSmrgstatic void
1050145b7b3cSmrgMoveForwardChar (
1051145b7b3cSmrg    Widget	ctxw,
1052145b7b3cSmrg    XEvent	*event,
1053145b7b3cSmrg    String	*params,
1054145b7b3cSmrg    Cardinal	*num_params)
1055145b7b3cSmrg{
1056145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1057145b7b3cSmrg
1058145b7b3cSmrg    RemoveFail (ctx);
1059145b7b3cSmrg
1060145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1061145b7b3cSmrg	return;
1062145b7b3cSmrg    }
1063145b7b3cSmrg
1064145b7b3cSmrg    XorCursor (ctx);
1065145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) <
1066145b7b3cSmrg	(int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) {
1067145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) += 1;
1068145b7b3cSmrg	if (VALUE_SHOW_END(ctx, ctx->login.activePrompt)
1069145b7b3cSmrg	    < CUR_PROMPT_CURSOR(ctx)) {
1070145b7b3cSmrg	    EraseValue(ctx, 0, ctx->login.activePrompt);
1071145b7b3cSmrg	    DrawValue(ctx, 0, ctx->login.activePrompt);
1072145b7b3cSmrg	}
1073145b7b3cSmrg    }
1074145b7b3cSmrg    XorCursor (ctx);
1075145b7b3cSmrg}
1076145b7b3cSmrg
1077145b7b3cSmrg/*ARGSUSED*/
1078145b7b3cSmrgstatic void
1079145b7b3cSmrgMoveToBegining (
1080145b7b3cSmrg    Widget	ctxw,
1081145b7b3cSmrg    XEvent	*event,
1082145b7b3cSmrg    String	*params,
1083145b7b3cSmrg    Cardinal	*num_params)
1084145b7b3cSmrg{
1085145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1086145b7b3cSmrg
1087145b7b3cSmrg    RemoveFail (ctx);
1088145b7b3cSmrg
1089145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1090145b7b3cSmrg	return;
1091145b7b3cSmrg    }
1092145b7b3cSmrg
1093145b7b3cSmrg    XorCursor (ctx);
1094145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = 0;
1095145b7b3cSmrg    if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) {
1096145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1097145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0;
1098145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1099145b7b3cSmrg    }
1100145b7b3cSmrg    XorCursor (ctx);
1101145b7b3cSmrg}
1102145b7b3cSmrg
1103145b7b3cSmrg/*ARGSUSED*/
1104145b7b3cSmrgstatic void
1105145b7b3cSmrgMoveToEnd (
1106145b7b3cSmrg    Widget	ctxw,
1107145b7b3cSmrg    XEvent	*event,
1108145b7b3cSmrg    String	*params,
1109145b7b3cSmrg    Cardinal	*num_params)
1110145b7b3cSmrg{
1111145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1112145b7b3cSmrg
1113145b7b3cSmrg    RemoveFail (ctx);
1114145b7b3cSmrg
1115145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1116145b7b3cSmrg	return;
1117145b7b3cSmrg    }
1118145b7b3cSmrg
1119145b7b3cSmrg    XorCursor (ctx);
1120145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt));
1121145b7b3cSmrg    if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) {
1122145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1123145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1124145b7b3cSmrg    }
1125145b7b3cSmrg    XorCursor (ctx);
1126145b7b3cSmrg}
1127145b7b3cSmrg
1128145b7b3cSmrg/*ARGSUSED*/
1129145b7b3cSmrgstatic void
1130145b7b3cSmrgEraseToEndOfLine (
1131145b7b3cSmrg    Widget	ctxw,
1132145b7b3cSmrg    XEvent	*event,
1133145b7b3cSmrg    String	*params,
1134145b7b3cSmrg    Cardinal	*num_params)
1135145b7b3cSmrg{
1136145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1137145b7b3cSmrg
1138145b7b3cSmrg    RemoveFail (ctx);
1139145b7b3cSmrg
1140145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1141145b7b3cSmrg	return;
1142145b7b3cSmrg    }
1143145b7b3cSmrg
1144145b7b3cSmrg    XorCursor (ctx);
1145145b7b3cSmrg    EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt);
1146145b7b3cSmrg    bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) +
1147145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx),
1148145b7b3cSmrg	  VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) -
1149145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx));
1150145b7b3cSmrg    XorCursor (ctx);
1151145b7b3cSmrg}
1152145b7b3cSmrg
1153145b7b3cSmrg/*ARGSUSED*/
1154145b7b3cSmrgstatic void
1155145b7b3cSmrgEraseLine (
1156145b7b3cSmrg    Widget	ctxw,
1157145b7b3cSmrg    XEvent	*event,
1158145b7b3cSmrg    String	*params,
1159145b7b3cSmrg    Cardinal	*num_params)
1160145b7b3cSmrg{
1161145b7b3cSmrg    MoveToBegining (ctxw, event, params, num_params);
1162145b7b3cSmrg    EraseToEndOfLine (ctxw, event, params, num_params);
1163145b7b3cSmrg}
1164145b7b3cSmrg
1165145b7b3cSmrg/*ARGSUSED*/
1166145b7b3cSmrgstatic void
1167145b7b3cSmrgFinishField (
1168145b7b3cSmrg    Widget	ctxw,
1169145b7b3cSmrg    XEvent	*event,
1170145b7b3cSmrg    String	*params,
1171145b7b3cSmrg    Cardinal	*num_params)
1172145b7b3cSmrg{
1173145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1174145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1175145b7b3cSmrg    int nextPrompt;
1176145b7b3cSmrg
1177145b7b3cSmrg    RemoveFail (ctx);
1178145b7b3cSmrg
1179145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1180145b7b3cSmrg	return;
1181145b7b3cSmrg    }
1182145b7b3cSmrg
1183145b7b3cSmrg    XorCursor (ctx);
1184145b7b3cSmrg
1185145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) {
1186145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1187145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1188145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1189145b7b3cSmrg	    break;
1190145b7b3cSmrg	}
1191145b7b3cSmrg    }
1192145b7b3cSmrg    if (nextPrompt > LAST_PROMPT) {
1193145b7b3cSmrg	ctx->login.state = DONE;
1194145b7b3cSmrg	(*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
1195145b7b3cSmrg	Debug("FinishField #%d: now DONE\n", promptNum);
1196145b7b3cSmrg    } else {
1197145b7b3cSmrg	Debug("FinishField #%d: %d next\n", promptNum, nextPrompt);
1198145b7b3cSmrg    }
1199145b7b3cSmrg
1200145b7b3cSmrg    XorCursor (ctx);
1201145b7b3cSmrg}
1202145b7b3cSmrg
1203145b7b3cSmrg/*ARGSUSED*/
1204145b7b3cSmrgstatic void
1205145b7b3cSmrgTabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1206145b7b3cSmrg{
1207145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1208145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1209145b7b3cSmrg    int nextPrompt;
1210145b7b3cSmrg
1211145b7b3cSmrg    RemoveFail (ctx);
1212145b7b3cSmrg
1213145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1214145b7b3cSmrg	return;
1215145b7b3cSmrg    }
1216145b7b3cSmrg
1217145b7b3cSmrg    XorCursor (ctx);
1218145b7b3cSmrg
1219145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) {
1220145b7b3cSmrg	if (nextPrompt > LAST_PROMPT) {
1221145b7b3cSmrg	    nextPrompt = 0;
1222145b7b3cSmrg	}
1223578741aaSmrg
1224145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1225145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1226145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1227145b7b3cSmrg	    break;
1228145b7b3cSmrg	}
1229145b7b3cSmrg    }
1230145b7b3cSmrg    XorCursor (ctx);
1231145b7b3cSmrg}
1232145b7b3cSmrg
1233145b7b3cSmrg/*ARGSUSED*/
1234145b7b3cSmrgstatic void
1235145b7b3cSmrgAllowAccess (
1236145b7b3cSmrg    Widget	ctxw,
1237145b7b3cSmrg    XEvent	*event,
1238145b7b3cSmrg    String	*params,
1239145b7b3cSmrg    Cardinal	*num_params)
1240145b7b3cSmrg{
1241145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1242145b7b3cSmrg    Arg	arglist[1];
1243145b7b3cSmrg    Boolean allow;
1244145b7b3cSmrg
1245145b7b3cSmrg    RemoveFail (ctx);
1246145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
1247145b7b3cSmrg    XtGetValues ((Widget) ctx, arglist, 1);
1248145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, !allow);
1249145b7b3cSmrg    XtSetValues ((Widget) ctx, arglist, 1);
1250145b7b3cSmrg}
1251145b7b3cSmrg
1252145b7b3cSmrg/*ARGSUSED*/
1253145b7b3cSmrgstatic void
1254145b7b3cSmrgSetSessionArgument (
1255145b7b3cSmrg    Widget	ctxw,
1256145b7b3cSmrg    XEvent	*event,
1257145b7b3cSmrg    String	*params,
1258145b7b3cSmrg    Cardinal	*num_params)
1259145b7b3cSmrg{
1260145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1261145b7b3cSmrg
1262145b7b3cSmrg    RemoveFail (ctx);
1263145b7b3cSmrg    if (ctx->login.sessionArg)
1264145b7b3cSmrg	XtFree (ctx->login.sessionArg);
1265145b7b3cSmrg    ctx->login.sessionArg = NULL;
1266145b7b3cSmrg    if (*num_params > 0) {
1267145b7b3cSmrg	ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
1268145b7b3cSmrg	if (ctx->login.sessionArg)
1269145b7b3cSmrg	    strcpy (ctx->login.sessionArg, params[0]);
1270145b7b3cSmrg	else
1271145b7b3cSmrg	    LogOutOfMem ("set session argument");
1272145b7b3cSmrg    }
1273145b7b3cSmrg}
1274145b7b3cSmrg
1275145b7b3cSmrg/*ARGSUSED*/
1276145b7b3cSmrgstatic void
1277145b7b3cSmrgRestartSession (
1278145b7b3cSmrg    Widget	ctxw,
1279145b7b3cSmrg    XEvent	*event,
1280145b7b3cSmrg    String	*params,
1281145b7b3cSmrg    Cardinal	*num_params)
1282145b7b3cSmrg{
1283145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1284145b7b3cSmrg
1285145b7b3cSmrg    XorCursor (ctx);
1286145b7b3cSmrg    RemoveFail (ctx);
1287145b7b3cSmrg    ctx->login.state = DONE;
1288145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
1289145b7b3cSmrg    XorCursor (ctx);
1290145b7b3cSmrg}
1291145b7b3cSmrg
1292145b7b3cSmrg/*ARGSUSED*/
1293145b7b3cSmrgstatic void
1294145b7b3cSmrgAbortSession (
1295145b7b3cSmrg    Widget	ctxw,
1296145b7b3cSmrg    XEvent	*event,
1297145b7b3cSmrg    String	*params,
1298145b7b3cSmrg    Cardinal	*num_params)
1299145b7b3cSmrg{
1300145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1301145b7b3cSmrg
1302145b7b3cSmrg    XorCursor (ctx);
1303145b7b3cSmrg    RemoveFail (ctx);
1304145b7b3cSmrg    ctx->login.state = DONE;
1305145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
1306145b7b3cSmrg    XorCursor (ctx);
1307145b7b3cSmrg}
1308145b7b3cSmrg
1309145b7b3cSmrg/*ARGSUSED*/
1310145b7b3cSmrgstatic void
1311145b7b3cSmrgAbortDisplay (
1312145b7b3cSmrg    Widget	ctxw,
1313145b7b3cSmrg    XEvent	*event,
1314145b7b3cSmrg    String	*params,
1315145b7b3cSmrg    Cardinal	*num_params)
1316145b7b3cSmrg{
1317145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1318145b7b3cSmrg
1319145b7b3cSmrg    XorCursor (ctx);
1320145b7b3cSmrg    RemoveFail (ctx);
1321145b7b3cSmrg    ctx->login.state = DONE;
1322145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
1323145b7b3cSmrg    XorCursor (ctx);
1324145b7b3cSmrg}
1325145b7b3cSmrg
1326145b7b3cSmrgstatic void
1327145b7b3cSmrgResetLogin (LoginWidget w)
1328145b7b3cSmrg{
1329145b7b3cSmrg    int i;
1330145b7b3cSmrg
1331145b7b3cSmrg    for (i = 0; i < NUM_PROMPTS ; i++) {
1332145b7b3cSmrg	EraseValue(w, 0, i);
1333145b7b3cSmrg	bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i));
1334145b7b3cSmrg	VALUE_SHOW_START(w, i) = 0;
1335145b7b3cSmrg	PROMPT_CURSOR(w, i) = 0;
1336145b7b3cSmrg    }
1337145b7b3cSmrg    w->login.state = PROMPTING;
1338145b7b3cSmrg    w->login.activePrompt = 0;
1339145b7b3cSmrg}
1340145b7b3cSmrg
1341145b7b3cSmrgstatic void
1342145b7b3cSmrgInitI18N(Widget ctxw)
1343145b7b3cSmrg{
1344145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1345145b7b3cSmrg    XIM         xim = (XIM) NULL;
1346145b7b3cSmrg    char *p;
1347145b7b3cSmrg
1348145b7b3cSmrg    ctx->login.xic = (XIC) NULL;
1349145b7b3cSmrg
1350145b7b3cSmrg    if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
1351145b7b3cSmrg	xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL);
1352145b7b3cSmrg
1353145b7b3cSmrg    if (!xim) {
1354145b7b3cSmrg	LogError("Failed to open input method\n");
1355145b7b3cSmrg	return;
1356145b7b3cSmrg    }
1357145b7b3cSmrg
1358145b7b3cSmrg    ctx->login.xic = XCreateIC(xim,
1359145b7b3cSmrg	XNInputStyle, (XIMPreeditNothing|XIMStatusNothing),
1360145b7b3cSmrg	XNClientWindow, ctx->core.window,
1361145b7b3cSmrg	XNFocusWindow,  ctx->core.window, NULL);
1362145b7b3cSmrg
1363145b7b3cSmrg    if (!ctx->login.xic) {
1364145b7b3cSmrg	LogError("Failed to create input context\n");
1365145b7b3cSmrg	XCloseIM(xim);
1366145b7b3cSmrg    }
1367145b7b3cSmrg    return;
1368145b7b3cSmrg}
1369145b7b3cSmrg
1370145b7b3cSmrg/* ARGSUSED */
1371145b7b3cSmrgstatic void
1372145b7b3cSmrgInsertChar (
1373145b7b3cSmrg    Widget	ctxw,
1374145b7b3cSmrg    XEvent	*event,
1375145b7b3cSmrg    String	*params,
1376145b7b3cSmrg    Cardinal	*num_params)
1377145b7b3cSmrg{
1378145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1379145b7b3cSmrg
1380145b7b3cSmrg    char strbuf[128];
1381145b7b3cSmrg    int  len, promptNum = ctx->login.activePrompt;
1382145b7b3cSmrg    KeySym  keysym = 0;
1383145b7b3cSmrg
1384145b7b3cSmrg    if (ctx->login.xic) {
1385145b7b3cSmrg	static Status status;
1386145b7b3cSmrg	len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf,
1387145b7b3cSmrg			      sizeof (strbuf), &keysym, &status);
1388145b7b3cSmrg    } else {
1389145b7b3cSmrg	static XComposeStatus compose_status = {NULL, 0};
1390145b7b3cSmrg	len = XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1391145b7b3cSmrg			     &keysym, &compose_status);
1392145b7b3cSmrg    }
1393145b7b3cSmrg    strbuf[len] = '\0';
1394145b7b3cSmrg
1395145b7b3cSmrg    /*
1396145b7b3cSmrg     * Note: You can override this default key handling
1397145b7b3cSmrg     * by the settings in the translation table
1398145b7b3cSmrg     * loginActionsTable at the end of this file.
1399145b7b3cSmrg     */
1400145b7b3cSmrg    switch (keysym) {
1401145b7b3cSmrg    case XK_Return:
1402145b7b3cSmrg    case XK_KP_Enter:
1403145b7b3cSmrg    case XK_Linefeed:
1404145b7b3cSmrg    case XK_Execute:
1405145b7b3cSmrg	FinishField(ctxw, event, params, num_params);
1406145b7b3cSmrg	return;
1407145b7b3cSmrg    case XK_BackSpace:
1408145b7b3cSmrg	DeleteBackwardChar(ctxw, event, params, num_params);
1409145b7b3cSmrg	return;
1410145b7b3cSmrg    case XK_Delete:
1411145b7b3cSmrg    case XK_KP_Delete:
1412145b7b3cSmrg    case DXK_Remove:
1413145b7b3cSmrg	/* Sorry, it's not a telex machine, it's a terminal */
1414145b7b3cSmrg	DeleteForwardChar(ctxw, event, params, num_params);
1415145b7b3cSmrg	return;
1416145b7b3cSmrg    case XK_Left:
1417145b7b3cSmrg    case XK_KP_Left:
1418145b7b3cSmrg	MoveBackwardChar(ctxw, event, params, num_params);
1419145b7b3cSmrg	return;
1420145b7b3cSmrg    case XK_Right:
1421145b7b3cSmrg    case XK_KP_Right:
1422145b7b3cSmrg	MoveForwardChar(ctxw, event, params, num_params);
1423145b7b3cSmrg	return;
1424145b7b3cSmrg    case XK_End:
1425145b7b3cSmrg    case XK_KP_End:
1426145b7b3cSmrg	MoveToEnd(ctxw, event, params, num_params);
1427145b7b3cSmrg	return;
1428145b7b3cSmrg    case XK_Home:
1429145b7b3cSmrg    case XK_KP_Home:
1430145b7b3cSmrg	MoveToBegining(ctxw, event, params, num_params);
1431145b7b3cSmrg	return;
1432145b7b3cSmrg    default:
1433145b7b3cSmrg	if (len == 0) {
1434145b7b3cSmrg	    if (!IsModifierKey(keysym))  /* it's not a modifier */
1435145b7b3cSmrg		XBell(XtDisplay(ctxw), 60);
1436145b7b3cSmrg	    return;
1437145b7b3cSmrg	} else
1438145b7b3cSmrg	    break;
1439145b7b3cSmrg    }
1440145b7b3cSmrg
1441578741aaSmrg    if (ctx->login.state == PROMPTING) {
1442145b7b3cSmrg	if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >=
1443145b7b3cSmrg	     (VALUE_TEXT_MAX(ctx,promptNum) - 1))) {
1444145b7b3cSmrg	    len = VALUE_TEXT_MAX(ctx,promptNum) -
1445145b7b3cSmrg		strlen(VALUE_TEXT(ctx, promptNum)) - 2;
1446145b7b3cSmrg	}
1447145b7b3cSmrg    }
1448145b7b3cSmrg    EraseCursor (ctx);
1449145b7b3cSmrg    RemoveFail (ctx);
1450145b7b3cSmrg    if (len != 0)
1451145b7b3cSmrg    {
1452145b7b3cSmrg	if (ctx->login.state == PROMPTING) {
1453145b7b3cSmrg	    EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1454145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len,
1455145b7b3cSmrg		    VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1456145b7b3cSmrg		    strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1);
1457145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1458145b7b3cSmrg		     strbuf, len);
1459145b7b3cSmrg	    DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1460145b7b3cSmrg	    PROMPT_CURSOR(ctx, promptNum) += len;
1461145b7b3cSmrg	}
1462145b7b3cSmrg    }
1463145b7b3cSmrg    XorCursor (ctx);
1464145b7b3cSmrg}
1465145b7b3cSmrg
1466145b7b3cSmrg
1467145b7b3cSmrg/**** Copied from xclock.c - original author: Keith Packard ****/
1468145b7b3cSmrg#ifdef USE_XFT
1469145b7b3cSmrgstatic XtConvertArgRec xftColorConvertArgs[] = {
1470145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1471145b7b3cSmrg     sizeof(Screen *)},
1472145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
1473145b7b3cSmrg     sizeof(Colormap)}
1474145b7b3cSmrg};
1475145b7b3cSmrg
1476578741aaSmrg# define	donestr(type, value, tstr) \
1477145b7b3cSmrg	{							\
1478145b7b3cSmrg	    if (toVal->addr != NULL) {				\
1479145b7b3cSmrg		if (toVal->size < sizeof(type)) {		\
1480145b7b3cSmrg		    toVal->size = sizeof(type);			\
1481145b7b3cSmrg		    XtDisplayStringConversionWarning(dpy, 	\
1482145b7b3cSmrg			(char*) fromVal->addr, tstr);		\
1483145b7b3cSmrg		    return False;				\
1484145b7b3cSmrg		}						\
1485145b7b3cSmrg		*(type*)(toVal->addr) = (value);		\
1486145b7b3cSmrg	    }							\
1487145b7b3cSmrg	    else {						\
1488145b7b3cSmrg		static type static_val;				\
1489145b7b3cSmrg		static_val = (value);				\
1490145b7b3cSmrg		toVal->addr = (XPointer)&static_val;		\
1491145b7b3cSmrg	    }							\
1492145b7b3cSmrg	    toVal->size = sizeof(type);				\
1493145b7b3cSmrg	    return True;					\
1494145b7b3cSmrg	}
1495145b7b3cSmrg
1496145b7b3cSmrgstatic void
1497145b7b3cSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1498145b7b3cSmrg		 XrmValuePtr args, Cardinal *num_args)
1499145b7b3cSmrg{
1500145b7b3cSmrg    Screen	*screen;
1501145b7b3cSmrg    Colormap	colormap;
1502145b7b3cSmrg    XftColor	*color;
1503578741aaSmrg
1504145b7b3cSmrg    if (*num_args != 2)
1505145b7b3cSmrg    {
1506145b7b3cSmrg	XtAppErrorMsg (app,
1507145b7b3cSmrg		       "freeXftColor", "wrongParameters",
1508145b7b3cSmrg		       "XtToolkitError",
1509145b7b3cSmrg		       "Freeing an XftColor requires screen and colormap arguments",
1510145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1511145b7b3cSmrg	return;
1512145b7b3cSmrg    }
1513145b7b3cSmrg
1514145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1515145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1516145b7b3cSmrg    color = (XftColor *) toVal->addr;
1517145b7b3cSmrg    XftColorFree (DisplayOfScreen (screen),
1518145b7b3cSmrg		  DefaultVisual (DisplayOfScreen (screen),
1519145b7b3cSmrg				 XScreenNumberOfScreen (screen)),
1520145b7b3cSmrg		  colormap, color);
1521145b7b3cSmrg}
1522578741aaSmrg
1523145b7b3cSmrgstatic Boolean
1524145b7b3cSmrgXmuCvtStringToXftColor(Display *dpy,
1525145b7b3cSmrg		       XrmValue *args, Cardinal *num_args,
1526145b7b3cSmrg		       XrmValue *fromVal, XrmValue *toVal,
1527145b7b3cSmrg		       XtPointer *converter_data)
1528145b7b3cSmrg{
1529145b7b3cSmrg    char	    *spec;
1530145b7b3cSmrg    XRenderColor    renderColor;
1531145b7b3cSmrg    XftColor	    xftColor;
1532145b7b3cSmrg    Screen	    *screen;
1533145b7b3cSmrg    Colormap	    colormap;
1534578741aaSmrg
1535145b7b3cSmrg    if (*num_args != 2)
1536145b7b3cSmrg    {
1537145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1538145b7b3cSmrg		       "cvtStringToXftColor", "wrongParameters",
1539145b7b3cSmrg		       "XtToolkitError",
1540145b7b3cSmrg		       "String to render color conversion needs screen and colormap arguments",
1541145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1542145b7b3cSmrg	return False;
1543145b7b3cSmrg    }
1544145b7b3cSmrg
1545145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1546145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1547145b7b3cSmrg
1548145b7b3cSmrg    spec = (char *) fromVal->addr;
1549145b7b3cSmrg    if (strcasecmp (spec, XtDefaultForeground) == 0)
1550145b7b3cSmrg    {
1551145b7b3cSmrg	renderColor.red = 0;
1552145b7b3cSmrg	renderColor.green = 0;
1553145b7b3cSmrg	renderColor.blue = 0;
1554145b7b3cSmrg	renderColor.alpha = 0xffff;
1555145b7b3cSmrg    }
1556145b7b3cSmrg    else if (strcasecmp (spec, XtDefaultBackground) == 0)
1557145b7b3cSmrg    {
1558145b7b3cSmrg	renderColor.red = 0xffff;
1559145b7b3cSmrg	renderColor.green = 0xffff;
1560145b7b3cSmrg	renderColor.blue = 0xffff;
1561145b7b3cSmrg	renderColor.alpha = 0xffff;
1562145b7b3cSmrg    }
1563145b7b3cSmrg    else if (!XRenderParseColor (dpy, spec, &renderColor))
1564145b7b3cSmrg	return False;
1565578741aaSmrg    if (!XftColorAllocValue (dpy,
1566145b7b3cSmrg			     DefaultVisual (dpy,
1567145b7b3cSmrg					    XScreenNumberOfScreen (screen)),
1568145b7b3cSmrg			     colormap,
1569145b7b3cSmrg			     &renderColor,
1570145b7b3cSmrg			     &xftColor))
1571145b7b3cSmrg	return False;
1572578741aaSmrg
1573145b7b3cSmrg    donestr (XftColor, xftColor, XtRXftColor);
1574145b7b3cSmrg}
1575145b7b3cSmrg
1576145b7b3cSmrgstatic void
1577145b7b3cSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1578145b7b3cSmrg		XrmValuePtr args, Cardinal *num_args)
1579145b7b3cSmrg{
1580145b7b3cSmrg    Screen  *screen;
1581145b7b3cSmrg    XftFont *font;
1582578741aaSmrg
1583145b7b3cSmrg    if (*num_args != 1)
1584145b7b3cSmrg    {
1585145b7b3cSmrg	XtAppErrorMsg (app,
1586145b7b3cSmrg		       "freeXftFont", "wrongParameters",
1587145b7b3cSmrg		       "XtToolkitError",
1588145b7b3cSmrg		       "Freeing an XftFont requires screen argument",
1589145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1590145b7b3cSmrg	return;
1591145b7b3cSmrg    }
1592145b7b3cSmrg
1593145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1594145b7b3cSmrg    font = *((XftFont **) toVal->addr);
1595145b7b3cSmrg    if (font)
1596145b7b3cSmrg	XftFontClose (DisplayOfScreen (screen), font);
1597145b7b3cSmrg}
1598145b7b3cSmrg
1599145b7b3cSmrgstatic Boolean
1600145b7b3cSmrgXmuCvtStringToXftFont(Display *dpy,
1601145b7b3cSmrg		      XrmValue *args, Cardinal *num_args,
1602145b7b3cSmrg		      XrmValue *fromVal, XrmValue *toVal,
1603145b7b3cSmrg		      XtPointer *converter_data)
1604145b7b3cSmrg{
1605145b7b3cSmrg    char    *name;
1606145b7b3cSmrg    XftFont *font;
1607145b7b3cSmrg    Screen  *screen;
1608578741aaSmrg
1609145b7b3cSmrg    if (*num_args != 1)
1610145b7b3cSmrg    {
1611145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1612145b7b3cSmrg		       "cvtStringToXftFont", "wrongParameters",
1613145b7b3cSmrg		       "XtToolkitError",
1614145b7b3cSmrg		       "String to XftFont conversion needs screen argument",
1615145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1616145b7b3cSmrg	return False;
1617145b7b3cSmrg    }
1618145b7b3cSmrg
1619145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1620145b7b3cSmrg    name = (char *) fromVal->addr;
1621578741aaSmrg
1622145b7b3cSmrg    font = XftFontOpenName (dpy,
1623145b7b3cSmrg			    XScreenNumberOfScreen (screen),
1624145b7b3cSmrg			    name);
1625145b7b3cSmrg    if (font)
1626145b7b3cSmrg    {
1627145b7b3cSmrg	donestr (XftFont *, font, XtRXftFont);
1628145b7b3cSmrg    }
1629145b7b3cSmrg    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
1630145b7b3cSmrg    return False;
1631145b7b3cSmrg}
1632145b7b3cSmrg
1633145b7b3cSmrgstatic XtConvertArgRec xftFontConvertArgs[] = {
1634145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1635145b7b3cSmrg     sizeof(Screen *)},
1636145b7b3cSmrg};
1637145b7b3cSmrg
1638145b7b3cSmrg
1639145b7b3cSmrgstatic int
1640145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len)
1641145b7b3cSmrg{
1642145b7b3cSmrg    XGlyphInfo  extents;
1643145b7b3cSmrg
1644145b7b3cSmrg    XftTextExtents8 (dpy, font, string, len, &extents);
1645145b7b3cSmrg
1646145b7b3cSmrg    return extents.xOff;
1647145b7b3cSmrg}
1648145b7b3cSmrg
1649145b7b3cSmrg#endif /* USE_XFT */
1650145b7b3cSmrg
1651578741aaSmrgstatic void
1652145b7b3cSmrgClassInitialize(void)
1653145b7b3cSmrg{
1654145b7b3cSmrg#ifdef USE_XFT
1655578741aaSmrg    XtSetTypeConverter (XtRString, XtRXftColor,
1656578741aaSmrg			XmuCvtStringToXftColor,
1657145b7b3cSmrg			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
1658145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftColor);
1659145b7b3cSmrg    XtSetTypeConverter (XtRString, XtRXftFont,
1660145b7b3cSmrg			XmuCvtStringToXftFont,
1661145b7b3cSmrg			xftFontConvertArgs, XtNumber(xftFontConvertArgs),
1662145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftFont);
1663145b7b3cSmrg#endif /* USE_XFT */
1664145b7b3cSmrg}
1665145b7b3cSmrg/**** End of portion borrowed from xclock ****/
1666145b7b3cSmrg
1667145b7b3cSmrg/* ARGSUSED */
1668145b7b3cSmrgstatic void Initialize (
1669145b7b3cSmrg    Widget greq,
1670145b7b3cSmrg    Widget gnew,
1671145b7b3cSmrg    ArgList args,
1672145b7b3cSmrg    Cardinal *num_args)
1673145b7b3cSmrg{
1674145b7b3cSmrg    LoginWidget w = (LoginWidget)gnew;
1675145b7b3cSmrg    XtGCMask	valuemask, xvaluemask;
1676145b7b3cSmrg    XGCValues	myXGCV;
1677145b7b3cSmrg    Arg		position[2];
1678145b7b3cSmrg    Position	x, y;
1679145b7b3cSmrg#ifdef USE_XINERAMA
1680145b7b3cSmrg    XineramaScreenInfo *screens;
1681145b7b3cSmrg    int                 s_num;
1682145b7b3cSmrg#endif
1683145b7b3cSmrg    int 	rv = 0;
1684578741aaSmrg
1685145b7b3cSmrg    myXGCV.foreground = w->login.hipixel;
1686145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1687145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1688145b7b3cSmrg    w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV);
1689145b7b3cSmrg
1690145b7b3cSmrg    myXGCV.foreground = w->login.shdpixel;
1691145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1692145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1693145b7b3cSmrg    w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV);
1694145b7b3cSmrg
1695b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1696b7d26471Smrg    myXGCV.background = w->core.background_pixel;
1697b7d26471Smrg    valuemask = GCForeground | GCBackground;
1698b7d26471Smrg    w->login.inpGC = XtGetGC(gnew, valuemask, &myXGCV);
1699b7d26471Smrg
1700145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text);
1701145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1702145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1703145b7b3cSmrg#ifndef USE_XFT
1704145b7b3cSmrg    if (w->login.textFont) {
1705145b7b3cSmrg	myXGCV.font = w->login.textFont->fid;
1706145b7b3cSmrg	valuemask |= GCFont;
1707145b7b3cSmrg    }
1708578741aaSmrg#endif
1709145b7b3cSmrg    w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
1710b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1711145b7b3cSmrg    w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
1712145b7b3cSmrg
1713b7d26471Smrg    myXGCV.foreground = TEXT_COLOR(text) ^ w->login.inppixel;
1714145b7b3cSmrg    myXGCV.function = GXxor;
1715145b7b3cSmrg    xvaluemask = valuemask | GCFunction;
1716145b7b3cSmrg    w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1717145b7b3cSmrg
1718145b7b3cSmrg#ifndef USE_XFT
1719145b7b3cSmrg    /*
1720145b7b3cSmrg     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
1721329eaa64Smrg     * returns the currently contained font.
1722145b7b3cSmrg     */
1723145b7b3cSmrg
1724145b7b3cSmrg    if (w->login.textFont == NULL)
1725145b7b3cSmrg	w->login.textFont = XQueryFont (XtDisplay (w),
1726145b7b3cSmrg		XGContextFromGC (XDefaultGCOfScreen (XtScreen (w))));
1727145b7b3cSmrg
1728145b7b3cSmrg    xvaluemask = valuemask;
1729145b7b3cSmrg    if (w->login.promptFont == NULL)
1730145b7b3cSmrg        w->login.promptFont = w->login.textFont;
1731145b7b3cSmrg    else
1732145b7b3cSmrg	xvaluemask |= GCFont;
1733145b7b3cSmrg
1734145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(prompt);
1735145b7b3cSmrg    myXGCV.font = w->login.promptFont->fid;
1736145b7b3cSmrg    w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1737145b7b3cSmrg
1738145b7b3cSmrg    xvaluemask = valuemask;
1739145b7b3cSmrg    if (w->login.greetFont == NULL)
1740629baa8cSmrg	w->login.greetFont = w->login.textFont;
1741145b7b3cSmrg    else
1742145b7b3cSmrg	xvaluemask |= GCFont;
1743145b7b3cSmrg
1744145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(greet);
1745145b7b3cSmrg    myXGCV.font = w->login.greetFont->fid;
1746145b7b3cSmrg    w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1747145b7b3cSmrg
1748145b7b3cSmrg    xvaluemask = valuemask;
1749145b7b3cSmrg    if (w->login.failFont == NULL)
1750145b7b3cSmrg	w->login.failFont = w->login.textFont;
1751145b7b3cSmrg    else
1752145b7b3cSmrg	xvaluemask |= GCFont;
1753145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(fail);
1754145b7b3cSmrg    myXGCV.font = w->login.failFont->fid;
1755145b7b3cSmrg    w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1756145b7b3cSmrg#endif /* USE_XFT */
1757145b7b3cSmrg
1758145b7b3cSmrg#ifdef XPM
1759145b7b3cSmrg    w->login.logoValid = False;
1760145b7b3cSmrg
1761145b7b3cSmrg    if (NULL != w->login.logoFileName)
1762145b7b3cSmrg    {
1763145b7b3cSmrg        XpmAttributes myAttributes = { 0 };
1764145b7b3cSmrg        Window tmpWindow = { 0 };
1765145b7b3cSmrg        struct stat myBuffer = { 0 };
1766145b7b3cSmrg        unsigned int myPixmapDepth = 0;
1767145b7b3cSmrg
1768145b7b3cSmrg        if (0 != stat(w->login.logoFileName, &myBuffer))
1769145b7b3cSmrg        {
1770145b7b3cSmrg            LogError("Unable to stat() pixmap file %s\n",
1771145b7b3cSmrg                w->login.logoFileName);
1772145b7b3cSmrg            w->login.logoValid = False;
1773145b7b3cSmrg            goto SkipXpmLoad;
1774145b7b3cSmrg        }
1775145b7b3cSmrg
1776145b7b3cSmrg        myAttributes.valuemask |= XpmReturnPixels;
1777145b7b3cSmrg        myAttributes.valuemask |= XpmReturnExtensions;
1778145b7b3cSmrg
1779145b7b3cSmrg        rv = XpmReadFileToPixmap(XtDisplay(w),		/* display */
1780145b7b3cSmrg	     RootWindowOfScreen(XtScreen(w)),		/* window */
1781145b7b3cSmrg	     w->login.logoFileName,			/* XPM filename */
1782145b7b3cSmrg	     &(w->login.logoPixmap),			/* pixmap */
1783145b7b3cSmrg	     &(w->login.logoMask),			/* pixmap mask */
1784145b7b3cSmrg	     &myAttributes);				/* XPM attributes */
1785578741aaSmrg
1786145b7b3cSmrg	if ( rv < 0 )
1787145b7b3cSmrg	{
1788145b7b3cSmrg	    LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName,
1789145b7b3cSmrg		     XpmGetErrorString(rv));
1790145b7b3cSmrg	    goto SkipXpmLoad;
1791145b7b3cSmrg	}
1792145b7b3cSmrg
1793145b7b3cSmrg	w->login.logoValid = True;
1794145b7b3cSmrg
1795145b7b3cSmrg        XGetGeometry(XtDisplay(w), w->login.logoPixmap,
1796145b7b3cSmrg            &tmpWindow,
1797145b7b3cSmrg            &(w->login.logoX),
1798145b7b3cSmrg            &(w->login.logoY),
1799145b7b3cSmrg            &(w->login.logoWidth),
1800145b7b3cSmrg            &(w->login.logoHeight),
1801145b7b3cSmrg            &(w->login.logoBorderWidth),
1802145b7b3cSmrg            &myPixmapDepth);
1803145b7b3cSmrg    } else {
1804145b7b3cSmrg	w->login.logoX = 0;
1805145b7b3cSmrg	w->login.logoY = 0;
1806145b7b3cSmrg	w->login.logoWidth = 0;
1807145b7b3cSmrg	w->login.logoHeight = 0;
1808145b7b3cSmrg	w->login.logoBorderWidth = 0;
1809145b7b3cSmrg    }
1810145b7b3cSmrg
1811145b7b3cSmrg
1812145b7b3cSmrgSkipXpmLoad:
1813145b7b3cSmrg#endif /* XPM */
1814145b7b3cSmrg    w->login.data.name[0] = '\0';
1815145b7b3cSmrg    w->login.data.passwd[0] = '\0';
1816145b7b3cSmrg    w->login.state = INITIALIZING;
1817145b7b3cSmrg    w->login.activePrompt = LOGIN_PROMPT_USERNAME;
1818145b7b3cSmrg    w->login.failUp = 0;
1819145b7b3cSmrg    w->login.fail = (char *) w->login.failMsg;
1820145b7b3cSmrg
1821145b7b3cSmrg    /* Set prompt defaults */
1822145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= NULL;
1823145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.namePrompt;
1824145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.data.name;
1825145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME)	= sizeof(w->login.data.name);
1826145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME)	= 0;
1827578741aaSmrg
1828145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= NULL;
1829145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.passwdPrompt;
1830145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.data.passwd;
1831145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD)	= sizeof(w->login.data.passwd);
1832145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD)	= 0;
1833145b7b3cSmrg
1834145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False);
1835145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False);
1836578741aaSmrg
1837145b7b3cSmrg    if (w->core.width == 0)
1838145b7b3cSmrg	w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
1839145b7b3cSmrg    if (w->core.height == 0) {
1840145b7b3cSmrg	int fy = FAIL_Y(w);
1841145b7b3cSmrg	int pady = PAD_Y(w);
1842145b7b3cSmrg
1843145b7b3cSmrg#ifndef XPM
1844145b7b3cSmrg	w->core.height = fy + pady;	/* for stupid compilers */
1845145b7b3cSmrg#else
1846145b7b3cSmrg/*	w->core.height = fy + pady;	* for stupid compilers */
1847145b7b3cSmrg
1848145b7b3cSmrg        w->core.height = max(fy + pady,
1849145b7b3cSmrg            (w->login.logoHeight + (2*w->login.logoPadding)) + pady);
1850578741aaSmrg
1851145b7b3cSmrg#endif /* XPM */
1852145b7b3cSmrg    }
1853145b7b3cSmrg#ifdef USE_XINERAMA
1854145b7b3cSmrg    if (
1855145b7b3cSmrg	XineramaIsActive(XtDisplay(w)) &&
1856145b7b3cSmrg	(screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL
1857145b7b3cSmrg       )
1858145b7b3cSmrg    {
1859145b7b3cSmrg	if ((x = w->core.x) == -1)
1860145b7b3cSmrg	    x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2;
1861145b7b3cSmrg	if ((y = w->core.y) == -1)
1862145b7b3cSmrg	    y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3;
1863578741aaSmrg
1864145b7b3cSmrg	XFree(screens);
1865145b7b3cSmrg    }
1866145b7b3cSmrg    else
1867145b7b3cSmrg#endif
1868145b7b3cSmrg    {
1869145b7b3cSmrg	if ((x = w->core.x) == -1)
1870145b7b3cSmrg	    x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2;
1871145b7b3cSmrg	if ((y = w->core.y) == -1)
1872145b7b3cSmrg	    y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3;
1873145b7b3cSmrg    }
1874145b7b3cSmrg    XtSetArg (position[0], XtNx, x);
1875145b7b3cSmrg    XtSetArg (position[1], XtNy, y);
1876145b7b3cSmrg    XtSetValues (XtParent (w), position, (Cardinal) 2);
1877145b7b3cSmrg
1878145b7b3cSmrg    w->login.state = PROMPTING;
1879145b7b3cSmrg}
1880145b7b3cSmrg
1881578741aaSmrg
1882145b7b3cSmrgstatic void Realize (
1883145b7b3cSmrg     Widget gw,
1884145b7b3cSmrg     XtValueMask *valueMask,
1885145b7b3cSmrg     XSetWindowAttributes *attrs)
1886145b7b3cSmrg{
1887145b7b3cSmrg    LoginWidget	w = (LoginWidget) gw;
1888145b7b3cSmrg    Cursor cursor;
1889145b7b3cSmrg
1890145b7b3cSmrg    XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
1891145b7b3cSmrg		     *valueMask, attrs );
1892145b7b3cSmrg    InitI18N(gw);
1893145b7b3cSmrg
1894145b7b3cSmrg#ifdef USE_XFT
1895145b7b3cSmrg    w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w),
1896145b7b3cSmrg	   DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))),
1897145b7b3cSmrg				   w->core.colormap);
1898145b7b3cSmrg
1899145b7b3cSmrg#endif
1900145b7b3cSmrg
1901145b7b3cSmrg    cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr);
1902145b7b3cSmrg    XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor);
1903145b7b3cSmrg
1904145b7b3cSmrg#ifdef XPM
1905578741aaSmrg    /*
1906145b7b3cSmrg     * Check if Pixmap was valid
1907145b7b3cSmrg     */
1908145b7b3cSmrg    if (True == w->login.logoValid)
1909145b7b3cSmrg    {
1910145b7b3cSmrg        /*
1911578741aaSmrg         * Create pixmap window
1912145b7b3cSmrg         */
1913145b7b3cSmrg        {
1914629baa8cSmrg            XSetWindowAttributes windowAttributes = {
1915629baa8cSmrg                .background_pixel = w->core.background_pixel,
1916629baa8cSmrg                .background_pixmap = None
1917629baa8cSmrg            };
1918145b7b3cSmrg
1919145b7b3cSmrg            w->login.logoWindow = XCreateWindow(XtDisplay(w),
1920145b7b3cSmrg                XtWindow(w),
1921145b7b3cSmrg                w->core.width - w->login.outframewidth -
1922145b7b3cSmrg                    w->login.logoWidth - w->login.logoPadding,
1923145b7b3cSmrg                (w->core.height - w->login.logoHeight) /2,
1924145b7b3cSmrg                w->login.logoWidth, w->login.logoHeight, 0,
1925145b7b3cSmrg                CopyFromParent, InputOutput, CopyFromParent,
1926629baa8cSmrg                CWBackPixel | CWBackPixmap, &windowAttributes);
1927145b7b3cSmrg        }
1928145b7b3cSmrg
1929145b7b3cSmrg        /*
1930145b7b3cSmrg         * check if we can use shape extension
1931145b7b3cSmrg         */
1932145b7b3cSmrg        if (True == w->login.useShape)
1933145b7b3cSmrg        {
1934145b7b3cSmrg            int foo, bar;
1935145b7b3cSmrg
1936145b7b3cSmrg            if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE)
1937145b7b3cSmrg            {
1938145b7b3cSmrg                XShapeCombineMask(XtDisplay(w), w->login.logoWindow,
1939145b7b3cSmrg                    ShapeBounding, w->login.logoX, w->login.logoY,
1940145b7b3cSmrg                    w->login.logoMask, ShapeSet);
1941145b7b3cSmrg            }
1942145b7b3cSmrg        }
1943145b7b3cSmrg
1944145b7b3cSmrg        XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow,
1945145b7b3cSmrg            w->login.logoPixmap);
1946145b7b3cSmrg        XMapWindow(XtDisplay(w), w->login.logoWindow);
1947145b7b3cSmrg    }
1948145b7b3cSmrg#endif /* XPM */
1949145b7b3cSmrg}
1950145b7b3cSmrg
1951145b7b3cSmrgstatic void Destroy (Widget gw)
1952145b7b3cSmrg{
1953145b7b3cSmrg    LoginWidget w = (LoginWidget)gw;
1954145b7b3cSmrg    bzero (w->login.data.name, NAME_LEN);
1955145b7b3cSmrg    bzero (w->login.data.passwd, PASSWORD_LEN);
1956145b7b3cSmrg
1957145b7b3cSmrg    if (PROMPT_TEXT(w,0) != NULL)
1958145b7b3cSmrg	XtFree(PROMPT_TEXT(w,0));
1959145b7b3cSmrg    if (PROMPT_TEXT(w,1) != NULL)
1960145b7b3cSmrg	XtFree(PROMPT_TEXT(w,1));
1961145b7b3cSmrg
1962145b7b3cSmrg#ifdef USE_XFT
1963145b7b3cSmrg    if (w->login.draw) {
1964145b7b3cSmrg	XftDrawDestroy(w->login.draw);
1965145b7b3cSmrg	w->login.draw = NULL;
1966145b7b3cSmrg    }
1967578741aaSmrg#endif
1968578741aaSmrg
1969145b7b3cSmrg    XtReleaseGC(gw, w->login.textGC);
1970145b7b3cSmrg    XtReleaseGC(gw, w->login.bgGC);
1971145b7b3cSmrg    XtReleaseGC(gw, w->login.xorGC);
1972145b7b3cSmrg#ifndef USE_XFT
1973145b7b3cSmrg    XtReleaseGC(gw, w->login.promptGC);
1974145b7b3cSmrg    XtReleaseGC(gw, w->login.greetGC);
1975145b7b3cSmrg    XtReleaseGC(gw, w->login.failGC);
1976145b7b3cSmrg#endif
1977145b7b3cSmrg    XtReleaseGC(gw, w->login.hiGC);
1978145b7b3cSmrg    XtReleaseGC(gw, w->login.shdGC);
1979b7d26471Smrg    XtReleaseGC(gw, w->login.inpGC);
1980145b7b3cSmrg
1981145b7b3cSmrg#ifdef XPM
1982145b7b3cSmrg    if (True == w->login.logoValid)
1983145b7b3cSmrg    {
1984145b7b3cSmrg        if (w->login.logoPixmap != 0)
1985145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoPixmap);
1986145b7b3cSmrg
1987145b7b3cSmrg        if (w->login.logoMask != 0)
1988145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoMask);
1989145b7b3cSmrg    }
1990145b7b3cSmrg#endif /* XPM */
1991145b7b3cSmrg}
1992145b7b3cSmrg
1993145b7b3cSmrg/* ARGSUSED */
1994145b7b3cSmrgstatic void Redisplay(
1995145b7b3cSmrg     Widget gw,
1996145b7b3cSmrg     XEvent *event,
1997145b7b3cSmrg     Region region)
1998145b7b3cSmrg{
1999145b7b3cSmrg    draw_it ((LoginWidget) gw);
2000145b7b3cSmrg}
2001145b7b3cSmrg
2002145b7b3cSmrg/*ARGSUSED*/
2003145b7b3cSmrgstatic Boolean SetValues (
2004145b7b3cSmrg    Widget  current,
2005145b7b3cSmrg    Widget  request,
2006145b7b3cSmrg    Widget  new,
2007145b7b3cSmrg    ArgList args,
2008145b7b3cSmrg    Cardinal *num_args)
2009145b7b3cSmrg{
2010145b7b3cSmrg    LoginWidget currentL, newL;
2011578741aaSmrg
2012145b7b3cSmrg    currentL = (LoginWidget) current;
2013145b7b3cSmrg    newL = (LoginWidget) new;
2014145b7b3cSmrg    if (GREETING (currentL) != GREETING (newL))
2015145b7b3cSmrg	return True;
2016145b7b3cSmrg    return False;
2017145b7b3cSmrg}
2018145b7b3cSmrg
2019145b7b3cSmrgstatic
2020145b7b3cSmrgchar defaultLoginTranslations [] =
2021145b7b3cSmrg"Ctrl<Key>H:	delete-previous-character() \n"
2022145b7b3cSmrg"Ctrl<Key>D:	delete-character() \n"
2023145b7b3cSmrg"Ctrl<Key>B:	move-backward-character() \n"
2024145b7b3cSmrg"Ctrl<Key>F:	move-forward-character() \n"
2025145b7b3cSmrg"Ctrl<Key>A:	move-to-begining() \n"
2026145b7b3cSmrg"Ctrl<Key>E:	move-to-end() \n"
2027145b7b3cSmrg"Ctrl<Key>K:	erase-to-end-of-line() \n"
2028145b7b3cSmrg"Ctrl<Key>U:	erase-line() \n"
2029145b7b3cSmrg"Ctrl<Key>X:	erase-line() \n"
2030145b7b3cSmrg"Ctrl<Key>C:	restart-session() \n"
2031145b7b3cSmrg"Ctrl<Key>\\\\:	abort-session() \n"
2032145b7b3cSmrg":Ctrl<Key>plus:	allow-all-access() \n"
2033145b7b3cSmrg"<Key>BackSpace:	delete-previous-character() \n"
2034145b7b3cSmrg#ifdef linux
2035145b7b3cSmrg"<Key>Delete:	delete-character() \n"
2036145b7b3cSmrg#else
2037145b7b3cSmrg"<Key>Delete:	delete-previous-character() \n"
2038145b7b3cSmrg#endif
2039145b7b3cSmrg"<Key>Return:	finish-field() \n"
2040145b7b3cSmrg"<Key>Tab:	tab-field() \n"
2041145b7b3cSmrg"<KeyPress>:	insert-char()"
2042145b7b3cSmrg;
2043145b7b3cSmrg
2044145b7b3cSmrgstatic
2045145b7b3cSmrgXtActionsRec loginActionsTable [] = {
2046145b7b3cSmrg  {"delete-previous-character",	DeleteBackwardChar},
2047145b7b3cSmrg  {"delete-character",		DeleteForwardChar},
2048145b7b3cSmrg  {"move-backward-character",	MoveBackwardChar},
2049145b7b3cSmrg  {"move-forward-character",	MoveForwardChar},
2050145b7b3cSmrg  {"move-to-begining",		MoveToBegining},
2051145b7b3cSmrg  {"move-to-end",		MoveToEnd},
2052145b7b3cSmrg  {"erase-to-end-of-line",	EraseToEndOfLine},
2053145b7b3cSmrg  {"erase-line",		EraseLine},
2054145b7b3cSmrg  {"finish-field", 		FinishField},
2055145b7b3cSmrg  {"tab-field", 		TabField},
2056145b7b3cSmrg  {"abort-session",		AbortSession},
2057145b7b3cSmrg  {"abort-display",		AbortDisplay},
2058145b7b3cSmrg  {"restart-session",		RestartSession},
2059145b7b3cSmrg  {"insert-char", 		InsertChar},
2060145b7b3cSmrg  {"set-session-argument",	SetSessionArgument},
2061145b7b3cSmrg  {"allow-all-access",		AllowAccess},
2062145b7b3cSmrg};
2063145b7b3cSmrg
2064145b7b3cSmrgLoginClassRec loginClassRec = {
2065145b7b3cSmrg    { /* core fields */
2066145b7b3cSmrg    /* superclass		*/	&widgetClassRec,
2067145b7b3cSmrg    /* class_name		*/	"Login",
2068145b7b3cSmrg    /* size			*/	sizeof(LoginRec),
2069145b7b3cSmrg    /* class_initialize		*/	ClassInitialize,
2070145b7b3cSmrg    /* class_part_initialize	*/	NULL,
2071145b7b3cSmrg    /* class_inited		*/	FALSE,
2072145b7b3cSmrg    /* initialize		*/	Initialize,
2073145b7b3cSmrg    /* initialize_hook		*/	NULL,
2074145b7b3cSmrg    /* realize			*/	Realize,
2075145b7b3cSmrg    /* actions			*/	loginActionsTable,
2076145b7b3cSmrg    /* num_actions		*/	XtNumber (loginActionsTable),
2077145b7b3cSmrg    /* resources		*/	resources,
2078145b7b3cSmrg    /* num_resources		*/	XtNumber(resources),
2079145b7b3cSmrg    /* xrm_class		*/	NULLQUARK,
2080145b7b3cSmrg    /* compress_motion		*/	TRUE,
2081145b7b3cSmrg    /* compress_exposure	*/	TRUE,
2082145b7b3cSmrg    /* compress_enterleave	*/	TRUE,
2083145b7b3cSmrg    /* visible_interest		*/	FALSE,
2084145b7b3cSmrg    /* destroy			*/	Destroy,
2085145b7b3cSmrg    /* resize			*/	NULL,
2086145b7b3cSmrg    /* expose			*/	Redisplay,
2087145b7b3cSmrg    /* set_values		*/	SetValues,
2088145b7b3cSmrg    /* set_values_hook		*/	NULL,
2089145b7b3cSmrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
2090145b7b3cSmrg    /* get_values_hook		*/	NULL,
2091145b7b3cSmrg    /* accept_focus		*/	NULL,
2092145b7b3cSmrg    /* version			*/	XtVersion,
2093145b7b3cSmrg    /* callback_private		*/	NULL,
2094145b7b3cSmrg    /* tm_table			*/	defaultLoginTranslations,
2095145b7b3cSmrg    /* query_geometry		*/	XtInheritQueryGeometry,
2096145b7b3cSmrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
2097145b7b3cSmrg    /* extension		*/	NULL
2098145b7b3cSmrg    }
2099145b7b3cSmrg};
2100145b7b3cSmrg
2101145b7b3cSmrgWidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
2102