Login.c revision 6cc8c0d3
1145b7b3cSmrg/*
2145b7b3cSmrg
3145b7b3cSmrgCopyright 1988, 1998  The Open Group
4145b7b3cSmrg
5145b7b3cSmrgPermission to use, copy, modify, distribute, and sell this software and its
6145b7b3cSmrgdocumentation for any purpose is hereby granted without fee, provided that
7145b7b3cSmrgthe above copyright notice appear in all copies and that both that
8145b7b3cSmrgcopyright notice and this permission notice appear in supporting
9145b7b3cSmrgdocumentation.
10145b7b3cSmrg
11145b7b3cSmrgThe above copyright notice and this permission notice shall be included
12145b7b3cSmrgin all copies or substantial portions of the Software.
13145b7b3cSmrg
14145b7b3cSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15145b7b3cSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16145b7b3cSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17145b7b3cSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18145b7b3cSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19145b7b3cSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20145b7b3cSmrgOTHER DEALINGS IN THE SOFTWARE.
21145b7b3cSmrg
22145b7b3cSmrgExcept as contained in this notice, the name of The Open Group shall
23145b7b3cSmrgnot be used in advertising or otherwise to promote the sale, use or
24145b7b3cSmrgother dealings in this Software without prior written authorization
25145b7b3cSmrgfrom The Open Group.
26145b7b3cSmrg
27145b7b3cSmrg*/
285ffd6003Smrg/*
29629baa8cSmrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
30145b7b3cSmrg *
31145b7b3cSmrg * Permission is hereby granted, free of charge, to any person obtaining a
325ffd6003Smrg * copy of this software and associated documentation files (the "Software"),
335ffd6003Smrg * to deal in the Software without restriction, including without limitation
345ffd6003Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
355ffd6003Smrg * and/or sell copies of the Software, and to permit persons to whom the
365ffd6003Smrg * Software is furnished to do so, subject to the following conditions:
37145b7b3cSmrg *
385ffd6003Smrg * The above copyright notice and this permission notice (including the next
395ffd6003Smrg * paragraph) shall be included in all copies or substantial portions of the
405ffd6003Smrg * Software.
41145b7b3cSmrg *
425ffd6003Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
435ffd6003Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
445ffd6003Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
455ffd6003Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
465ffd6003Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
475ffd6003Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
485ffd6003Smrg * DEALINGS IN THE SOFTWARE.
49145b7b3cSmrg */
50145b7b3cSmrg
51145b7b3cSmrg
52145b7b3cSmrg/*
53145b7b3cSmrg * xdm - display manager daemon
54145b7b3cSmrg * Author:  Keith Packard, MIT X Consortium
55145b7b3cSmrg *
56145b7b3cSmrg * Login.c
57145b7b3cSmrg */
58145b7b3cSmrg
59578741aaSmrg#include <X11/IntrinsicP.h>
60578741aaSmrg#include <X11/StringDefs.h>
61578741aaSmrg#include <X11/keysym.h>
62578741aaSmrg#include <X11/DECkeysym.h>
63578741aaSmrg#include <X11/Xfuncs.h>
64145b7b3cSmrg
65578741aaSmrg#include <stdio.h>
66578741aaSmrg#include <ctype.h>
67578741aaSmrg#include <time.h>
68578741aaSmrg#include <string.h>
69145b7b3cSmrg
70578741aaSmrg#include "dm.h"
71578741aaSmrg#include "dm_error.h"
72578741aaSmrg#include "greet.h"
73578741aaSmrg#include "LoginP.h"
74145b7b3cSmrg
75145b7b3cSmrg#ifdef XPM
76578741aaSmrg# include <sys/stat.h>
77578741aaSmrg# include <unistd.h>
78578741aaSmrg# include <X11/Xlib.h>
79578741aaSmrg# include <X11/xpm.h>
80578741aaSmrg# include <X11/extensions/shape.h>
81145b7b3cSmrg#endif /* XPM */
82145b7b3cSmrg
83145b7b3cSmrg#include <X11/cursorfont.h>
84145b7b3cSmrg
85145b7b3cSmrg#ifdef USE_XINERAMA
86578741aaSmrg# include <X11/extensions/Xinerama.h>
87145b7b3cSmrg#endif
88145b7b3cSmrg
89b7d26471Smrg#ifdef USE_XFT
90b7d26471Smrg# include <X11/extensions/Xrender.h>
91b7d26471Smrg#endif
92b7d26471Smrg
93145b7b3cSmrg#ifndef DEBUG
94145b7b3cSmrg# define XDM_ASSERT(a)	/* do nothing */
95145b7b3cSmrg#else
96145b7b3cSmrg# if defined(__STDC__) && __STDC_VERSION__ - 0 >= 199901L
97145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
98145b7b3cSmrg	Debug("Assertion failed in %s() at file %s line %d\n", \
99145b7b3cSmrg	      __func__, __FILE__, __LINE__); }
100145b7b3cSmrg# else
101145b7b3cSmrg#  define XDM_ASSERT(a)	if (!(a)) { \
102145b7b3cSmrg	Debug("Assertion failed at file %s line %d\n", __FILE__, __LINE__); }
103145b7b3cSmrg# endif
104145b7b3cSmrg#endif
105145b7b3cSmrg
106145b7b3cSmrgstatic void RedrawFail (LoginWidget w);
107145b7b3cSmrgstatic void ResetLogin (LoginWidget w);
108145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id);
109145b7b3cSmrgstatic void EraseCursor (LoginWidget w);
110145b7b3cSmrgstatic void XorCursor (LoginWidget w);
111145b7b3cSmrg
112145b7b3cSmrg#define offset(field) XtOffsetOf(LoginRec, login.field)
113145b7b3cSmrg#define goffset(field) XtOffsetOf(WidgetRec, core.field)
114145b7b3cSmrg
115145b7b3cSmrg
116145b7b3cSmrgstatic XtResource resources[] = {
117145b7b3cSmrg    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
118145b7b3cSmrg	goffset(width), XtRImmediate,	(XtPointer) 0},
119145b7b3cSmrg    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
120145b7b3cSmrg	goffset(height), XtRImmediate,	(XtPointer) 0},
121145b7b3cSmrg    {XtNx, XtCX, XtRPosition, sizeof (Position),
122145b7b3cSmrg	goffset(x), XtRImmediate,	(XtPointer) -1},
123145b7b3cSmrg    {XtNy, XtCY, XtRPosition, sizeof (Position),
124145b7b3cSmrg	goffset(y), XtRImmediate,	(XtPointer) -1},
125578741aaSmrg#ifndef USE_XFT
126145b7b3cSmrg    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
127145b7b3cSmrg        offset(textpixel), XtRString,	XtDefaultForeground},
128145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel),
129145b7b3cSmrg        offset(promptpixel), XtRString,	XtDefaultForeground},
130145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel),
131145b7b3cSmrg        offset(greetpixel), XtRString,	XtDefaultForeground},
132145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel),
133145b7b3cSmrg	offset(failpixel), XtRString,	XtDefaultForeground},
134145b7b3cSmrg#endif
135145b7b3cSmrg
136145b7b3cSmrg#ifdef DANCING
137145b7b3cSmrg/* added by Caolan McNamara */
138145b7b3cSmrg	{XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int),
139145b7b3cSmrg	offset(lastEventTime), XtRImmediate,	(XtPointer)0},
140145b7b3cSmrg/* end (caolan) */
141145b7b3cSmrg#endif /* DANCING */
142145b7b3cSmrg
143578741aaSmrg#ifdef XPM
144145b7b3cSmrg/* added by Ivan Griffin (ivan.griffin@ul.ie) */
145145b7b3cSmrg        {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*),
146145b7b3cSmrg        offset(logoFileName), XtRImmediate, (XtPointer)0},
147145b7b3cSmrg        {XtNuseShape, XtCUseShape, XtRBoolean, sizeof(Boolean),
148145b7b3cSmrg        offset(useShape), XtRImmediate, (XtPointer) True},
149145b7b3cSmrg        {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int),
150145b7b3cSmrg        offset(logoPadding), XtRImmediate, (XtPointer) 5},
151145b7b3cSmrg/* end (ivan) */
152145b7b3cSmrg#endif /* XPM */
153145b7b3cSmrg
154145b7b3cSmrg/* added by Amit Margalit */
155145b7b3cSmrg    {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel),
156145b7b3cSmrg	offset(hipixel), XtRString,	XtDefaultForeground},
157145b7b3cSmrg    {XtNshdColor, XtCForeground, XtRPixel, sizeof (Pixel),
158145b7b3cSmrg	offset(shdpixel), XtRString,	XtDefaultForeground},
159b7d26471Smrg    {XtNinpColor, XtCForeground, XtRPixel, sizeof (Pixel),
160b7d26471Smrg	offset(inppixel), XtRString,	XtDefaultBackground},
161145b7b3cSmrg    {XtNframeWidth, XtCFrameWidth, XtRInt, sizeof(int),
162145b7b3cSmrg        offset(outframewidth), XtRImmediate, (XtPointer) 1},
163145b7b3cSmrg    {XtNinnerFramesWidth, XtCFrameWidth, XtRInt, sizeof(int),
164145b7b3cSmrg        offset(inframeswidth), XtRImmediate, (XtPointer) 1},
165145b7b3cSmrg    {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int),
166145b7b3cSmrg        offset(sepwidth), XtRImmediate, (XtPointer) 1},
167145b7b3cSmrg/* end (amit) */
168145b7b3cSmrg
169578741aaSmrg#ifndef USE_XFT
170145b7b3cSmrg    {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
171629baa8cSmrg	offset (textFont), XtRString,	"*-new century schoolbook-medium-r-normal-*-180-*"},
172145b7b3cSmrg    {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
173629baa8cSmrg	offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"},
174145b7b3cSmrg    {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
175629baa8cSmrg	offset (greetFont), XtRString,	"*-new century schoolbook-bold-i-normal-*-240-*"},
176145b7b3cSmrg    {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
177145b7b3cSmrg	offset (failFont), XtRString,	"*-new century schoolbook-bold-r-normal-*-180-*"},
178145b7b3cSmrg#else /* USE_XFT */
179145b7b3cSmrg    {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
180145b7b3cSmrg        offset (textFace), XtRString, "Serif-18"},
181145b7b3cSmrg    {XtNpromptFace, XtCFace, XtRXftFont, sizeof (XftFont *),
182145b7b3cSmrg        offset (promptFace), XtRString, "Serif-18:bold"},
183145b7b3cSmrg    {XtNgreetFace, XtCFace, XtRXftFont, sizeof (XftFont *),
184145b7b3cSmrg        offset (greetFace), XtRString, "Serif-24:italic"},
185145b7b3cSmrg    {XtNfailFace, XtCFace, XtRXftFont, sizeof (XftFont *),
186145b7b3cSmrg        offset (failFace), XtRString, "Serif-18:bold"},
187145b7b3cSmrg    {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
188145b7b3cSmrg        offset(textcolor), XtRString,	XtDefaultForeground},
189145b7b3cSmrg    {XtNpromptColor, XtCForeground, XtRXftColor, sizeof(XftColor),
190145b7b3cSmrg        offset(promptcolor), XtRString,	XtDefaultForeground},
191145b7b3cSmrg    {XtNgreetColor, XtCForeground, XtRXftColor, sizeof(XftColor),
192145b7b3cSmrg        offset(greetcolor), XtRString,	XtDefaultForeground},
193145b7b3cSmrg    {XtNfailColor, XtCForeground, XtRXftColor, sizeof (XftColor),
194145b7b3cSmrg	offset(failcolor), XtRString,	XtDefaultForeground},
195145b7b3cSmrg#endif
196145b7b3cSmrg    {XtNgreeting, XtCGreeting, XtRString, sizeof (char *),
197629baa8cSmrg	offset(greeting), XtRString, "X Window System"},
198145b7b3cSmrg    {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *),
199145b7b3cSmrg	offset(unsecure_greet), XtRString, "This is an unsecure session"},
200145b7b3cSmrg    {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *),
201145b7b3cSmrg	offset(namePrompt), XtRString, "Login:  "},
202145b7b3cSmrg    {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *),
203145b7b3cSmrg	offset(passwdPrompt), XtRString, "Password:  "},
204145b7b3cSmrg    {XtNfail, XtCFail, XtRString, sizeof (char *),
205145b7b3cSmrg	offset(failMsg), XtRString,
206629baa8cSmrg	"Login incorrect or forbidden by policy"
207145b7b3cSmrg    },
208145b7b3cSmrg    {XtNchangePasswdMessage, XtCChangePasswdMessage, XtRString,
209145b7b3cSmrg	sizeof (char *), offset(passwdChangeMsg), XtRString,
210145b7b3cSmrg	(XtPointer) "Password Change Required" },
211145b7b3cSmrg    {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int),
212145b7b3cSmrg	offset(failTimeout), XtRImmediate, (XtPointer) 10},
213145b7b3cSmrg    {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer),
214145b7b3cSmrg	offset(notify_done), XtRFunction, (XtPointer) 0},
215145b7b3cSmrg    {XtNsessionArgument, XtCSessionArgument, XtRString,	sizeof (char *),
216145b7b3cSmrg	offset(sessionArg), XtRString, (XtPointer) 0 },
217145b7b3cSmrg    {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean),
218145b7b3cSmrg	offset(secure_session), XtRImmediate, (XtPointer) False },
219145b7b3cSmrg    {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean),
220145b7b3cSmrg	offset(allow_access), XtRImmediate, (XtPointer) False },
221145b7b3cSmrg    {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean),
222145b7b3cSmrg	offset(allow_null_passwd), XtRImmediate, (XtPointer) False},
223145b7b3cSmrg    {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean),
2245ffd6003Smrg	offset(allow_root_login), XtRImmediate, (XtPointer) True},
2255ffd6003Smrg    {XtNechoPasswd, XtCEchoPasswd, XtRBoolean, sizeof(Boolean),
226629baa8cSmrg	offset(echo_passwd), XtRImmediate, (XtPointer) False},
227629baa8cSmrg    {XtNechoPasswdChar, XtCEchoPasswdChar, XtRString,	sizeof (char *),
228629baa8cSmrg	offset(echo_passwd_char), XtRString, (XtPointer) "*" }
229145b7b3cSmrg};
230145b7b3cSmrg
231145b7b3cSmrg#undef offset
232145b7b3cSmrg#undef goffset
233145b7b3cSmrg
234145b7b3cSmrg#ifdef USE_XFT
235145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Face->max_advance_width)
236145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Face->ascent)
237145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Face->descent)
238145b7b3cSmrg#else
239145b7b3cSmrg# define F_MAX_WIDTH(f)	((w)->login.f##Font->max_bounds.width)
240145b7b3cSmrg# define F_ASCENT(f)	((w)->login.f##Font->max_bounds.ascent)
241145b7b3cSmrg# define F_DESCENT(f)	((w)->login.f##Font->max_bounds.descent)
242145b7b3cSmrg#endif
243145b7b3cSmrg
244578741aaSmrg#define TEXT_X_INC(w)		F_MAX_WIDTH(text)
245578741aaSmrg#define TEXT_Y_INC(w)		(F_ASCENT(text) + F_DESCENT(text))
246145b7b3cSmrg
247026e32a9Smlelstv#define PROMPT_X_INC(w)		F_MAX_WIDTH(prompt)
248026e32a9Smlelstv#define PROMPT_Y_INC(w)		(F_ASCENT(prompt) + F_DESCENT(prompt))
249145b7b3cSmrg
250578741aaSmrg#define GREET_X_INC(w)		F_MAX_WIDTH(greet)
251578741aaSmrg#define GREET_Y_INC(w)		(F_ASCENT(greet) + F_DESCENT(greet))
252145b7b3cSmrg
253578741aaSmrg#define FAIL_X_INC(w)		F_MAX_WIDTH(fail)
254578741aaSmrg#define FAIL_Y_INC(w)		(F_ASCENT(fail) + F_DESCENT(fail))
255145b7b3cSmrg
256026e32a9Smlelstv#define Y_ASCENT(w)	max (F_ASCENT(prompt), F_ASCENT(text))
257026e32a9Smlelstv#define Y_DESCENT(w)	max (F_DESCENT(prompt), F_DESCENT(text))
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
278145b7b3cSmrgstatic int
279145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len);
280145b7b3cSmrg
281026e32a9Smlelstv# define TEXT_COLOR(f)		(w->login.f##color.pixel)
282026e32a9Smlelstv# define TEXT_WIDTH(f, m, l) 	XmuXftTextWidth(XtDisplay (w), \
283026e32a9Smlelstv				w->login.f##Face, (FcChar8 *) m, l)
284145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
285145b7b3cSmrg	/* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \
286145b7b3cSmrg	XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \
287145b7b3cSmrg			x, y, (FcChar8 *) m, l)
288145b7b3cSmrg
289145b7b3cSmrg#else
290145b7b3cSmrg
291145b7b3cSmrg# define TEXT_COLOR(f)		(w->login.f##pixel)
292145b7b3cSmrg# define TEXT_WIDTH(f, m, l) 	(XTextWidth (w->login.f##Font, m, l))
293145b7b3cSmrg# define DRAW_STRING(f, x, y, m, l) \
294145b7b3cSmrg	XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l)
295145b7b3cSmrg
296145b7b3cSmrg#endif
297145b7b3cSmrg
298145b7b3cSmrg
299578741aaSmrg#define STRING_WIDTH(f, s) 	TEXT_WIDTH (f, s, strlen(s))
300145b7b3cSmrg
301629baa8cSmrg/* Padded width of logo image, if compiled with XPM support */
302629baa8cSmrg#ifdef XPM
303026e32a9Smlelstv# define LOGO_PAD(w)   ((w)->login.logoPadding)
304026e32a9Smlelstv# define LOGO_W(w)     ((w)->login.logoWidth + (LOGO_PAD(w) * 2))
305629baa8cSmrg#else
306026e32a9Smlelstv# define LOGO_PAD(w)   0
307629baa8cSmrg# define LOGO_W(w)     0
308629baa8cSmrg#endif
309145b7b3cSmrg
310578741aaSmrg#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth)
311145b7b3cSmrg
312026e32a9Smlelstv#define DEF_PROMPT_W(w,n)	TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt)
313026e32a9Smlelstv#define MAX_DEF_PROMPT_W(w)	(max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1)))
314026e32a9Smlelstv#define CUR_PROMPT_W(w,n)	(max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \
315026e32a9Smlelstv					TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0))
316145b7b3cSmrg
317578741aaSmrg#define GREETING(w)	((w)->login.secure_session  && !(w)->login.allow_access ?\
318145b7b3cSmrg				(w)->login.greeting : (w)->login.unsecure_greet)
3191cacedb1Smlelstv#define GREET_X(w)	((int)((w->core.width - LOGO_W(w) + LOGO_PAD(w) - \
320145b7b3cSmrg			     	STRING_WIDTH (greet, GREETING(w))) / 2))
321578741aaSmrg#define GREET_Y(w)	(GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
322629baa8cSmrg#define GREET_W(w)	(max (STRING_WIDTH (greet, w->login.greeting), \
323026e32a9Smlelstv			      STRING_WIDTH (greet, w->login.unsecure_greet)))
324026e32a9Smlelstv
325026e32a9Smlelstv#define SEP_X(w)	((w)->login.outframewidth + LOGO_PAD(w))
326026e32a9Smlelstv#define SEP_Y(w)	(GREET_Y(w) + GREET_Y_INC(w))
327026e32a9Smlelstv#define SEP_W(w)	((w)->core.width - 2*(w->login.outframewidth) - LOGO_W(w) - LOGO_PAD(w))
328026e32a9Smlelstv#define SEP_H(w)	((w)->login.inframeswidth * 2)
329629baa8cSmrg
330578741aaSmrg#define PROMPT_X(w)	(2 * PROMPT_X_INC(w))
3316cc8c0d3Smlelstv#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)))
332026e32a9Smlelstv#define PROMPT_W(w)	(w->core.width - PROMPT_X(w) - 2 * TEXT_X_INC(w) - LOGO_W(w))
333026e32a9Smlelstv#define PROMPT_H(w)	Y_INC(w)
334026e32a9Smlelstv
33509dea964Smlelstv#define VALUE_HPAD(w,n)	(TEXT_X_INC(w)/8)
3361cacedb1Smlelstv#define VALUE_VPAD(w,n)	((Y_INC(w)+3)/4)
33709dea964Smlelstv#define VALUE_X(w,n)	(PROMPT_X(w) + CUR_PROMPT_W(w,n) + VALUE_HPAD(w,n))
338026e32a9Smlelstv#define VALUE_Y(w,n)	(PROMPT_Y(w,n))
339026e32a9Smlelstv#define VALUE_W(w,n)	(PROMPT_W(w) - VALUE_X(w,n) + PROMPT_X(w) - CURSOR_W)
340026e32a9Smlelstv#define VALUE_H(w,n)	Y_INC(w)
341145b7b3cSmrg
342b7d26471Smrg#define ERROR_X(w,m)	((int)(w->core.width - LOGO_W(w) - STRING_WIDTH (fail, m)) / 2)
343629baa8cSmrg#define ERROR_W(w,m)	(STRING_WIDTH (fail, m) + LOGO_W(w))
344145b7b3cSmrg
345026e32a9Smlelstv#define FAIL_X(w)	ERROR_X(w, w->login.fail)
346026e32a9Smlelstv#define FAIL_Y(w)	(PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail))
347578741aaSmrg#define FAIL_W(w)	max(ERROR_W(w, w->login.failMsg), \
348145b7b3cSmrg			    ERROR_W(w, w->login.passwdChangeMsg))
349145b7b3cSmrg
350d44fbef5Smlelstv#define PAD_X(w)	(2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w)) + 4*w->login.outframewidth))
351578741aaSmrg#define PAD_Y(w)	(max (max (Y_INC(w), GREET_Y_INC(w)),\
352145b7b3cSmrg			     FAIL_Y_INC(w)))
353578741aaSmrg
354145b7b3cSmrg#ifndef max
355145b7b3cSmrgstatic inline int max (int a, int b) { return a > b ? a : b; }
356145b7b3cSmrg#endif
357145b7b3cSmrg
358145b7b3cSmrgstatic void
359145b7b3cSmrgrealizeValue (LoginWidget w, int cursor, int promptNum, GC gc)
360145b7b3cSmrg{
3615ffd6003Smrg    loginPromptState state = PROMPT_STATE(w, promptNum);
362145b7b3cSmrg    char *text = VALUE_TEXT(w, promptNum);
363026e32a9Smlelstv    int	x, y, height, width, curoff, offset, textlen;
364145b7b3cSmrg
365145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
366145b7b3cSmrg
3675ffd6003Smrg    /* replace all password characters with asterisks */
3685ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
3695ffd6003Smrg    {
3705ffd6003Smrg	Cardinal length = strlen(text);
3715ffd6003Smrg	Cardinal i = 0;
3725ffd6003Smrg
3735ffd6003Smrg	text = XtMalloc(length + 1);
3745ffd6003Smrg
3755ffd6003Smrg	if (text == NULL)
3765ffd6003Smrg	{
3775ffd6003Smrg	    LogOutOfMem("realizeValue");
3785ffd6003Smrg	    return;
3795ffd6003Smrg	}
3805ffd6003Smrg
3815ffd6003Smrg	while (i < length)
3825ffd6003Smrg	{
383629baa8cSmrg	    text[i++] = w->login.echo_passwd_char[0];
3845ffd6003Smrg	}
3855ffd6003Smrg
3865ffd6003Smrg	text[i] = 0;
3875ffd6003Smrg    }
3885ffd6003Smrg
38909dea964Smlelstv    x = VALUE_X (w,promptNum) + VALUE_HPAD(w,promptNum);
390026e32a9Smlelstv    y = VALUE_Y (w,promptNum);
391145b7b3cSmrg
3921cacedb1Smlelstv    height = VALUE_H(w,promptNum);
393026e32a9Smlelstv    width = VALUE_W(w,promptNum);
394145b7b3cSmrg
395026e32a9Smlelstv    offset = VALUE_SHOW_START(w, promptNum);
396026e32a9Smlelstv    if (cursor > offset)
397026e32a9Smlelstv	curoff = TEXT_WIDTH (text, text + offset, cursor - offset);
398145b7b3cSmrg    else
399145b7b3cSmrg	curoff = 0;
400145b7b3cSmrg
401145b7b3cSmrg    if (gc == w->login.bgGC) {
402145b7b3cSmrg	if (curoff < width) {
403145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
404026e32a9Smlelstv			    x + curoff, y - Y_ASCENT(w),
405145b7b3cSmrg			    width - curoff, height);
406145b7b3cSmrg	}
4075ffd6003Smrg    } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) ||
4085ffd6003Smrg	       ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)))
4095ffd6003Smrg    {
410026e32a9Smlelstv	offset = max(cursor, VALUE_SHOW_START(w, promptNum));
411026e32a9Smlelstv	textlen = strlen (text + offset);
412578741aaSmrg
413629baa8cSmrg	if (TEXT_WIDTH (text, text + offset, textlen) > (width - curoff)) {
414145b7b3cSmrg	    /* Recalculate amount of text that can fit in field */
415145b7b3cSmrg	    offset = VALUE_SHOW_START(w, promptNum);
416145b7b3cSmrg	    textlen = strlen (text + offset);
417145b7b3cSmrg
418629baa8cSmrg	    while ((textlen > 0) &&
419629baa8cSmrg		   (TEXT_WIDTH (text, text + offset, textlen) > width))
420145b7b3cSmrg	    {
421145b7b3cSmrg		if (offset < PROMPT_CURSOR(w, promptNum)) {
422145b7b3cSmrg		    offset++;
423145b7b3cSmrg		}
424145b7b3cSmrg		textlen--;
425578741aaSmrg	    }
426145b7b3cSmrg
427145b7b3cSmrg	    VALUE_SHOW_START(w, promptNum) = offset;
428145b7b3cSmrg	    VALUE_SHOW_END(w, promptNum) = offset + textlen;
429145b7b3cSmrg
430145b7b3cSmrg	    /* Erase old string */
431145b7b3cSmrg	    XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC,
432026e32a9Smlelstv			    x, y - Y_ASCENT(w), width, height);
433145b7b3cSmrg
434145b7b3cSmrg	    DRAW_STRING(text, x, y, text + offset, textlen);
435145b7b3cSmrg	} else {
436145b7b3cSmrg	    DRAW_STRING(text, x + curoff, y, text + offset, textlen);
437145b7b3cSmrg	}
438145b7b3cSmrg    }
4395ffd6003Smrg    /* free memory */
4405ffd6003Smrg    if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))
4415ffd6003Smrg    {
4425ffd6003Smrg	XtFree(text);
4435ffd6003Smrg    }
444145b7b3cSmrg}
445145b7b3cSmrg
446145b7b3cSmrgstatic void
447145b7b3cSmrgEraseValue (LoginWidget w, int cursor, int promptNum)
448145b7b3cSmrg{
449145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.bgGC);
450145b7b3cSmrg}
451145b7b3cSmrg
452145b7b3cSmrgstatic void
453145b7b3cSmrgDrawValue (LoginWidget w, int cursor, int promptNum)
454145b7b3cSmrg{
455145b7b3cSmrg    realizeValue(w, cursor, promptNum, w->login.textGC);
456145b7b3cSmrg#ifdef DANCING
457145b7b3cSmrg    /*as good a place as any Caolan begin*/
458145b7b3cSmrg    w->login.lastEventTime = time(NULL);
459145b7b3cSmrg    /*as good a place as any Caolan end*/
460145b7b3cSmrg#endif /* DANCING */
461145b7b3cSmrg}
462145b7b3cSmrg
463145b7b3cSmrgstatic void
464145b7b3cSmrgrealizeCursor (LoginWidget w, GC gc)
465145b7b3cSmrg{
466145b7b3cSmrg    int	x, y;
467026e32a9Smlelstv    int ascent, descent;
468145b7b3cSmrg
469145b7b3cSmrg    if (w->login.state != PROMPTING) {
470145b7b3cSmrg	return;
471145b7b3cSmrg    }
472578741aaSmrg
47309dea964Smlelstv    x = VALUE_X (w, w->login.activePrompt)
47409dea964Smlelstv      + VALUE_HPAD(w, w->login.activePrompt);
475026e32a9Smlelstv    y = VALUE_Y (w, w->login.activePrompt);
476026e32a9Smlelstv    ascent = F_ASCENT(text);
477026e32a9Smlelstv    descent = F_DESCENT(text);
478145b7b3cSmrg
479145b7b3cSmrg    switch (PROMPT_STATE(w, w->login.activePrompt)) {
480145b7b3cSmrg    case LOGIN_PROMPT_NOT_SHOWN:
481145b7b3cSmrg    case LOGIN_TEXT_INFO:
482145b7b3cSmrg	return;
483145b7b3cSmrg    case LOGIN_PROMPT_ECHO_ON:
484145b7b3cSmrg	if (CUR_PROMPT_CURSOR(w) > 0) {
485145b7b3cSmrg	    x += TEXT_WIDTH (text,
486145b7b3cSmrg			     VALUE_TEXT(w, w->login.activePrompt)
487145b7b3cSmrg			     + VALUE_SHOW_START(w, w->login.activePrompt),
488145b7b3cSmrg			     PROMPT_CURSOR(w, w->login.activePrompt)
489145b7b3cSmrg			     - VALUE_SHOW_START(w, w->login.activePrompt) );
490145b7b3cSmrg	}
491145b7b3cSmrg	break;
492145b7b3cSmrg    case LOGIN_PROMPT_ECHO_OFF:
4935ffd6003Smrg	if (w->login.echo_passwd == True) {
494629baa8cSmrg	    if (w->login.echo_passwd_char[0] != 0) {
495629baa8cSmrg		int len = PROMPT_CURSOR(w, w->login.activePrompt) -
496629baa8cSmrg		    VALUE_SHOW_START(w, w->login.activePrompt);
4975ffd6003Smrg
498629baa8cSmrg		x += len*TEXT_WIDTH(text, w->login.echo_passwd_char, 1);
499629baa8cSmrg	    } else {
500629baa8cSmrg		/* Move cursor one pixel per character to give some feedback
501629baa8cSmrg		   without giving away the password length */
502629baa8cSmrg		if (PROMPT_CURSOR(w, w->login.activePrompt) <
503026e32a9Smlelstv		    VALUE_W(w, w->login.activePrompt))
504629baa8cSmrg		    x += PROMPT_CURSOR(w, w->login.activePrompt);
505629baa8cSmrg		else
506026e32a9Smlelstv		    x += VALUE_W(w, w->login.activePrompt);
507629baa8cSmrg	    }
5085ffd6003Smrg	}
509145b7b3cSmrg	break;
510145b7b3cSmrg    }
511578741aaSmrg
5123f10d660Smlelstv    x += 2;
5133f10d660Smlelstv
514145b7b3cSmrg    XFillRectangle (XtDisplay (w), XtWindow (w), gc,
515026e32a9Smlelstv		    x, y - ascent + 1, 1, ascent + descent - 2);
516026e32a9Smlelstv
517145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
518026e32a9Smlelstv		    x-1 , y - ascent);
519145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
520026e32a9Smlelstv		    x+1 , y - ascent);
521145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
522026e32a9Smlelstv		    x-1 , y + descent - 1);
523145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
524026e32a9Smlelstv		    x+1 , y - descent - 1);
525026e32a9Smlelstv
526145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
527026e32a9Smlelstv		    x-2 , y - ascent);
528145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
529026e32a9Smlelstv		    x+2 , y - ascent);
530145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
531026e32a9Smlelstv		    x-2 , y + descent - 1);
532145b7b3cSmrg    XDrawPoint     (XtDisplay (w), XtWindow (w), gc,
533026e32a9Smlelstv		    x+2 , y + descent - 1);
534145b7b3cSmrg
535578741aaSmrg    XFlush (XtDisplay(w));
536145b7b3cSmrg}
537145b7b3cSmrg
538145b7b3cSmrgstatic void
539145b7b3cSmrgEraseFail (LoginWidget w)
540145b7b3cSmrg{
541578741aaSmrg#ifdef USE_XFT
542145b7b3cSmrg    w->login.failUp = 0;
543145b7b3cSmrg    RedrawFail(w);
544578741aaSmrg#else
545145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
546145b7b3cSmrg			w->core.background_pixel);
547145b7b3cSmrg    RedrawFail(w);
548145b7b3cSmrg    w->login.failUp = 0;
549145b7b3cSmrg    XSetForeground (XtDisplay (w), w->login.failGC,
550145b7b3cSmrg			TEXT_COLOR(fail));
551578741aaSmrg#endif
552145b7b3cSmrg}
553145b7b3cSmrg
554145b7b3cSmrgstatic void
555145b7b3cSmrgXorCursor (LoginWidget w)
556145b7b3cSmrg{
557145b7b3cSmrg    realizeCursor (w, w->login.xorGC);
558145b7b3cSmrg}
559145b7b3cSmrg
560145b7b3cSmrgstatic void
561145b7b3cSmrgRemoveFail (LoginWidget w)
562145b7b3cSmrg{
563145b7b3cSmrg    if (w->login.failUp)
564145b7b3cSmrg	EraseFail (w);
565145b7b3cSmrg}
566145b7b3cSmrg
567145b7b3cSmrgstatic void
568145b7b3cSmrgEraseCursor (LoginWidget w)
569145b7b3cSmrg{
570145b7b3cSmrg    realizeCursor (w, w->login.bgGC);
571145b7b3cSmrg}
572145b7b3cSmrg
573145b7b3cSmrg/*ARGSUSED*/
574145b7b3cSmrgstatic void failTimeout (XtPointer client_data, XtIntervalId * id)
575145b7b3cSmrg{
576145b7b3cSmrg    LoginWidget	w = (LoginWidget)client_data;
577145b7b3cSmrg
578145b7b3cSmrg    Debug ("failTimeout\n");
579145b7b3cSmrg    w->login.interval_id = 0;
580145b7b3cSmrg    EraseFail (w);
581145b7b3cSmrg}
582145b7b3cSmrg
583145b7b3cSmrg_X_INTERNAL
584145b7b3cSmrgvoid
585145b7b3cSmrgDrawFail (Widget ctx)
586145b7b3cSmrg{
587145b7b3cSmrg    LoginWidget	w;
588145b7b3cSmrg
589145b7b3cSmrg    w = (LoginWidget) ctx;
590145b7b3cSmrg    XorCursor (w);
591145b7b3cSmrg    ResetLogin (w);
592145b7b3cSmrg    XorCursor (w);
593145b7b3cSmrg    ErrorMessage(ctx, w->login.failMsg, True);
594145b7b3cSmrg}
595145b7b3cSmrg
596145b7b3cSmrgstatic void
597145b7b3cSmrgRedrawFail (LoginWidget w)
598145b7b3cSmrg{
599145b7b3cSmrg    int x = FAIL_X(w);
600145b7b3cSmrg    int y = FAIL_Y(w);
601145b7b3cSmrg    int maxw = w->core.width - PAD_X(w);
602145b7b3cSmrg
603578741aaSmrg#ifndef USE_XFT
604145b7b3cSmrg    if (w->login.failUp)
605578741aaSmrg#endif
606145b7b3cSmrg    {
607145b7b3cSmrg	Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp);
608145b7b3cSmrg	if (ERROR_W(w, w->login.fail) > maxw) {
609145b7b3cSmrg	    /* Too long to fit on one line, break into multiple lines */
610145b7b3cSmrg	    char *tempCopy = strdup(w->login.fail);
611145b7b3cSmrg	    if (tempCopy != NULL) {
612145b7b3cSmrg		char *start, *next;
613578741aaSmrg		char lastspace = ' ';
614145b7b3cSmrg
615145b7b3cSmrg		y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w));
616578741aaSmrg
617145b7b3cSmrg		for (start = next = tempCopy; start != NULL ; start = next) {
618145b7b3cSmrg		    /* search for longest string broken by whitespace that
619145b7b3cSmrg		       will fit on a single line */
620145b7b3cSmrg		    do {
621145b7b3cSmrg			if (next != start) {
622145b7b3cSmrg			    *next = lastspace;
623145b7b3cSmrg			}
624145b7b3cSmrg			for (next = next + 1;
625145b7b3cSmrg			     (*next != '\0') && !isspace(*next) ; next++)
626145b7b3cSmrg			{
627145b7b3cSmrg			    /* this loop intentionally left blank */
628145b7b3cSmrg			}
629145b7b3cSmrg			if (*next != '\0') {
630145b7b3cSmrg			    lastspace = *next;
631145b7b3cSmrg			    *next = '\0';
632145b7b3cSmrg			} else {
633145b7b3cSmrg			    next = NULL;
634145b7b3cSmrg			}
635145b7b3cSmrg		    } while ((next != NULL) && ERROR_W(w, start) < maxw);
636578741aaSmrg
637145b7b3cSmrg		    x = ERROR_X(w, start);
638145b7b3cSmrg#ifdef USE_XFT
639145b7b3cSmrg		    if (w->login.failUp == 0) {
6405ffd6003Smrg			XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
641145b7b3cSmrg				   ERROR_W(w, start), FAIL_Y_INC(w), False);
642145b7b3cSmrg		    } else
643578741aaSmrg#endif
644145b7b3cSmrg			DRAW_STRING (fail, x, y, start, strlen(start));
645145b7b3cSmrg
646145b7b3cSmrg		    if (next != NULL) {
647145b7b3cSmrg			next++;
648145b7b3cSmrg			y += FAIL_Y_INC(w);
649145b7b3cSmrg		    }
650145b7b3cSmrg		}
651145b7b3cSmrg		free(tempCopy);
652145b7b3cSmrg		return;
653145b7b3cSmrg	    }
654145b7b3cSmrg	    /* if strdup failed, fall through to draw all at once, even
655145b7b3cSmrg	       though we know it can't all fit */
656145b7b3cSmrg	    LogOutOfMem("RedrawFail");
657145b7b3cSmrg	}
658145b7b3cSmrg
659145b7b3cSmrg#ifdef USE_XFT
660145b7b3cSmrg	if (w->login.failUp == 0) {
6615ffd6003Smrg	    XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail),
662145b7b3cSmrg		       ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False);
663145b7b3cSmrg	} else
664578741aaSmrg#endif
665145b7b3cSmrg	    DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail));
666145b7b3cSmrg    }
667145b7b3cSmrg}
668145b7b3cSmrg
669145b7b3cSmrg_X_INTERNAL
670145b7b3cSmrgvoid
671145b7b3cSmrgErrorMessage(Widget ctx, const char *message, Bool timeout)
672145b7b3cSmrg{
673145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
674145b7b3cSmrg
675145b7b3cSmrg/*  Debug("ErrorMessage: %s\n", message);   */
676145b7b3cSmrg    if (w->login.interval_id != 0) {
677145b7b3cSmrg	XtRemoveTimeOut(w->login.interval_id);
678145b7b3cSmrg	w->login.interval_id = 0;
679145b7b3cSmrg    }
680145b7b3cSmrg    RemoveFail(w);
681145b7b3cSmrg    if (w->login.fail != w->login.failMsg)
682145b7b3cSmrg	free(w->login.fail);
683145b7b3cSmrg    w->login.fail = strdup(message);
684145b7b3cSmrg    if (w->login.fail == NULL)
685145b7b3cSmrg	w->login.fail = (char *) w->login.failMsg;
686145b7b3cSmrg    w->login.failUp = 1;
687145b7b3cSmrg    RedrawFail (w);
688145b7b3cSmrg    if (timeout && (w->login.failTimeout > 0)) {
689145b7b3cSmrg	Debug ("failTimeout: %d\n", w->login.failTimeout);
690145b7b3cSmrg	w->login.interval_id =
691145b7b3cSmrg	    XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w),
692145b7b3cSmrg			    w->login.failTimeout * 1000,
693145b7b3cSmrg			    failTimeout, (XtPointer) w);
694145b7b3cSmrg    }
695145b7b3cSmrg}
696145b7b3cSmrg
697145b7b3cSmrg_X_INTERNAL
698145b7b3cSmrgvoid
699145b7b3cSmrgShowChangePasswdMessage(Widget ctx)
700145b7b3cSmrg{
701145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
702145b7b3cSmrg
703145b7b3cSmrg    ErrorMessage(ctx, w->login.passwdChangeMsg, False);
704145b7b3cSmrg}
705145b7b3cSmrg
706145b7b3cSmrgstatic void
707145b7b3cSmrgdraw_it (LoginWidget w)
708145b7b3cSmrg{
709145b7b3cSmrg    int p;
710145b7b3cSmrg    int i;
711145b7b3cSmrg    int gr_line_x, gr_line_y, gr_line_w;
712145b7b3cSmrg
713145b7b3cSmrg    EraseCursor (w);
714145b7b3cSmrg
7155ffd6003Smrg    /* draw window borders */
716145b7b3cSmrg    for(i=1;i<=(w->login.outframewidth);i++)
717145b7b3cSmrg    {
718145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
719629baa8cSmrg		i-1,i-1,w->core.width-i,i-1);
720145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
721629baa8cSmrg		i-1,i-1,i-1,w->core.height-i);
722145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
723629baa8cSmrg		w->core.width-i,i-1,w->core.width-i,w->core.height-i);
724145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
725629baa8cSmrg		i-1,w->core.height-i,w->core.width-i,w->core.height-i);
726145b7b3cSmrg    }
727578741aaSmrg
728145b7b3cSmrg    /* make separator line */
729026e32a9Smlelstv    gr_line_x = SEP_X(w);
730026e32a9Smlelstv    gr_line_y = SEP_Y(w);
731026e32a9Smlelstv    gr_line_w = SEP_W(w);
732145b7b3cSmrg
733145b7b3cSmrg    for(i=1;i<=(w->login.sepwidth);i++)
734145b7b3cSmrg    {
735145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC,
736145b7b3cSmrg        gr_line_x,           gr_line_y + i-1,
737145b7b3cSmrg        gr_line_x+gr_line_w, gr_line_y + i-1);
738145b7b3cSmrg      XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC,
739026e32a9Smlelstv        gr_line_x,           gr_line_y + SEP_H(w) -i,
740026e32a9Smlelstv        gr_line_x+gr_line_w, gr_line_y + SEP_H(w) -i);
741145b7b3cSmrg    }
742145b7b3cSmrg
743145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++)
744145b7b3cSmrg    {
745026e32a9Smlelstv	int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth;
7461cacedb1Smlelstv	int in_frame_y = VALUE_Y(w,p) - Y_ASCENT(w) - w->login.inframeswidth
7471cacedb1Smlelstv		- VALUE_VPAD(w,p);
748578741aaSmrg
74909dea964Smlelstv	int in_width = VALUE_W(w,p) + CURSOR_W + 2 * w->login.inframeswidth
75009dea964Smlelstv		+ 2 * VALUE_HPAD(w,p);
7511cacedb1Smlelstv	int in_height = VALUE_H(w,p) + 2 * w->login.inframeswidth
7521cacedb1Smlelstv		+ 2 * VALUE_VPAD(w,p);
753578741aaSmrg
754b7d26471Smrg	GC topLeftGC, botRightGC, inpGC;
755145b7b3cSmrg
756145b7b3cSmrg	if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) ||
757145b7b3cSmrg	    (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) {
758145b7b3cSmrg	    topLeftGC = w->login.shdGC;
759145b7b3cSmrg	    botRightGC = w->login.hiGC;
760b7d26471Smrg	    inpGC = w->login.inpGC;
761145b7b3cSmrg	} else {
762b7d26471Smrg	    topLeftGC = botRightGC = inpGC = w->login.bgGC;
763145b7b3cSmrg	}
764145b7b3cSmrg
7655ffd6003Smrg	/* draw borders of editboxes */
766145b7b3cSmrg	for (i=1; i<=(w->login.inframeswidth); i++)
767145b7b3cSmrg	{
768145b7b3cSmrg	    /* Make top/left sides */
769145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
770145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
771578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1);
772145b7b3cSmrg
773145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC,
774145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + i-1,
775578741aaSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i);
776145b7b3cSmrg
777145b7b3cSmrg	    /* Make bottom/right sides */
778145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
779145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + i-1,
780578741aaSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
781145b7b3cSmrg
782145b7b3cSmrg	    XDrawLine(XtDisplay (w), XtWindow (w), botRightGC,
783145b7b3cSmrg		      in_frame_x + i-1,         in_frame_y + in_height-i,
784145b7b3cSmrg		      in_frame_x + in_width-i,  in_frame_y + in_height-i);
785145b7b3cSmrg	}
786b7d26471Smrg	XFillRectangle(XtDisplay (w), XtWindow (w), inpGC,
787b7d26471Smrg	    in_frame_x + w->login.inframeswidth,
788b7d26471Smrg	    in_frame_y + w->login.inframeswidth,
789b7d26471Smrg	    in_width - 2*w->login.inframeswidth,
790b7d26471Smrg	    in_height - 2*w->login.inframeswidth);
791145b7b3cSmrg    }
792145b7b3cSmrg
793145b7b3cSmrg    if (GREETING(w)[0]) {
7941cacedb1Smlelstv	DRAW_STRING (greet, GREET_X(w), GREET_Y(w),
7951cacedb1Smlelstv		     GREETING(w), strlen (GREETING(w)));
796145b7b3cSmrg    }
797145b7b3cSmrg    for (p = 0; p < NUM_PROMPTS ; p++) {
798145b7b3cSmrg	if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) {
799145b7b3cSmrg	    DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p),
800145b7b3cSmrg			 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p)));
801145b7b3cSmrg	    DrawValue (w, 0, p);
802145b7b3cSmrg	}
803145b7b3cSmrg    }
804145b7b3cSmrg    RedrawFail (w);
805145b7b3cSmrg    XorCursor (w);
8065ffd6003Smrg    XSetInputFocus (XtDisplay (w), XtWindow (w),
8075ffd6003Smrg		    RevertToPointerRoot, CurrentTime);
808145b7b3cSmrg}
809145b7b3cSmrg
810145b7b3cSmrg/* Returns 0 on success, -1 on failure */
811145b7b3cSmrg_X_INTERNAL
812145b7b3cSmrgint
813145b7b3cSmrgSetPrompt (Widget ctx, int promptNum, const char *message,
814145b7b3cSmrg	   loginPromptState state, Boolean minimumTime)
815145b7b3cSmrg{
816145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
817145b7b3cSmrg    char *prompt;
818145b7b3cSmrg    int messageLen, e;
819145b7b3cSmrg    const char *stateNames[4] = {
820145b7b3cSmrg	"LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON",
821145b7b3cSmrg	"LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" };
822145b7b3cSmrg    loginPromptState priorState;
823578741aaSmrg
824145b7b3cSmrg    Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum,
825145b7b3cSmrg	  message ? message : "<NULL>", stateNames[state], state);
826145b7b3cSmrg
827145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
828578741aaSmrg
829145b7b3cSmrg    if (PROMPT_TEXT(w, promptNum) != NULL) {
830145b7b3cSmrg	XtFree(PROMPT_TEXT(w, promptNum));
831145b7b3cSmrg	PROMPT_TEXT(w, promptNum) = NULL;
832145b7b3cSmrg    }
833145b7b3cSmrg
834145b7b3cSmrg    priorState = PROMPT_STATE(w, promptNum);
835145b7b3cSmrg    PROMPT_STATE(w, promptNum) = state;
836145b7b3cSmrg
837145b7b3cSmrg    if (state == LOGIN_PROMPT_NOT_SHOWN) {
838145b7b3cSmrg	return 0;
839145b7b3cSmrg    }
840145b7b3cSmrg
841145b7b3cSmrg    if (message == NULL) {
842145b7b3cSmrg	message = DEF_PROMPT_TEXT(w, promptNum);
843145b7b3cSmrg    }
844145b7b3cSmrg
845145b7b3cSmrg    messageLen = strlen(message);
846578741aaSmrg
847145b7b3cSmrg    prompt = XtMalloc(messageLen + 3);
848145b7b3cSmrg    if (prompt == NULL) {
849145b7b3cSmrg	LogOutOfMem ("SetPrompt");
850145b7b3cSmrg	return -1;
851145b7b3cSmrg    }
852578741aaSmrg
853145b7b3cSmrg    strncpy(prompt, message, messageLen);
854578741aaSmrg
855145b7b3cSmrg    /* Make sure text prompts have at least two spaces at end */
856145b7b3cSmrg    e = messageLen;
857578741aaSmrg
858145b7b3cSmrg    if (!isspace(message[messageLen - 2])) {
859145b7b3cSmrg	prompt[e] = ' ';
860145b7b3cSmrg	e++;
861145b7b3cSmrg    }
862145b7b3cSmrg    if (!isspace(message[messageLen - 1])) {
863145b7b3cSmrg	prompt[e] = ' ';
864145b7b3cSmrg	e++;
865145b7b3cSmrg    }
866145b7b3cSmrg    prompt[e] = '\0';
867145b7b3cSmrg
868145b7b3cSmrg    PROMPT_TEXT(w, promptNum) = prompt;
869145b7b3cSmrg
870145b7b3cSmrg    if (w->login.state == INITIALIZING) {
871145b7b3cSmrg	return 0;
872145b7b3cSmrg    }
873578741aaSmrg
874145b7b3cSmrg    if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) {
875145b7b3cSmrg	time_t now = time(NULL);
876145b7b3cSmrg	int timeleft = w->login.msgTimeout - now;
877578741aaSmrg
878145b7b3cSmrg	if (timeleft > 0) {
879145b7b3cSmrg	    sleep(timeleft);
880145b7b3cSmrg	}
881145b7b3cSmrg	w->login.msgTimeout = 0;
882145b7b3cSmrg    }
883145b7b3cSmrg
884145b7b3cSmrg    if (state == LOGIN_TEXT_INFO) {
885145b7b3cSmrg	if (minimumTime) {
886145b7b3cSmrg	    time_t now = time(NULL);
887145b7b3cSmrg	    w->login.msgTimeout = now + w->login.failTimeout;
888145b7b3cSmrg	}
889145b7b3cSmrg	w->login.state = SHOW_MESSAGE;
890145b7b3cSmrg    } else {
891145b7b3cSmrg	w->login.activePrompt = promptNum;
892145b7b3cSmrg	w->login.state = PROMPTING;
893145b7b3cSmrg    }
894578741aaSmrg
895145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
896145b7b3cSmrg    XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE);
897145b7b3cSmrg    draw_it(w);
898145b7b3cSmrg    return 0;
899145b7b3cSmrg}
900145b7b3cSmrg
901145b7b3cSmrg_X_INTERNAL
902145b7b3cSmrgconst char *
903145b7b3cSmrgGetPrompt(Widget ctx, int promptNum)
904145b7b3cSmrg{
905145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
906145b7b3cSmrg
907145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
908578741aaSmrg
909145b7b3cSmrg    return CUR_PROMPT_TEXT(w,promptNum);
910145b7b3cSmrg}
911145b7b3cSmrg
912145b7b3cSmrg_X_INTERNAL
913145b7b3cSmrgint
914145b7b3cSmrgSetValue(Widget ctx, int promptNum, char *value)
915145b7b3cSmrg{
916145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
917145b7b3cSmrg
918145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
919578741aaSmrg
920145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
921145b7b3cSmrg	return -1;
922145b7b3cSmrg
923145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
924578741aaSmrg
925145b7b3cSmrg    if (VALUE_TEXT(w, promptNum) == NULL)
926145b7b3cSmrg	return -1;
927145b7b3cSmrg
928145b7b3cSmrg    if (value == NULL) {
929145b7b3cSmrg	bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum));
930145b7b3cSmrg    } else {
931145b7b3cSmrg	strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum));
932145b7b3cSmrg	VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0';
933145b7b3cSmrg    }
934145b7b3cSmrg
935145b7b3cSmrg    VALUE_SHOW_START(w, promptNum) = 0;
936145b7b3cSmrg    VALUE_SHOW_END(w, promptNum) = 0;
937145b7b3cSmrg    PROMPT_CURSOR(w, promptNum) = 0;
938578741aaSmrg
939145b7b3cSmrg    return 0;
940145b7b3cSmrg}
941145b7b3cSmrg
942145b7b3cSmrg_X_INTERNAL
943145b7b3cSmrgconst char *
944145b7b3cSmrgGetValue(Widget ctx, int promptNum)
945145b7b3cSmrg{
946145b7b3cSmrg    LoginWidget	w = (LoginWidget) ctx;
947145b7b3cSmrg
948145b7b3cSmrg    XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT);
949578741aaSmrg
950145b7b3cSmrg    if ((promptNum < 0) || (promptNum > LAST_PROMPT))
951145b7b3cSmrg	return NULL;
952145b7b3cSmrg
953145b7b3cSmrg    XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL);
954145b7b3cSmrg
955145b7b3cSmrg    return VALUE_TEXT(w, promptNum);
956145b7b3cSmrg}
957145b7b3cSmrg
958145b7b3cSmrg
959145b7b3cSmrgstatic void
960145b7b3cSmrgrealizeDeleteChar (LoginWidget ctx)
961145b7b3cSmrg{
962145b7b3cSmrg    if (ctx->login.state == PROMPTING) {
963145b7b3cSmrg	int promptNum = ctx->login.activePrompt;
964145b7b3cSmrg	int redrawFrom = PROMPT_CURSOR(ctx, promptNum);
965578741aaSmrg
966145b7b3cSmrg	if (PROMPT_CURSOR(ctx,promptNum) <  (int)strlen(VALUE_TEXT(ctx,promptNum))) {
967026e32a9Smlelstv	    if (redrawFrom <= VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
968026e32a9Smlelstv		if (redrawFrom > 0)
969026e32a9Smlelstv			redrawFrom--;
970026e32a9Smlelstv		EraseValue (ctx, 0, promptNum);
971026e32a9Smlelstv		VALUE_SHOW_START(ctx, ctx->login.activePrompt) = redrawFrom;
972145b7b3cSmrg	    } else {
973145b7b3cSmrg		EraseValue (ctx, redrawFrom, promptNum);
974145b7b3cSmrg	    }
975145b7b3cSmrg	    strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
976145b7b3cSmrg		   VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1);
977145b7b3cSmrg	    DrawValue (ctx, redrawFrom, promptNum);
978145b7b3cSmrg	}
979145b7b3cSmrg    }
980145b7b3cSmrg}
981145b7b3cSmrg
982145b7b3cSmrg/*ARGSUSED*/
983145b7b3cSmrgstatic void
984145b7b3cSmrgDeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
985145b7b3cSmrg{
986145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
987145b7b3cSmrg
988145b7b3cSmrg    RemoveFail (ctx);
989145b7b3cSmrg
990145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
991145b7b3cSmrg	return;
992145b7b3cSmrg    }
993145b7b3cSmrg
994145b7b3cSmrg    XorCursor (ctx);
995145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0) {
996145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
997145b7b3cSmrg	realizeDeleteChar(ctx);
998145b7b3cSmrg    }
999578741aaSmrg    XorCursor (ctx);
1000145b7b3cSmrg}
1001145b7b3cSmrg
1002145b7b3cSmrg/*ARGSUSED*/
1003145b7b3cSmrgstatic void
1004145b7b3cSmrgDeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1005145b7b3cSmrg{
1006145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1007145b7b3cSmrg
1008145b7b3cSmrg    RemoveFail (ctx);
1009145b7b3cSmrg
1010145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1011145b7b3cSmrg	return;
1012145b7b3cSmrg    }
1013145b7b3cSmrg
1014145b7b3cSmrg    XorCursor (ctx);
1015145b7b3cSmrg    realizeDeleteChar(ctx);
1016578741aaSmrg    XorCursor (ctx);
1017145b7b3cSmrg}
1018145b7b3cSmrg
1019145b7b3cSmrg/*ARGSUSED*/
1020145b7b3cSmrgstatic void
1021145b7b3cSmrgMoveBackwardChar (
1022145b7b3cSmrg    Widget	ctxw,
1023145b7b3cSmrg    XEvent	*event,
1024145b7b3cSmrg    String	*params,
1025145b7b3cSmrg    Cardinal	*num_params)
1026145b7b3cSmrg{
1027145b7b3cSmrg    LoginWidget	ctx = (LoginWidget)ctxw;
1028145b7b3cSmrg
1029145b7b3cSmrg    RemoveFail (ctx);
1030145b7b3cSmrg
1031145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1032145b7b3cSmrg	return;
1033145b7b3cSmrg    }
1034145b7b3cSmrg
1035145b7b3cSmrg    XorCursor (ctx);
1036145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) > 0)
1037145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) -= 1;
1038145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) {
1039145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1040145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt)
1041145b7b3cSmrg	    = CUR_PROMPT_CURSOR(ctx);
1042145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1043145b7b3cSmrg    }
1044145b7b3cSmrg    XorCursor (ctx);
1045145b7b3cSmrg}
1046145b7b3cSmrg
1047145b7b3cSmrg/*ARGSUSED*/
1048145b7b3cSmrgstatic void
1049145b7b3cSmrgMoveForwardChar (
1050145b7b3cSmrg    Widget	ctxw,
1051145b7b3cSmrg    XEvent	*event,
1052145b7b3cSmrg    String	*params,
1053145b7b3cSmrg    Cardinal	*num_params)
1054145b7b3cSmrg{
1055145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1056145b7b3cSmrg
1057145b7b3cSmrg    RemoveFail (ctx);
1058145b7b3cSmrg
1059145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1060145b7b3cSmrg	return;
1061145b7b3cSmrg    }
1062145b7b3cSmrg
1063145b7b3cSmrg    XorCursor (ctx);
1064145b7b3cSmrg    if (CUR_PROMPT_CURSOR(ctx) <
1065145b7b3cSmrg	(int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) {
1066145b7b3cSmrg	CUR_PROMPT_CURSOR(ctx) += 1;
1067145b7b3cSmrg	if (VALUE_SHOW_END(ctx, ctx->login.activePrompt)
1068145b7b3cSmrg	    < CUR_PROMPT_CURSOR(ctx)) {
1069145b7b3cSmrg	    EraseValue(ctx, 0, ctx->login.activePrompt);
1070145b7b3cSmrg	    DrawValue(ctx, 0, ctx->login.activePrompt);
1071145b7b3cSmrg	}
1072145b7b3cSmrg    }
1073145b7b3cSmrg    XorCursor (ctx);
1074145b7b3cSmrg}
1075145b7b3cSmrg
1076145b7b3cSmrg/*ARGSUSED*/
1077145b7b3cSmrgstatic void
1078145b7b3cSmrgMoveToBegining (
1079145b7b3cSmrg    Widget	ctxw,
1080145b7b3cSmrg    XEvent	*event,
1081145b7b3cSmrg    String	*params,
1082145b7b3cSmrg    Cardinal	*num_params)
1083145b7b3cSmrg{
1084145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1085145b7b3cSmrg
1086145b7b3cSmrg    RemoveFail (ctx);
1087145b7b3cSmrg
1088145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1089145b7b3cSmrg	return;
1090145b7b3cSmrg    }
1091145b7b3cSmrg
1092145b7b3cSmrg    XorCursor (ctx);
1093145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = 0;
1094145b7b3cSmrg    if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) {
1095145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1096145b7b3cSmrg	VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0;
1097145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1098145b7b3cSmrg    }
1099145b7b3cSmrg    XorCursor (ctx);
1100145b7b3cSmrg}
1101145b7b3cSmrg
1102145b7b3cSmrg/*ARGSUSED*/
1103145b7b3cSmrgstatic void
1104145b7b3cSmrgMoveToEnd (
1105145b7b3cSmrg    Widget	ctxw,
1106145b7b3cSmrg    XEvent	*event,
1107145b7b3cSmrg    String	*params,
1108145b7b3cSmrg    Cardinal	*num_params)
1109145b7b3cSmrg{
1110145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1111145b7b3cSmrg
1112145b7b3cSmrg    RemoveFail (ctx);
1113145b7b3cSmrg
1114145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1115145b7b3cSmrg	return;
1116145b7b3cSmrg    }
1117145b7b3cSmrg
1118145b7b3cSmrg    XorCursor (ctx);
1119145b7b3cSmrg    CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt));
1120145b7b3cSmrg    if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) {
1121145b7b3cSmrg	EraseValue(ctx, 0, ctx->login.activePrompt);
1122145b7b3cSmrg	DrawValue(ctx, 0, ctx->login.activePrompt);
1123145b7b3cSmrg    }
1124145b7b3cSmrg    XorCursor (ctx);
1125145b7b3cSmrg}
1126145b7b3cSmrg
1127145b7b3cSmrg/*ARGSUSED*/
1128145b7b3cSmrgstatic void
1129145b7b3cSmrgEraseToEndOfLine (
1130145b7b3cSmrg    Widget	ctxw,
1131145b7b3cSmrg    XEvent	*event,
1132145b7b3cSmrg    String	*params,
1133145b7b3cSmrg    Cardinal	*num_params)
1134145b7b3cSmrg{
1135145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1136145b7b3cSmrg
1137145b7b3cSmrg    RemoveFail (ctx);
1138145b7b3cSmrg
1139145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1140145b7b3cSmrg	return;
1141145b7b3cSmrg    }
1142145b7b3cSmrg
1143145b7b3cSmrg    XorCursor (ctx);
1144145b7b3cSmrg    EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt);
1145145b7b3cSmrg    bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) +
1146145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx),
1147145b7b3cSmrg	  VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) -
1148145b7b3cSmrg	  CUR_PROMPT_CURSOR(ctx));
1149145b7b3cSmrg    XorCursor (ctx);
1150145b7b3cSmrg}
1151145b7b3cSmrg
1152145b7b3cSmrg/*ARGSUSED*/
1153145b7b3cSmrgstatic void
1154145b7b3cSmrgEraseLine (
1155145b7b3cSmrg    Widget	ctxw,
1156145b7b3cSmrg    XEvent	*event,
1157145b7b3cSmrg    String	*params,
1158145b7b3cSmrg    Cardinal	*num_params)
1159145b7b3cSmrg{
1160145b7b3cSmrg    MoveToBegining (ctxw, event, params, num_params);
1161145b7b3cSmrg    EraseToEndOfLine (ctxw, event, params, num_params);
1162145b7b3cSmrg}
1163145b7b3cSmrg
1164145b7b3cSmrg/*ARGSUSED*/
1165145b7b3cSmrgstatic void
1166145b7b3cSmrgFinishField (
1167145b7b3cSmrg    Widget	ctxw,
1168145b7b3cSmrg    XEvent	*event,
1169145b7b3cSmrg    String	*params,
1170145b7b3cSmrg    Cardinal	*num_params)
1171145b7b3cSmrg{
1172145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1173145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1174145b7b3cSmrg    int nextPrompt;
1175145b7b3cSmrg
1176145b7b3cSmrg    RemoveFail (ctx);
1177145b7b3cSmrg
1178145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1179145b7b3cSmrg	return;
1180145b7b3cSmrg    }
1181145b7b3cSmrg
1182145b7b3cSmrg    XorCursor (ctx);
1183145b7b3cSmrg
1184145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) {
1185145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1186145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1187145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1188145b7b3cSmrg	    break;
1189145b7b3cSmrg	}
1190145b7b3cSmrg    }
1191145b7b3cSmrg    if (nextPrompt > LAST_PROMPT) {
1192145b7b3cSmrg	ctx->login.state = DONE;
1193145b7b3cSmrg	(*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
1194145b7b3cSmrg	Debug("FinishField #%d: now DONE\n", promptNum);
1195145b7b3cSmrg    } else {
1196145b7b3cSmrg	Debug("FinishField #%d: %d next\n", promptNum, nextPrompt);
1197145b7b3cSmrg    }
1198145b7b3cSmrg
1199145b7b3cSmrg    XorCursor (ctx);
1200145b7b3cSmrg}
1201145b7b3cSmrg
1202145b7b3cSmrg/*ARGSUSED*/
1203145b7b3cSmrgstatic void
1204145b7b3cSmrgTabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params)
1205145b7b3cSmrg{
1206145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1207145b7b3cSmrg    int promptNum = ctx->login.activePrompt;
1208145b7b3cSmrg    int nextPrompt;
1209145b7b3cSmrg
1210145b7b3cSmrg    RemoveFail (ctx);
1211145b7b3cSmrg
1212145b7b3cSmrg    if (ctx->login.state != PROMPTING) {
1213145b7b3cSmrg	return;
1214145b7b3cSmrg    }
1215145b7b3cSmrg
1216145b7b3cSmrg    XorCursor (ctx);
1217145b7b3cSmrg
1218145b7b3cSmrg    for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) {
1219145b7b3cSmrg	if (nextPrompt > LAST_PROMPT) {
1220145b7b3cSmrg	    nextPrompt = 0;
1221145b7b3cSmrg	}
1222578741aaSmrg
1223145b7b3cSmrg	if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) ||
1224145b7b3cSmrg	    (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) {
1225145b7b3cSmrg	    ctx->login.activePrompt = nextPrompt;
1226145b7b3cSmrg	    break;
1227145b7b3cSmrg	}
1228145b7b3cSmrg    }
1229145b7b3cSmrg    XorCursor (ctx);
1230145b7b3cSmrg}
1231145b7b3cSmrg
1232145b7b3cSmrg/*ARGSUSED*/
1233145b7b3cSmrgstatic void
1234145b7b3cSmrgAllowAccess (
1235145b7b3cSmrg    Widget	ctxw,
1236145b7b3cSmrg    XEvent	*event,
1237145b7b3cSmrg    String	*params,
1238145b7b3cSmrg    Cardinal	*num_params)
1239145b7b3cSmrg{
1240145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1241145b7b3cSmrg    Arg	arglist[1];
1242145b7b3cSmrg    Boolean allow;
1243145b7b3cSmrg
1244145b7b3cSmrg    RemoveFail (ctx);
1245145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
1246145b7b3cSmrg    XtGetValues ((Widget) ctx, arglist, 1);
1247145b7b3cSmrg    XtSetArg (arglist[0], XtNallowAccess, !allow);
1248145b7b3cSmrg    XtSetValues ((Widget) ctx, arglist, 1);
1249145b7b3cSmrg}
1250145b7b3cSmrg
1251145b7b3cSmrg/*ARGSUSED*/
1252145b7b3cSmrgstatic void
1253145b7b3cSmrgSetSessionArgument (
1254145b7b3cSmrg    Widget	ctxw,
1255145b7b3cSmrg    XEvent	*event,
1256145b7b3cSmrg    String	*params,
1257145b7b3cSmrg    Cardinal	*num_params)
1258145b7b3cSmrg{
1259145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1260145b7b3cSmrg
1261145b7b3cSmrg    RemoveFail (ctx);
1262145b7b3cSmrg    if (ctx->login.sessionArg)
1263145b7b3cSmrg	XtFree (ctx->login.sessionArg);
1264145b7b3cSmrg    ctx->login.sessionArg = NULL;
1265145b7b3cSmrg    if (*num_params > 0) {
1266145b7b3cSmrg	ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
1267145b7b3cSmrg	if (ctx->login.sessionArg)
1268145b7b3cSmrg	    strcpy (ctx->login.sessionArg, params[0]);
1269145b7b3cSmrg	else
1270145b7b3cSmrg	    LogOutOfMem ("set session argument");
1271145b7b3cSmrg    }
1272145b7b3cSmrg}
1273145b7b3cSmrg
1274145b7b3cSmrg/*ARGSUSED*/
1275145b7b3cSmrgstatic void
1276145b7b3cSmrgRestartSession (
1277145b7b3cSmrg    Widget	ctxw,
1278145b7b3cSmrg    XEvent	*event,
1279145b7b3cSmrg    String	*params,
1280145b7b3cSmrg    Cardinal	*num_params)
1281145b7b3cSmrg{
1282145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1283145b7b3cSmrg
1284145b7b3cSmrg    XorCursor (ctx);
1285145b7b3cSmrg    RemoveFail (ctx);
1286145b7b3cSmrg    ctx->login.state = DONE;
1287145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
1288145b7b3cSmrg    XorCursor (ctx);
1289145b7b3cSmrg}
1290145b7b3cSmrg
1291145b7b3cSmrg/*ARGSUSED*/
1292145b7b3cSmrgstatic void
1293145b7b3cSmrgAbortSession (
1294145b7b3cSmrg    Widget	ctxw,
1295145b7b3cSmrg    XEvent	*event,
1296145b7b3cSmrg    String	*params,
1297145b7b3cSmrg    Cardinal	*num_params)
1298145b7b3cSmrg{
1299145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1300145b7b3cSmrg
1301145b7b3cSmrg    XorCursor (ctx);
1302145b7b3cSmrg    RemoveFail (ctx);
1303145b7b3cSmrg    ctx->login.state = DONE;
1304145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
1305145b7b3cSmrg    XorCursor (ctx);
1306145b7b3cSmrg}
1307145b7b3cSmrg
1308145b7b3cSmrg/*ARGSUSED*/
1309145b7b3cSmrgstatic void
1310145b7b3cSmrgAbortDisplay (
1311145b7b3cSmrg    Widget	ctxw,
1312145b7b3cSmrg    XEvent	*event,
1313145b7b3cSmrg    String	*params,
1314145b7b3cSmrg    Cardinal	*num_params)
1315145b7b3cSmrg{
1316145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1317145b7b3cSmrg
1318145b7b3cSmrg    XorCursor (ctx);
1319145b7b3cSmrg    RemoveFail (ctx);
1320145b7b3cSmrg    ctx->login.state = DONE;
1321145b7b3cSmrg    (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
1322145b7b3cSmrg    XorCursor (ctx);
1323145b7b3cSmrg}
1324145b7b3cSmrg
1325145b7b3cSmrgstatic void
1326145b7b3cSmrgResetLogin (LoginWidget w)
1327145b7b3cSmrg{
1328145b7b3cSmrg    int i;
1329145b7b3cSmrg
1330145b7b3cSmrg    for (i = 0; i < NUM_PROMPTS ; i++) {
1331145b7b3cSmrg	EraseValue(w, 0, i);
1332145b7b3cSmrg	bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i));
1333145b7b3cSmrg	VALUE_SHOW_START(w, i) = 0;
1334145b7b3cSmrg	PROMPT_CURSOR(w, i) = 0;
1335145b7b3cSmrg    }
1336145b7b3cSmrg    w->login.state = PROMPTING;
1337145b7b3cSmrg    w->login.activePrompt = 0;
1338145b7b3cSmrg}
1339145b7b3cSmrg
1340145b7b3cSmrgstatic void
1341145b7b3cSmrgInitI18N(Widget ctxw)
1342145b7b3cSmrg{
1343145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1344145b7b3cSmrg    XIM         xim = (XIM) NULL;
1345145b7b3cSmrg    char *p;
1346145b7b3cSmrg
1347145b7b3cSmrg    ctx->login.xic = (XIC) NULL;
1348145b7b3cSmrg
1349145b7b3cSmrg    if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
1350145b7b3cSmrg	xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL);
1351145b7b3cSmrg
1352145b7b3cSmrg    if (!xim) {
1353145b7b3cSmrg	LogError("Failed to open input method\n");
1354145b7b3cSmrg	return;
1355145b7b3cSmrg    }
1356145b7b3cSmrg
1357145b7b3cSmrg    ctx->login.xic = XCreateIC(xim,
1358145b7b3cSmrg	XNInputStyle, (XIMPreeditNothing|XIMStatusNothing),
1359145b7b3cSmrg	XNClientWindow, ctx->core.window,
1360145b7b3cSmrg	XNFocusWindow,  ctx->core.window, NULL);
1361145b7b3cSmrg
1362145b7b3cSmrg    if (!ctx->login.xic) {
1363145b7b3cSmrg	LogError("Failed to create input context\n");
1364145b7b3cSmrg	XCloseIM(xim);
1365145b7b3cSmrg    }
1366145b7b3cSmrg    return;
1367145b7b3cSmrg}
1368145b7b3cSmrg
1369145b7b3cSmrg/* ARGSUSED */
1370145b7b3cSmrgstatic void
1371145b7b3cSmrgInsertChar (
1372145b7b3cSmrg    Widget	ctxw,
1373145b7b3cSmrg    XEvent	*event,
1374145b7b3cSmrg    String	*params,
1375145b7b3cSmrg    Cardinal	*num_params)
1376145b7b3cSmrg{
1377145b7b3cSmrg    LoginWidget ctx = (LoginWidget)ctxw;
1378145b7b3cSmrg
1379145b7b3cSmrg    char strbuf[128];
1380145b7b3cSmrg    int  len, promptNum = ctx->login.activePrompt;
1381145b7b3cSmrg    KeySym  keysym = 0;
1382145b7b3cSmrg
1383145b7b3cSmrg    if (ctx->login.xic) {
1384145b7b3cSmrg	static Status status;
1385145b7b3cSmrg	len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf,
1386145b7b3cSmrg			      sizeof (strbuf), &keysym, &status);
1387145b7b3cSmrg    } else {
1388145b7b3cSmrg	static XComposeStatus compose_status = {NULL, 0};
1389145b7b3cSmrg	len = XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1390145b7b3cSmrg			     &keysym, &compose_status);
1391145b7b3cSmrg    }
1392145b7b3cSmrg    strbuf[len] = '\0';
1393145b7b3cSmrg
1394145b7b3cSmrg    /*
1395145b7b3cSmrg     * Note: You can override this default key handling
1396145b7b3cSmrg     * by the settings in the translation table
1397145b7b3cSmrg     * loginActionsTable at the end of this file.
1398145b7b3cSmrg     */
1399145b7b3cSmrg    switch (keysym) {
1400145b7b3cSmrg    case XK_Return:
1401145b7b3cSmrg    case XK_KP_Enter:
1402145b7b3cSmrg    case XK_Linefeed:
1403145b7b3cSmrg    case XK_Execute:
1404145b7b3cSmrg	FinishField(ctxw, event, params, num_params);
1405145b7b3cSmrg	return;
1406145b7b3cSmrg    case XK_BackSpace:
1407145b7b3cSmrg	DeleteBackwardChar(ctxw, event, params, num_params);
1408145b7b3cSmrg	return;
1409145b7b3cSmrg    case XK_Delete:
1410145b7b3cSmrg    case XK_KP_Delete:
1411145b7b3cSmrg    case DXK_Remove:
1412145b7b3cSmrg	/* Sorry, it's not a telex machine, it's a terminal */
1413145b7b3cSmrg	DeleteForwardChar(ctxw, event, params, num_params);
1414145b7b3cSmrg	return;
1415145b7b3cSmrg    case XK_Left:
1416145b7b3cSmrg    case XK_KP_Left:
1417145b7b3cSmrg	MoveBackwardChar(ctxw, event, params, num_params);
1418145b7b3cSmrg	return;
1419145b7b3cSmrg    case XK_Right:
1420145b7b3cSmrg    case XK_KP_Right:
1421145b7b3cSmrg	MoveForwardChar(ctxw, event, params, num_params);
1422145b7b3cSmrg	return;
1423145b7b3cSmrg    case XK_End:
1424145b7b3cSmrg    case XK_KP_End:
1425145b7b3cSmrg	MoveToEnd(ctxw, event, params, num_params);
1426145b7b3cSmrg	return;
1427145b7b3cSmrg    case XK_Home:
1428145b7b3cSmrg    case XK_KP_Home:
1429145b7b3cSmrg	MoveToBegining(ctxw, event, params, num_params);
1430145b7b3cSmrg	return;
1431145b7b3cSmrg    default:
1432145b7b3cSmrg	if (len == 0) {
1433145b7b3cSmrg	    if (!IsModifierKey(keysym))  /* it's not a modifier */
1434145b7b3cSmrg		XBell(XtDisplay(ctxw), 60);
1435145b7b3cSmrg	    return;
1436145b7b3cSmrg	} else
1437145b7b3cSmrg	    break;
1438145b7b3cSmrg    }
1439145b7b3cSmrg
1440578741aaSmrg    if (ctx->login.state == PROMPTING) {
1441145b7b3cSmrg	if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >=
1442145b7b3cSmrg	     (VALUE_TEXT_MAX(ctx,promptNum) - 1))) {
1443145b7b3cSmrg	    len = VALUE_TEXT_MAX(ctx,promptNum) -
1444145b7b3cSmrg		strlen(VALUE_TEXT(ctx, promptNum)) - 2;
1445145b7b3cSmrg	}
1446145b7b3cSmrg    }
1447145b7b3cSmrg    EraseCursor (ctx);
1448145b7b3cSmrg    RemoveFail (ctx);
1449145b7b3cSmrg    if (len != 0)
1450145b7b3cSmrg    {
1451145b7b3cSmrg	if (ctx->login.state == PROMPTING) {
1452145b7b3cSmrg	    EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1453145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len,
1454145b7b3cSmrg		    VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1455145b7b3cSmrg		    strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1);
1456145b7b3cSmrg	    memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum),
1457145b7b3cSmrg		     strbuf, len);
1458145b7b3cSmrg	    DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum);
1459145b7b3cSmrg	    PROMPT_CURSOR(ctx, promptNum) += len;
1460145b7b3cSmrg	}
1461145b7b3cSmrg    }
1462145b7b3cSmrg    XorCursor (ctx);
1463145b7b3cSmrg}
1464145b7b3cSmrg
1465145b7b3cSmrg
1466145b7b3cSmrg/**** Copied from xclock.c - original author: Keith Packard ****/
1467145b7b3cSmrg#ifdef USE_XFT
1468145b7b3cSmrgstatic XtConvertArgRec xftColorConvertArgs[] = {
1469145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1470145b7b3cSmrg     sizeof(Screen *)},
1471145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
1472145b7b3cSmrg     sizeof(Colormap)}
1473145b7b3cSmrg};
1474145b7b3cSmrg
1475578741aaSmrg# define	donestr(type, value, tstr) \
1476145b7b3cSmrg	{							\
1477145b7b3cSmrg	    if (toVal->addr != NULL) {				\
1478145b7b3cSmrg		if (toVal->size < sizeof(type)) {		\
1479145b7b3cSmrg		    toVal->size = sizeof(type);			\
1480145b7b3cSmrg		    XtDisplayStringConversionWarning(dpy, 	\
1481145b7b3cSmrg			(char*) fromVal->addr, tstr);		\
1482145b7b3cSmrg		    return False;				\
1483145b7b3cSmrg		}						\
1484145b7b3cSmrg		*(type*)(toVal->addr) = (value);		\
1485145b7b3cSmrg	    }							\
1486145b7b3cSmrg	    else {						\
1487145b7b3cSmrg		static type static_val;				\
1488145b7b3cSmrg		static_val = (value);				\
1489145b7b3cSmrg		toVal->addr = (XPointer)&static_val;		\
1490145b7b3cSmrg	    }							\
1491145b7b3cSmrg	    toVal->size = sizeof(type);				\
1492145b7b3cSmrg	    return True;					\
1493145b7b3cSmrg	}
1494145b7b3cSmrg
1495145b7b3cSmrgstatic void
1496145b7b3cSmrgXmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1497145b7b3cSmrg		 XrmValuePtr args, Cardinal *num_args)
1498145b7b3cSmrg{
1499145b7b3cSmrg    Screen	*screen;
1500145b7b3cSmrg    Colormap	colormap;
1501145b7b3cSmrg    XftColor	*color;
1502578741aaSmrg
1503145b7b3cSmrg    if (*num_args != 2)
1504145b7b3cSmrg    {
1505145b7b3cSmrg	XtAppErrorMsg (app,
1506145b7b3cSmrg		       "freeXftColor", "wrongParameters",
1507145b7b3cSmrg		       "XtToolkitError",
1508145b7b3cSmrg		       "Freeing an XftColor requires screen and colormap arguments",
1509145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1510145b7b3cSmrg	return;
1511145b7b3cSmrg    }
1512145b7b3cSmrg
1513145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1514145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1515145b7b3cSmrg    color = (XftColor *) toVal->addr;
1516145b7b3cSmrg    XftColorFree (DisplayOfScreen (screen),
1517145b7b3cSmrg		  DefaultVisual (DisplayOfScreen (screen),
1518145b7b3cSmrg				 XScreenNumberOfScreen (screen)),
1519145b7b3cSmrg		  colormap, color);
1520145b7b3cSmrg}
1521578741aaSmrg
1522145b7b3cSmrgstatic Boolean
1523145b7b3cSmrgXmuCvtStringToXftColor(Display *dpy,
1524145b7b3cSmrg		       XrmValue *args, Cardinal *num_args,
1525145b7b3cSmrg		       XrmValue *fromVal, XrmValue *toVal,
1526145b7b3cSmrg		       XtPointer *converter_data)
1527145b7b3cSmrg{
1528145b7b3cSmrg    char	    *spec;
1529145b7b3cSmrg    XRenderColor    renderColor;
1530145b7b3cSmrg    XftColor	    xftColor;
1531145b7b3cSmrg    Screen	    *screen;
1532145b7b3cSmrg    Colormap	    colormap;
1533578741aaSmrg
1534145b7b3cSmrg    if (*num_args != 2)
1535145b7b3cSmrg    {
1536145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1537145b7b3cSmrg		       "cvtStringToXftColor", "wrongParameters",
1538145b7b3cSmrg		       "XtToolkitError",
1539145b7b3cSmrg		       "String to render color conversion needs screen and colormap arguments",
1540145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1541145b7b3cSmrg	return False;
1542145b7b3cSmrg    }
1543145b7b3cSmrg
1544145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1545145b7b3cSmrg    colormap = *((Colormap *) args[1].addr);
1546145b7b3cSmrg
1547145b7b3cSmrg    spec = (char *) fromVal->addr;
1548145b7b3cSmrg    if (strcasecmp (spec, XtDefaultForeground) == 0)
1549145b7b3cSmrg    {
1550145b7b3cSmrg	renderColor.red = 0;
1551145b7b3cSmrg	renderColor.green = 0;
1552145b7b3cSmrg	renderColor.blue = 0;
1553145b7b3cSmrg	renderColor.alpha = 0xffff;
1554145b7b3cSmrg    }
1555145b7b3cSmrg    else if (strcasecmp (spec, XtDefaultBackground) == 0)
1556145b7b3cSmrg    {
1557145b7b3cSmrg	renderColor.red = 0xffff;
1558145b7b3cSmrg	renderColor.green = 0xffff;
1559145b7b3cSmrg	renderColor.blue = 0xffff;
1560145b7b3cSmrg	renderColor.alpha = 0xffff;
1561145b7b3cSmrg    }
1562145b7b3cSmrg    else if (!XRenderParseColor (dpy, spec, &renderColor))
1563145b7b3cSmrg	return False;
1564578741aaSmrg    if (!XftColorAllocValue (dpy,
1565145b7b3cSmrg			     DefaultVisual (dpy,
1566145b7b3cSmrg					    XScreenNumberOfScreen (screen)),
1567145b7b3cSmrg			     colormap,
1568145b7b3cSmrg			     &renderColor,
1569145b7b3cSmrg			     &xftColor))
1570145b7b3cSmrg	return False;
1571578741aaSmrg
1572145b7b3cSmrg    donestr (XftColor, xftColor, XtRXftColor);
1573145b7b3cSmrg}
1574145b7b3cSmrg
1575145b7b3cSmrgstatic void
1576145b7b3cSmrgXmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
1577145b7b3cSmrg		XrmValuePtr args, Cardinal *num_args)
1578145b7b3cSmrg{
1579145b7b3cSmrg    Screen  *screen;
1580145b7b3cSmrg    XftFont *font;
1581578741aaSmrg
1582145b7b3cSmrg    if (*num_args != 1)
1583145b7b3cSmrg    {
1584145b7b3cSmrg	XtAppErrorMsg (app,
1585145b7b3cSmrg		       "freeXftFont", "wrongParameters",
1586145b7b3cSmrg		       "XtToolkitError",
1587145b7b3cSmrg		       "Freeing an XftFont requires screen argument",
1588145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1589145b7b3cSmrg	return;
1590145b7b3cSmrg    }
1591145b7b3cSmrg
1592145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1593145b7b3cSmrg    font = *((XftFont **) toVal->addr);
1594145b7b3cSmrg    if (font)
1595145b7b3cSmrg	XftFontClose (DisplayOfScreen (screen), font);
1596145b7b3cSmrg}
1597145b7b3cSmrg
1598145b7b3cSmrgstatic Boolean
1599145b7b3cSmrgXmuCvtStringToXftFont(Display *dpy,
1600145b7b3cSmrg		      XrmValue *args, Cardinal *num_args,
1601145b7b3cSmrg		      XrmValue *fromVal, XrmValue *toVal,
1602145b7b3cSmrg		      XtPointer *converter_data)
1603145b7b3cSmrg{
1604145b7b3cSmrg    char    *name;
1605145b7b3cSmrg    XftFont *font;
1606145b7b3cSmrg    Screen  *screen;
1607578741aaSmrg
1608145b7b3cSmrg    if (*num_args != 1)
1609145b7b3cSmrg    {
1610145b7b3cSmrg	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
1611145b7b3cSmrg		       "cvtStringToXftFont", "wrongParameters",
1612145b7b3cSmrg		       "XtToolkitError",
1613145b7b3cSmrg		       "String to XftFont conversion needs screen argument",
1614145b7b3cSmrg		       (String *) NULL, (Cardinal *)NULL);
1615145b7b3cSmrg	return False;
1616145b7b3cSmrg    }
1617145b7b3cSmrg
1618145b7b3cSmrg    screen = *((Screen **) args[0].addr);
1619145b7b3cSmrg    name = (char *) fromVal->addr;
1620578741aaSmrg
1621145b7b3cSmrg    font = XftFontOpenName (dpy,
1622145b7b3cSmrg			    XScreenNumberOfScreen (screen),
1623145b7b3cSmrg			    name);
1624145b7b3cSmrg    if (font)
1625145b7b3cSmrg    {
1626145b7b3cSmrg	donestr (XftFont *, font, XtRXftFont);
1627145b7b3cSmrg    }
1628145b7b3cSmrg    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
1629145b7b3cSmrg    return False;
1630145b7b3cSmrg}
1631145b7b3cSmrg
1632145b7b3cSmrgstatic XtConvertArgRec xftFontConvertArgs[] = {
1633145b7b3cSmrg    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1634145b7b3cSmrg     sizeof(Screen *)},
1635145b7b3cSmrg};
1636145b7b3cSmrg
1637145b7b3cSmrg
1638145b7b3cSmrgstatic int
1639145b7b3cSmrgXmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len)
1640145b7b3cSmrg{
1641145b7b3cSmrg    XGlyphInfo  extents;
1642145b7b3cSmrg
1643145b7b3cSmrg    XftTextExtents8 (dpy, font, string, len, &extents);
1644145b7b3cSmrg
1645145b7b3cSmrg    return extents.xOff;
1646145b7b3cSmrg}
1647145b7b3cSmrg
1648145b7b3cSmrg#endif /* USE_XFT */
1649145b7b3cSmrg
1650578741aaSmrgstatic void
1651145b7b3cSmrgClassInitialize(void)
1652145b7b3cSmrg{
1653145b7b3cSmrg#ifdef USE_XFT
1654578741aaSmrg    XtSetTypeConverter (XtRString, XtRXftColor,
1655578741aaSmrg			XmuCvtStringToXftColor,
1656145b7b3cSmrg			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
1657145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftColor);
1658145b7b3cSmrg    XtSetTypeConverter (XtRString, XtRXftFont,
1659145b7b3cSmrg			XmuCvtStringToXftFont,
1660145b7b3cSmrg			xftFontConvertArgs, XtNumber(xftFontConvertArgs),
1661145b7b3cSmrg			XtCacheByDisplay, XmuFreeXftFont);
1662145b7b3cSmrg#endif /* USE_XFT */
1663145b7b3cSmrg}
1664145b7b3cSmrg/**** End of portion borrowed from xclock ****/
1665145b7b3cSmrg
1666145b7b3cSmrg/* ARGSUSED */
1667145b7b3cSmrgstatic void Initialize (
1668145b7b3cSmrg    Widget greq,
1669145b7b3cSmrg    Widget gnew,
1670145b7b3cSmrg    ArgList args,
1671145b7b3cSmrg    Cardinal *num_args)
1672145b7b3cSmrg{
1673145b7b3cSmrg    LoginWidget w = (LoginWidget)gnew;
1674145b7b3cSmrg    XtGCMask	valuemask, xvaluemask;
1675145b7b3cSmrg    XGCValues	myXGCV;
1676145b7b3cSmrg    Arg		position[2];
1677145b7b3cSmrg    Position	x, y;
1678145b7b3cSmrg#ifdef USE_XINERAMA
1679145b7b3cSmrg    XineramaScreenInfo *screens;
1680145b7b3cSmrg    int                 s_num;
1681145b7b3cSmrg#endif
1682145b7b3cSmrg    int 	rv = 0;
1683578741aaSmrg
1684145b7b3cSmrg    myXGCV.foreground = w->login.hipixel;
1685145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1686145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1687145b7b3cSmrg    w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV);
1688145b7b3cSmrg
1689145b7b3cSmrg    myXGCV.foreground = w->login.shdpixel;
1690145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1691145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1692145b7b3cSmrg    w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV);
1693145b7b3cSmrg
1694b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1695b7d26471Smrg    myXGCV.background = w->core.background_pixel;
1696b7d26471Smrg    valuemask = GCForeground | GCBackground;
1697b7d26471Smrg    w->login.inpGC = XtGetGC(gnew, valuemask, &myXGCV);
1698b7d26471Smrg
1699145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(text);
1700145b7b3cSmrg    myXGCV.background = w->core.background_pixel;
1701145b7b3cSmrg    valuemask = GCForeground | GCBackground;
1702145b7b3cSmrg#ifndef USE_XFT
1703145b7b3cSmrg    if (w->login.textFont) {
1704145b7b3cSmrg	myXGCV.font = w->login.textFont->fid;
1705145b7b3cSmrg	valuemask |= GCFont;
1706145b7b3cSmrg    }
1707578741aaSmrg#endif
1708145b7b3cSmrg    w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
1709b7d26471Smrg    myXGCV.foreground = w->login.inppixel;
1710145b7b3cSmrg    w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
1711145b7b3cSmrg
1712b7d26471Smrg    myXGCV.foreground = TEXT_COLOR(text) ^ w->login.inppixel;
1713145b7b3cSmrg    myXGCV.function = GXxor;
1714145b7b3cSmrg    xvaluemask = valuemask | GCFunction;
1715145b7b3cSmrg    w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1716145b7b3cSmrg
1717145b7b3cSmrg#ifndef USE_XFT
1718145b7b3cSmrg    /*
1719145b7b3cSmrg     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
1720145b7b3cSmrg     * returns the curently contained font.
1721145b7b3cSmrg     */
1722145b7b3cSmrg
1723145b7b3cSmrg    if (w->login.textFont == NULL)
1724145b7b3cSmrg	w->login.textFont = XQueryFont (XtDisplay (w),
1725145b7b3cSmrg		XGContextFromGC (XDefaultGCOfScreen (XtScreen (w))));
1726145b7b3cSmrg
1727145b7b3cSmrg    xvaluemask = valuemask;
1728145b7b3cSmrg    if (w->login.promptFont == NULL)
1729145b7b3cSmrg        w->login.promptFont = w->login.textFont;
1730145b7b3cSmrg    else
1731145b7b3cSmrg	xvaluemask |= GCFont;
1732145b7b3cSmrg
1733145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(prompt);
1734145b7b3cSmrg    myXGCV.font = w->login.promptFont->fid;
1735145b7b3cSmrg    w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1736145b7b3cSmrg
1737145b7b3cSmrg    xvaluemask = valuemask;
1738145b7b3cSmrg    if (w->login.greetFont == NULL)
1739629baa8cSmrg	w->login.greetFont = w->login.textFont;
1740145b7b3cSmrg    else
1741145b7b3cSmrg	xvaluemask |= GCFont;
1742145b7b3cSmrg
1743145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(greet);
1744145b7b3cSmrg    myXGCV.font = w->login.greetFont->fid;
1745145b7b3cSmrg    w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1746145b7b3cSmrg
1747145b7b3cSmrg    xvaluemask = valuemask;
1748145b7b3cSmrg    if (w->login.failFont == NULL)
1749145b7b3cSmrg	w->login.failFont = w->login.textFont;
1750145b7b3cSmrg    else
1751145b7b3cSmrg	xvaluemask |= GCFont;
1752145b7b3cSmrg    myXGCV.foreground = TEXT_COLOR(fail);
1753145b7b3cSmrg    myXGCV.font = w->login.failFont->fid;
1754145b7b3cSmrg    w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
1755145b7b3cSmrg#endif /* USE_XFT */
1756145b7b3cSmrg
1757145b7b3cSmrg#ifdef XPM
1758145b7b3cSmrg    w->login.logoValid = False;
1759145b7b3cSmrg
1760145b7b3cSmrg    if (NULL != w->login.logoFileName)
1761145b7b3cSmrg    {
1762145b7b3cSmrg        XpmAttributes myAttributes = { 0 };
1763145b7b3cSmrg        Window tmpWindow = { 0 };
1764145b7b3cSmrg        struct stat myBuffer = { 0 };
1765145b7b3cSmrg        unsigned int myPixmapDepth = 0;
1766145b7b3cSmrg
1767145b7b3cSmrg        if (0 != stat(w->login.logoFileName, &myBuffer))
1768145b7b3cSmrg        {
1769145b7b3cSmrg            LogError("Unable to stat() pixmap file %s\n",
1770145b7b3cSmrg                w->login.logoFileName);
1771145b7b3cSmrg            w->login.logoValid = False;
1772145b7b3cSmrg            goto SkipXpmLoad;
1773145b7b3cSmrg        }
1774145b7b3cSmrg
1775145b7b3cSmrg        myAttributes.valuemask |= XpmReturnPixels;
1776145b7b3cSmrg        myAttributes.valuemask |= XpmReturnExtensions;
1777145b7b3cSmrg
1778145b7b3cSmrg        rv = XpmReadFileToPixmap(XtDisplay(w),		/* display */
1779145b7b3cSmrg	     RootWindowOfScreen(XtScreen(w)),		/* window */
1780145b7b3cSmrg	     w->login.logoFileName,			/* XPM filename */
1781145b7b3cSmrg	     &(w->login.logoPixmap),			/* pixmap */
1782145b7b3cSmrg	     &(w->login.logoMask),			/* pixmap mask */
1783145b7b3cSmrg	     &myAttributes);				/* XPM attributes */
1784578741aaSmrg
1785145b7b3cSmrg	if ( rv < 0 )
1786145b7b3cSmrg	{
1787145b7b3cSmrg	    LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName,
1788145b7b3cSmrg		     XpmGetErrorString(rv));
1789145b7b3cSmrg	    goto SkipXpmLoad;
1790145b7b3cSmrg	}
1791145b7b3cSmrg
1792145b7b3cSmrg	w->login.logoValid = True;
1793145b7b3cSmrg
1794145b7b3cSmrg        XGetGeometry(XtDisplay(w), w->login.logoPixmap,
1795145b7b3cSmrg            &tmpWindow,
1796145b7b3cSmrg            &(w->login.logoX),
1797145b7b3cSmrg            &(w->login.logoY),
1798145b7b3cSmrg            &(w->login.logoWidth),
1799145b7b3cSmrg            &(w->login.logoHeight),
1800145b7b3cSmrg            &(w->login.logoBorderWidth),
1801145b7b3cSmrg            &myPixmapDepth);
1802145b7b3cSmrg    } else {
1803145b7b3cSmrg	w->login.logoX = 0;
1804145b7b3cSmrg	w->login.logoY = 0;
1805145b7b3cSmrg	w->login.logoWidth = 0;
1806145b7b3cSmrg	w->login.logoHeight = 0;
1807145b7b3cSmrg	w->login.logoBorderWidth = 0;
1808145b7b3cSmrg    }
1809145b7b3cSmrg
1810145b7b3cSmrg
1811145b7b3cSmrgSkipXpmLoad:
1812145b7b3cSmrg#endif /* XPM */
1813145b7b3cSmrg    w->login.data.name[0] = '\0';
1814145b7b3cSmrg    w->login.data.passwd[0] = '\0';
1815145b7b3cSmrg    w->login.state = INITIALIZING;
1816145b7b3cSmrg    w->login.activePrompt = LOGIN_PROMPT_USERNAME;
1817145b7b3cSmrg    w->login.failUp = 0;
1818145b7b3cSmrg    w->login.fail = (char *) w->login.failMsg;
1819145b7b3cSmrg
1820145b7b3cSmrg    /* Set prompt defaults */
1821145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= NULL;
1822145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.namePrompt;
1823145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) 	= w->login.data.name;
1824145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME)	= sizeof(w->login.data.name);
1825145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME)	= 0;
1826578741aaSmrg
1827145b7b3cSmrg    PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= NULL;
1828145b7b3cSmrg    DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.passwdPrompt;
1829145b7b3cSmrg    VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) 	= w->login.data.passwd;
1830145b7b3cSmrg    VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD)	= sizeof(w->login.data.passwd);
1831145b7b3cSmrg    VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD)	= 0;
1832145b7b3cSmrg
1833145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False);
1834145b7b3cSmrg    SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False);
1835578741aaSmrg
1836145b7b3cSmrg    if (w->core.width == 0)
1837145b7b3cSmrg	w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
1838145b7b3cSmrg    if (w->core.height == 0) {
1839145b7b3cSmrg	int fy = FAIL_Y(w);
1840145b7b3cSmrg	int pady = PAD_Y(w);
1841145b7b3cSmrg
1842145b7b3cSmrg#ifndef XPM
1843145b7b3cSmrg	w->core.height = fy + pady;	/* for stupid compilers */
1844145b7b3cSmrg#else
1845145b7b3cSmrg/*	w->core.height = fy + pady;	* for stupid compilers */
1846145b7b3cSmrg
1847145b7b3cSmrg        w->core.height = max(fy + pady,
1848145b7b3cSmrg            (w->login.logoHeight + (2*w->login.logoPadding)) + pady);
1849578741aaSmrg
1850145b7b3cSmrg#endif /* XPM */
1851145b7b3cSmrg    }
1852145b7b3cSmrg#ifdef USE_XINERAMA
1853145b7b3cSmrg    if (
1854145b7b3cSmrg	XineramaIsActive(XtDisplay(w)) &&
1855145b7b3cSmrg	(screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL
1856145b7b3cSmrg       )
1857145b7b3cSmrg    {
1858145b7b3cSmrg	if ((x = w->core.x) == -1)
1859145b7b3cSmrg	    x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2;
1860145b7b3cSmrg	if ((y = w->core.y) == -1)
1861145b7b3cSmrg	    y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3;
1862578741aaSmrg
1863145b7b3cSmrg	XFree(screens);
1864145b7b3cSmrg    }
1865145b7b3cSmrg    else
1866145b7b3cSmrg#endif
1867145b7b3cSmrg    {
1868145b7b3cSmrg	if ((x = w->core.x) == -1)
1869145b7b3cSmrg	    x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2;
1870145b7b3cSmrg	if ((y = w->core.y) == -1)
1871145b7b3cSmrg	    y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3;
1872145b7b3cSmrg    }
1873145b7b3cSmrg    XtSetArg (position[0], XtNx, x);
1874145b7b3cSmrg    XtSetArg (position[1], XtNy, y);
1875145b7b3cSmrg    XtSetValues (XtParent (w), position, (Cardinal) 2);
1876145b7b3cSmrg
1877145b7b3cSmrg    w->login.state = PROMPTING;
1878145b7b3cSmrg}
1879145b7b3cSmrg
1880578741aaSmrg
1881145b7b3cSmrgstatic void Realize (
1882145b7b3cSmrg     Widget gw,
1883145b7b3cSmrg     XtValueMask *valueMask,
1884145b7b3cSmrg     XSetWindowAttributes *attrs)
1885145b7b3cSmrg{
1886145b7b3cSmrg    LoginWidget	w = (LoginWidget) gw;
1887145b7b3cSmrg    Cursor cursor;
1888145b7b3cSmrg
1889145b7b3cSmrg    XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
1890145b7b3cSmrg		     *valueMask, attrs );
1891145b7b3cSmrg    InitI18N(gw);
1892145b7b3cSmrg
1893145b7b3cSmrg#ifdef USE_XFT
1894145b7b3cSmrg    w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w),
1895145b7b3cSmrg	   DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))),
1896145b7b3cSmrg				   w->core.colormap);
1897145b7b3cSmrg
1898145b7b3cSmrg#endif
1899145b7b3cSmrg
1900145b7b3cSmrg    cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr);
1901145b7b3cSmrg    XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor);
1902145b7b3cSmrg
1903145b7b3cSmrg#ifdef XPM
1904578741aaSmrg    /*
1905145b7b3cSmrg     * Check if Pixmap was valid
1906145b7b3cSmrg     */
1907145b7b3cSmrg    if (True == w->login.logoValid)
1908145b7b3cSmrg    {
1909145b7b3cSmrg        /*
1910578741aaSmrg         * Create pixmap window
1911145b7b3cSmrg         */
1912145b7b3cSmrg        {
1913629baa8cSmrg            XSetWindowAttributes windowAttributes = {
1914629baa8cSmrg                .background_pixel = w->core.background_pixel,
1915629baa8cSmrg                .background_pixmap = None
1916629baa8cSmrg            };
1917145b7b3cSmrg
1918145b7b3cSmrg            w->login.logoWindow = XCreateWindow(XtDisplay(w),
1919145b7b3cSmrg                XtWindow(w),
1920145b7b3cSmrg                w->core.width - w->login.outframewidth -
1921145b7b3cSmrg                    w->login.logoWidth - w->login.logoPadding,
1922145b7b3cSmrg                (w->core.height - w->login.logoHeight) /2,
1923145b7b3cSmrg                w->login.logoWidth, w->login.logoHeight, 0,
1924145b7b3cSmrg                CopyFromParent, InputOutput, CopyFromParent,
1925629baa8cSmrg                CWBackPixel | CWBackPixmap, &windowAttributes);
1926145b7b3cSmrg        }
1927145b7b3cSmrg
1928145b7b3cSmrg        /*
1929145b7b3cSmrg         * check if we can use shape extension
1930145b7b3cSmrg         */
1931145b7b3cSmrg        if (True == w->login.useShape)
1932145b7b3cSmrg        {
1933145b7b3cSmrg            int foo, bar;
1934145b7b3cSmrg
1935145b7b3cSmrg            if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE)
1936145b7b3cSmrg            {
1937145b7b3cSmrg                XShapeCombineMask(XtDisplay(w), w->login.logoWindow,
1938145b7b3cSmrg                    ShapeBounding, w->login.logoX, w->login.logoY,
1939145b7b3cSmrg                    w->login.logoMask, ShapeSet);
1940145b7b3cSmrg            }
1941145b7b3cSmrg        }
1942145b7b3cSmrg
1943145b7b3cSmrg        XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow,
1944145b7b3cSmrg            w->login.logoPixmap);
1945145b7b3cSmrg        XMapWindow(XtDisplay(w), w->login.logoWindow);
1946145b7b3cSmrg    }
1947145b7b3cSmrg#endif /* XPM */
1948145b7b3cSmrg}
1949145b7b3cSmrg
1950145b7b3cSmrgstatic void Destroy (Widget gw)
1951145b7b3cSmrg{
1952145b7b3cSmrg    LoginWidget w = (LoginWidget)gw;
1953145b7b3cSmrg    bzero (w->login.data.name, NAME_LEN);
1954145b7b3cSmrg    bzero (w->login.data.passwd, PASSWORD_LEN);
1955145b7b3cSmrg
1956145b7b3cSmrg    if (PROMPT_TEXT(w,0) != NULL)
1957145b7b3cSmrg	XtFree(PROMPT_TEXT(w,0));
1958145b7b3cSmrg    if (PROMPT_TEXT(w,1) != NULL)
1959145b7b3cSmrg	XtFree(PROMPT_TEXT(w,1));
1960145b7b3cSmrg
1961145b7b3cSmrg#ifdef USE_XFT
1962145b7b3cSmrg    if (w->login.draw) {
1963145b7b3cSmrg	XftDrawDestroy(w->login.draw);
1964145b7b3cSmrg	w->login.draw = NULL;
1965145b7b3cSmrg    }
1966578741aaSmrg#endif
1967578741aaSmrg
1968145b7b3cSmrg    XtReleaseGC(gw, w->login.textGC);
1969145b7b3cSmrg    XtReleaseGC(gw, w->login.bgGC);
1970145b7b3cSmrg    XtReleaseGC(gw, w->login.xorGC);
1971145b7b3cSmrg#ifndef USE_XFT
1972145b7b3cSmrg    XtReleaseGC(gw, w->login.promptGC);
1973145b7b3cSmrg    XtReleaseGC(gw, w->login.greetGC);
1974145b7b3cSmrg    XtReleaseGC(gw, w->login.failGC);
1975145b7b3cSmrg#endif
1976145b7b3cSmrg    XtReleaseGC(gw, w->login.hiGC);
1977145b7b3cSmrg    XtReleaseGC(gw, w->login.shdGC);
1978b7d26471Smrg    XtReleaseGC(gw, w->login.inpGC);
1979145b7b3cSmrg
1980145b7b3cSmrg#ifdef XPM
1981145b7b3cSmrg    if (True == w->login.logoValid)
1982145b7b3cSmrg    {
1983145b7b3cSmrg        if (w->login.logoPixmap != 0)
1984145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoPixmap);
1985145b7b3cSmrg
1986145b7b3cSmrg        if (w->login.logoMask != 0)
1987145b7b3cSmrg            XFreePixmap(XtDisplay(w), w->login.logoMask);
1988145b7b3cSmrg    }
1989145b7b3cSmrg#endif /* XPM */
1990145b7b3cSmrg}
1991145b7b3cSmrg
1992145b7b3cSmrg/* ARGSUSED */
1993145b7b3cSmrgstatic void Redisplay(
1994145b7b3cSmrg     Widget gw,
1995145b7b3cSmrg     XEvent *event,
1996145b7b3cSmrg     Region region)
1997145b7b3cSmrg{
1998145b7b3cSmrg    draw_it ((LoginWidget) gw);
1999145b7b3cSmrg}
2000145b7b3cSmrg
2001145b7b3cSmrg/*ARGSUSED*/
2002145b7b3cSmrgstatic Boolean SetValues (
2003145b7b3cSmrg    Widget  current,
2004145b7b3cSmrg    Widget  request,
2005145b7b3cSmrg    Widget  new,
2006145b7b3cSmrg    ArgList args,
2007145b7b3cSmrg    Cardinal *num_args)
2008145b7b3cSmrg{
2009145b7b3cSmrg    LoginWidget currentL, newL;
2010578741aaSmrg
2011145b7b3cSmrg    currentL = (LoginWidget) current;
2012145b7b3cSmrg    newL = (LoginWidget) new;
2013145b7b3cSmrg    if (GREETING (currentL) != GREETING (newL))
2014145b7b3cSmrg	return True;
2015145b7b3cSmrg    return False;
2016145b7b3cSmrg}
2017145b7b3cSmrg
2018145b7b3cSmrgstatic
2019145b7b3cSmrgchar defaultLoginTranslations [] =
2020145b7b3cSmrg"Ctrl<Key>H:	delete-previous-character() \n"
2021145b7b3cSmrg"Ctrl<Key>D:	delete-character() \n"
2022145b7b3cSmrg"Ctrl<Key>B:	move-backward-character() \n"
2023145b7b3cSmrg"Ctrl<Key>F:	move-forward-character() \n"
2024145b7b3cSmrg"Ctrl<Key>A:	move-to-begining() \n"
2025145b7b3cSmrg"Ctrl<Key>E:	move-to-end() \n"
2026145b7b3cSmrg"Ctrl<Key>K:	erase-to-end-of-line() \n"
2027145b7b3cSmrg"Ctrl<Key>U:	erase-line() \n"
2028145b7b3cSmrg"Ctrl<Key>X:	erase-line() \n"
2029145b7b3cSmrg"Ctrl<Key>C:	restart-session() \n"
2030145b7b3cSmrg"Ctrl<Key>\\\\:	abort-session() \n"
2031145b7b3cSmrg":Ctrl<Key>plus:	allow-all-access() \n"
2032145b7b3cSmrg"<Key>BackSpace:	delete-previous-character() \n"
2033145b7b3cSmrg#ifdef linux
2034145b7b3cSmrg"<Key>Delete:	delete-character() \n"
2035145b7b3cSmrg#else
2036145b7b3cSmrg"<Key>Delete:	delete-previous-character() \n"
2037145b7b3cSmrg#endif
2038145b7b3cSmrg"<Key>Return:	finish-field() \n"
2039145b7b3cSmrg"<Key>Tab:	tab-field() \n"
2040145b7b3cSmrg"<KeyPress>:	insert-char()"
2041145b7b3cSmrg;
2042145b7b3cSmrg
2043145b7b3cSmrgstatic
2044145b7b3cSmrgXtActionsRec loginActionsTable [] = {
2045145b7b3cSmrg  {"delete-previous-character",	DeleteBackwardChar},
2046145b7b3cSmrg  {"delete-character",		DeleteForwardChar},
2047145b7b3cSmrg  {"move-backward-character",	MoveBackwardChar},
2048145b7b3cSmrg  {"move-forward-character",	MoveForwardChar},
2049145b7b3cSmrg  {"move-to-begining",		MoveToBegining},
2050145b7b3cSmrg  {"move-to-end",		MoveToEnd},
2051145b7b3cSmrg  {"erase-to-end-of-line",	EraseToEndOfLine},
2052145b7b3cSmrg  {"erase-line",		EraseLine},
2053145b7b3cSmrg  {"finish-field", 		FinishField},
2054145b7b3cSmrg  {"tab-field", 		TabField},
2055145b7b3cSmrg  {"abort-session",		AbortSession},
2056145b7b3cSmrg  {"abort-display",		AbortDisplay},
2057145b7b3cSmrg  {"restart-session",		RestartSession},
2058145b7b3cSmrg  {"insert-char", 		InsertChar},
2059145b7b3cSmrg  {"set-session-argument",	SetSessionArgument},
2060145b7b3cSmrg  {"allow-all-access",		AllowAccess},
2061145b7b3cSmrg};
2062145b7b3cSmrg
2063145b7b3cSmrgLoginClassRec loginClassRec = {
2064145b7b3cSmrg    { /* core fields */
2065145b7b3cSmrg    /* superclass		*/	&widgetClassRec,
2066145b7b3cSmrg    /* class_name		*/	"Login",
2067145b7b3cSmrg    /* size			*/	sizeof(LoginRec),
2068145b7b3cSmrg    /* class_initialize		*/	ClassInitialize,
2069145b7b3cSmrg    /* class_part_initialize	*/	NULL,
2070145b7b3cSmrg    /* class_inited		*/	FALSE,
2071145b7b3cSmrg    /* initialize		*/	Initialize,
2072145b7b3cSmrg    /* initialize_hook		*/	NULL,
2073145b7b3cSmrg    /* realize			*/	Realize,
2074145b7b3cSmrg    /* actions			*/	loginActionsTable,
2075145b7b3cSmrg    /* num_actions		*/	XtNumber (loginActionsTable),
2076145b7b3cSmrg    /* resources		*/	resources,
2077145b7b3cSmrg    /* num_resources		*/	XtNumber(resources),
2078145b7b3cSmrg    /* xrm_class		*/	NULLQUARK,
2079145b7b3cSmrg    /* compress_motion		*/	TRUE,
2080145b7b3cSmrg    /* compress_exposure	*/	TRUE,
2081145b7b3cSmrg    /* compress_enterleave	*/	TRUE,
2082145b7b3cSmrg    /* visible_interest		*/	FALSE,
2083145b7b3cSmrg    /* destroy			*/	Destroy,
2084145b7b3cSmrg    /* resize			*/	NULL,
2085145b7b3cSmrg    /* expose			*/	Redisplay,
2086145b7b3cSmrg    /* set_values		*/	SetValues,
2087145b7b3cSmrg    /* set_values_hook		*/	NULL,
2088145b7b3cSmrg    /* set_values_almost	*/	XtInheritSetValuesAlmost,
2089145b7b3cSmrg    /* get_values_hook		*/	NULL,
2090145b7b3cSmrg    /* accept_focus		*/	NULL,
2091145b7b3cSmrg    /* version			*/	XtVersion,
2092145b7b3cSmrg    /* callback_private		*/	NULL,
2093145b7b3cSmrg    /* tm_table			*/	defaultLoginTranslations,
2094145b7b3cSmrg    /* query_geometry		*/	XtInheritQueryGeometry,
2095145b7b3cSmrg    /* display_accelerator	*/	XtInheritDisplayAccelerator,
2096145b7b3cSmrg    /* extension		*/	NULL
2097145b7b3cSmrg    }
2098145b7b3cSmrg};
2099145b7b3cSmrg
2100145b7b3cSmrgWidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
2101