diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-01-01 21:26:58 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-01-01 21:26:58 +0000 |
commit | e1d88289ecb729e48f867e5b8f3780596102a23b (patch) | |
tree | d8866955cd2e77a0a5b7963ad94cc0a8b0917cd7 /app/xdm | |
parent | 067a5c9d101a8cde740ef123573e77ab1576ef2a (diff) |
Fix the computed width of the rectangle to clear when no
error message is present and Xft is used.
Diffstat (limited to 'app/xdm')
-rw-r--r-- | app/xdm/greeter/Login.c | 1488 |
1 files changed, 1088 insertions, 400 deletions
diff --git a/app/xdm/greeter/Login.c b/app/xdm/greeter/Login.c index 603bcb365..9b7562c7b 100644 --- a/app/xdm/greeter/Login.c +++ b/app/xdm/greeter/Login.c @@ -1,4 +1,4 @@ -/* $XdotOrg: app/xdm/greeter/Login.c,v 1.5 2006/04/14 02:52:02 alanc Exp $ */ +/* $XdotOrg: app/xdm/greeter/Login.c,v 1.6 2006/06/03 00:05:24 alanc Exp $ */ /* $Xorg: Login.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ */ /* @@ -27,6 +27,34 @@ other dealings in this Software without prior written authorization from The Open Group. */ +/* Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * of the copyright holder. + */ + /* $XFree86: xc/programs/xdm/greeter/Login.c,v 3.17tsi Exp $ */ /* @@ -43,9 +71,8 @@ from The Open Group. # include <X11/Xfuncs.h> # include <stdio.h> -#ifdef XPM +# include <ctype.h> # include <time.h> -#endif /* XPM */ # include "dm.h" # include "dm_error.h" @@ -58,16 +85,32 @@ from The Open Group. #include <X11/Xlib.h> #include <X11/xpm.h> #include <X11/extensions/shape.h> -#include <X11/cursorfont.h> #endif /* XPM */ +#include <X11/cursorfont.h> + #ifdef USE_XINERAMA #include <X11/extensions/Xinerama.h> #endif +#ifndef DEBUG +# define XDM_ASSERT(a) /* do nothing */ +#else +# if defined(__STDC__) && __STDC_VERSION__ - 0 >= 199901L +# define XDM_ASSERT(a) if (!(a)) { \ + Debug("Assertion failed in %s() at file %s line %d\n", \ + __func__, __FILE__, __LINE__); } +# else +# define XDM_ASSERT(a) if (!(a)) { \ + Debug("Assertion failed at file %s line %d\n", __FILE__, __LINE__); } +# endif +#endif + static void RedrawFail (LoginWidget w); static void ResetLogin (LoginWidget w); static void failTimeout (XtPointer client_data, XtIntervalId * id); +static void EraseCursor (LoginWidget w); +static void XorCursor (LoginWidget w); #define offset(field) XtOffsetOf(LoginRec, login.field) #define goffset(field) XtOffsetOf(WidgetRec, core.field) @@ -82,6 +125,7 @@ static XtResource resources[] = { goffset(x), XtRImmediate, (XtPointer) -1}, {XtNy, XtCY, XtRPosition, sizeof (Position), goffset(y), XtRImmediate, (XtPointer) -1}, +#ifndef USE_XFT {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(textpixel), XtRString, XtDefaultForeground}, {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel), @@ -90,13 +134,16 @@ static XtResource resources[] = { offset(greetpixel), XtRString, XtDefaultForeground}, {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel), offset(failpixel), XtRString, XtDefaultForeground}, +#endif -#ifdef XPM +#ifdef DANCING /* added by Caolan McNamara */ {XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int), offset(lastEventTime), XtRImmediate, (XtPointer)0}, /* end (caolan) */ +#endif /* DANCING */ +#ifdef XPM /* added by Ivan Griffin (ivan.griffin@ul.ie) */ {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*), offset(logoFileName), XtRImmediate, (XtPointer)0}, @@ -105,7 +152,7 @@ static XtResource resources[] = { {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int), offset(logoPadding), XtRImmediate, (XtPointer) 5}, /* end (ivan) */ - +#endif /* XPM */ /* added by Amit Margalit */ {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel), @@ -119,16 +166,34 @@ static XtResource resources[] = { {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int), offset(sepwidth), XtRImmediate, (XtPointer) 1}, /* end (amit) */ -#endif /* XPM */ +#ifndef USE_XFT {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), - offset (font), XtRString, "*-new century schoolbook-medium-r-normal-*-180-*"}, + offset (textFont), XtRString, "*-new century schoolbook-medium-r-normal-*-180-*"}, {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"}, {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), offset (greetFont), XtRString, "*-new century schoolbook-bold-i-normal-*-240-*"}, {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), offset (failFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"}, +#else /* USE_XFT */ + {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *), + offset (textFace), XtRString, "Serif-18"}, + {XtNpromptFace, XtCFace, XtRXftFont, sizeof (XftFont *), + offset (promptFace), XtRString, "Serif-18:bold"}, + {XtNgreetFace, XtCFace, XtRXftFont, sizeof (XftFont *), + offset (greetFace), XtRString, "Serif-24:italic"}, + {XtNfailFace, XtCFace, XtRXftFont, sizeof (XftFont *), + offset (failFace), XtRString, "Serif-18:bold"}, + {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), + offset(textcolor), XtRString, XtDefaultForeground}, + {XtNpromptColor, XtCForeground, XtRXftColor, sizeof(XftColor), + offset(promptcolor), XtRString, XtDefaultForeground}, + {XtNgreetColor, XtCForeground, XtRXftColor, sizeof(XftColor), + offset(greetcolor), XtRString, XtDefaultForeground}, + {XtNfailColor, XtCForeground, XtRXftColor, sizeof (XftColor), + offset(failcolor), XtRString, XtDefaultForeground}, +#endif {XtNgreeting, XtCGreeting, XtRString, sizeof (char *), offset(greeting), XtRString, "X Window System"}, {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *), @@ -138,12 +203,16 @@ static XtResource resources[] = { {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *), offset(passwdPrompt), XtRString, "Password: "}, {XtNfail, XtCFail, XtRString, sizeof (char *), - offset(fail), XtRString, + offset(failMsg), XtRString, #if defined(sun) && defined(SVR4) - "Login incorrect or not on system console if root"}, + "Login incorrect or not on system console if root" #else - "Login incorrect"}, + "Login incorrect" #endif + }, + {XtNchangePasswdMessage, XtCChangePasswdMessage, XtRString, + sizeof (char *), offset(passwdChangeMsg), XtRString, + (XtPointer) "Password Change Required" }, {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int), offset(failTimeout), XtRImmediate, (XtPointer) 10}, {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer), @@ -151,11 +220,11 @@ static XtResource resources[] = { {XtNsessionArgument, XtCSessionArgument, XtRString, sizeof (char *), offset(sessionArg), XtRString, (XtPointer) 0 }, {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean), - offset(secure_session), XtRImmediate, False }, + offset(secure_session), XtRImmediate, (XtPointer) False }, {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean), - offset(allow_access), XtRImmediate, False }, + offset(allow_access), XtRImmediate, (XtPointer) False }, {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean), - offset(allow_null_passwd), XtRImmediate, False}, + offset(allow_null_passwd), XtRImmediate, (XtPointer) False}, {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean), offset(allow_root_login), XtRImmediate, (XtPointer) True} }; @@ -163,86 +232,115 @@ static XtResource resources[] = { #undef offset #undef goffset -# define TEXT_X_INC(w) ((w)->login.font->max_bounds.width) -# define TEXT_Y_INC(w) ((w)->login.font->max_bounds.ascent +\ - (w)->login.font->max_bounds.descent) -# define PROMPT_X_INC(w) ((w)->login.promptFont->max_bounds.width) -# define PROMPT_Y_INC(w) ((w)->login.promptFont->max_bounds.ascent +\ - (w)->login.promptFont->max_bounds.descent) -# define GREET_X_INC(w) ((w)->login.greetFont->max_bounds.width) -# define GREET_Y_INC(w) ((w)->login.greetFont->max_bounds.ascent +\ - (w)->login.greetFont->max_bounds.descent) -# define FAIL_X_INC(w) ((w)->login.failFont->max_bounds.width) -# define FAIL_Y_INC(w) ((w)->login.failFont->max_bounds.ascent +\ - (w)->login.failFont->max_bounds.descent) +#ifdef USE_XFT +# define F_MAX_WIDTH(f) ((w)->login.f##Face->max_advance_width) +# define F_ASCENT(f) ((w)->login.f##Face->ascent) +# define F_DESCENT(f) ((w)->login.f##Face->descent) +#else +# define F_MAX_WIDTH(f) ((w)->login.f##Font->max_bounds.width) +# define F_ASCENT(f) ((w)->login.f##Font->max_bounds.ascent) +# define F_DESCENT(f) ((w)->login.f##Font->max_bounds.descent) +#endif + +# define TEXT_X_INC(w) F_MAX_WIDTH(text) +# define TEXT_Y_INC(w) (F_ASCENT(text) + F_DESCENT(text)) + +# define PROMPT_X_INC(w) F_MAX_WIDTH(prompt) +# define PROMPT_Y_INC(w) (F_ASCENT(prompt) + F_DESCENT(prompt)) + +# define GREET_X_INC(w) F_MAX_WIDTH(greet) +# define GREET_Y_INC(w) (F_ASCENT(greet) + F_DESCENT(greet)) + +# define FAIL_X_INC(w) F_MAX_WIDTH(fail) +# define FAIL_Y_INC(w) (F_ASCENT(fail) + F_DESCENT(fail)) # define Y_INC(w) max (TEXT_Y_INC(w), PROMPT_Y_INC(w)) -#ifndef XPM -# define LOGIN_PROMPT_W(w) (XTextWidth (w->login.promptFont,\ - w->login.namePrompt,\ - strlen (w->login.namePrompt))) -#else -# define LOGIN_PROMPT_W(w) (XTextWidth (w->login.promptFont,\ - w->login.namePrompt,\ - strlen (w->login.namePrompt)) + \ - w->login.inframeswidth) -#endif /* XPM */ -#ifndef XPM -# define PASS_PROMPT_W(w) (XTextWidth (w->login.promptFont,\ - w->login.passwdPrompt,\ - strlen (w->login.passwdPrompt))) + +# define PROMPT_TEXT(w,n) ((w)->login.prompts[n].promptText) +# define DEF_PROMPT_TEXT(w,n) ((w)->login.prompts[n].defaultPrompt) +# define VALUE_TEXT(w,n) ((w)->login.prompts[n].valueText) +# define VALUE_TEXT_MAX(w,n) ((w)->login.prompts[n].valueTextMax) +# define VALUE_SHOW_START(w,n) ((w)->login.prompts[n].valueShownStart) +# define VALUE_SHOW_END(w,n) ((w)->login.prompts[n].valueShownEnd) +# define PROMPT_STATE(w,n) ((w)->login.prompts[n].state) +# define PROMPT_CURSOR(w,n) ((w)->login.prompts[n].cursor) + +# define CUR_PROMPT_CURSOR(w) PROMPT_CURSOR(w,w->login.activePrompt) + +# define CUR_PROMPT_TEXT(w, n) (PROMPT_TEXT(w,n) != NULL ? \ + PROMPT_TEXT(w,n) : DEF_PROMPT_TEXT(w,n)) + +#ifdef USE_XFT + +# define TEXT_COLOR(f) (w->login.f##color.pixel) + +# define TEXT_WIDTH(f, m, l) XmuXftTextWidth(XtDisplay (w), \ + w->login.f##Face, (FcChar8 *) m, l) +static int +XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len); + +# define DRAW_STRING(f, x, y, m, l) \ + /* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \ + XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \ + x, y, (FcChar8 *) m, l) + #else -# define PASS_PROMPT_W(w) (XTextWidth (w->login.promptFont,\ - w->login.passwdPrompt,\ - strlen (w->login.passwdPrompt)) + \ - w->login.inframeswidth) -#endif /* XPM */ -# define PROMPT_W(w) (max(LOGIN_PROMPT_W(w), PASS_PROMPT_W(w))) + +# define TEXT_COLOR(f) (w->login.f##pixel) + +# define TEXT_WIDTH(f, m, l) (XTextWidth (w->login.f##Font, m, l)) + +# define DRAW_STRING(f, x, y, m, l) \ + XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l) + +#endif + + +# define STRING_WIDTH(f, s) TEXT_WIDTH (f, s, strlen(s)) + + + +# define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth) + +# define DEF_PROMPT_W(w,n) TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt) +# define CUR_PROMPT_W(w,n) (max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \ + TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0)) + +# define MAX_DEF_PROMPT_W(w) (max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1))) + # define GREETING(w) ((w)->login.secure_session && !(w)->login.allow_access ?\ (w)->login.greeting : (w)->login.unsecure_greet) -# define GREET_X(w) ((int)(w->core.width - XTextWidth (w->login.greetFont,\ - GREETING(w), strlen (GREETING(w)))) / 2) +# define GREET_X(w) ((int)((w->core.width - \ + STRING_WIDTH (greet, GREETING(w))) / 2)) # define GREET_Y(w) (GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0) #ifndef XPM -# define GREET_W(w) (max (XTextWidth (w->login.greetFont,\ - w->login.greeting, strlen (w->login.greeting)), \ - XTextWidth (w->login.greetFont,\ - w->login.unsecure_greet, strlen (w->login.unsecure_greet)))) -#else -# define GREET_W(w) (max (XTextWidth (w->login.greetFont,\ - w->login.greeting, strlen (w->login.greeting)), \ - XTextWidth (w->login.greetFont,\ - w->login.unsecure_greet, strlen (w->login.unsecure_greet)))) + w->login.logoWidth + (2*w->login.logoPadding) -#endif /* XPM */ -# define LOGIN_X(w) (2 * PROMPT_X_INC(w)) -# define LOGIN_Y(w) (GREET_Y(w) + GREET_Y_INC(w) +\ - w->login.greetFont->max_bounds.ascent + Y_INC(w)) -# define LOGIN_W(w) (w->core.width - 6 * TEXT_X_INC(w)) -# define LOGIN_H(w) (3 * Y_INC(w) / 2) -# define LOGIN_TEXT_X(w)(LOGIN_X(w) + PROMPT_W(w)) -# define PASS_X(w) (LOGIN_X(w)) -#ifndef XPM -# define PASS_Y(w) (LOGIN_Y(w) + 8 * Y_INC(w) / 5) +# define GREET_W(w) (max (STRING_WIDTH (greet, w->login.greeting), \ + STRING_WIDTH (greet, w->login.unsecure_greet))) #else -# define PASS_Y(w) (LOGIN_Y(w) + 10 * Y_INC(w) / 5) -#endif /* XPM */ -# define PASS_W(w) (LOGIN_W(w)) -# define PASS_H(w) (LOGIN_H(w)) -# define PASS_TEXT_X(w) (PASS_X(w) + PROMPT_W(w)) -# define FAIL_X(w) ((int)(w->core.width - XTextWidth (w->login.failFont,\ - w->login.fail, strlen (w->login.fail))) / 2) -# define FAIL_Y(w) (PASS_Y(w) + 2 * FAIL_Y_INC (w) +\ - w->login.failFont->max_bounds.ascent) -#ifndef XPM -# define FAIL_W(w) (XTextWidth (w->login.failFont,\ - w->login.fail, strlen (w->login.fail))) -#else -# define FAIL_W(w) (XTextWidth (w->login.failFont,\ - w->login.fail, strlen (w->login.fail))) + w->login.logoWidth + (2*w->login.logoPadding) +# define GREET_W(w) (max (STRING_WIDTH (greet, w->login.greeting), \ + STRING_WIDTH (greet, w->login.unsecure_greet)) \ + + w->login.logoWidth + (2*w->login.logoPadding)) #endif /* XPM */ +# define PROMPT_X(w) (2 * PROMPT_X_INC(w)) +# define PROMPT_Y(w,n) ((GREET_Y(w) + GREET_Y_INC(w) +\ + F_ASCENT(greet) + Y_INC(w)) + \ + (n * PROMPT_SPACE_Y(w))) +# define PROMPT_W(w) (w->core.width - (2 * TEXT_X_INC(w))) +# define PROMPT_H(w) (3 * Y_INC(w) / 2) +# define VALUE_X(w,n) (PROMPT_X(w) + CUR_PROMPT_W(w,n)) +# define PROMPT_SPACE_Y(w) (10 * Y_INC(w) / 5) + +# define ERROR_X(w,m) ((int)(w->core.width - STRING_WIDTH (fail, m)) / 2) +# define FAIL_X(w) ERROR_X(w, w->login.fail) +# define FAIL_Y(w) (PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail)) -# define PAD_X(w) (2 * (LOGIN_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w)))) +# define ERROR_W(w,m) STRING_WIDTH (fail, m) + +# define FAIL_W(w) max(ERROR_W(w, w->login.failMsg), \ + ERROR_W(w, w->login.passwdChangeMsg)) + +# define PAD_X(w) (2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w)))) # define PAD_Y(w) (max (max (Y_INC(w), GREET_Y_INC(w)),\ FAIL_Y_INC(w))) @@ -252,33 +350,87 @@ static inline int max (int a, int b) { return a > b ? a : b; } #endif static void -EraseName (LoginWidget w, int cursor) +realizeValue (LoginWidget w, int cursor, int promptNum, GC gc) { - int x; + loginPromptState state = w->login.prompts[promptNum].state; + char *text = VALUE_TEXT(w, promptNum); + int x, y, height, width, curoff; + + XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); + + x = VALUE_X (w,promptNum); + y = PROMPT_Y (w,promptNum); + + height = PROMPT_H(w); + width = PROMPT_W(w) - x - 3; + + height -= (w->login.inframeswidth * 2); + width -= (w->login.inframeswidth * 2); +#ifdef XPM + width -= (w->login.logoWidth + 2*(w->login.logoPadding)); +#endif + if (cursor > VALUE_SHOW_START(w, promptNum)) + curoff = TEXT_WIDTH (text, text, cursor); + else + curoff = 0; + - x = LOGIN_TEXT_X (w); - if (cursor > 0) - x += XTextWidth (w->login.font, w->login.data.name, cursor); - XDrawString (XtDisplay(w), XtWindow (w), w->login.bgGC, x, LOGIN_Y(w), - w->login.data.name + cursor, strlen (w->login.data.name + cursor)); + if (gc == w->login.bgGC) { + if (curoff < width) { + XFillRectangle (XtDisplay (w), XtWindow (w), gc, + x + curoff, y - TEXT_Y_INC(w), + width - curoff, height); + } + } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO)) { + int textwidth; + int offset = max(cursor, VALUE_SHOW_START(w, promptNum)); + int textlen = strlen (text + offset); + + textwidth = TEXT_WIDTH (text, text + offset, textlen); + + if (textwidth > (width - curoff)) { + /* Recalculate amount of text that can fit in field */ + offset = VALUE_SHOW_START(w, promptNum); + textlen = strlen (text + offset); + + while ((textlen > 0) && (textwidth > width)) + { + if (offset < PROMPT_CURSOR(w, promptNum)) { + offset++; + } + textlen--; + textwidth = TEXT_WIDTH (text, text + offset, textlen); + } + + VALUE_SHOW_START(w, promptNum) = offset; + VALUE_SHOW_END(w, promptNum) = offset + textlen; + + /* Erase old string */ + XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC, + x, y - TEXT_Y_INC(w), width, height); + + DRAW_STRING(text, x, y, text + offset, textlen); + } else { + DRAW_STRING(text, x + curoff, y, text + offset, textlen); + } + } } static void -DrawName (LoginWidget w, int cursor) +EraseValue (LoginWidget w, int cursor, int promptNum) { - int x; - - x = LOGIN_TEXT_X (w); - if (cursor > 0) - x += XTextWidth (w->login.font, w->login.data.name, cursor); - XDrawString (XtDisplay(w), XtWindow (w), w->login.textGC, x, LOGIN_Y(w), - w->login.data.name + cursor, strlen (w->login.data.name + cursor)); + realizeValue(w, cursor, promptNum, w->login.bgGC); +} -#ifdef XPM - /*as good a place as any Caolan begin*/ - w->login.lastEventTime = time(NULL); - /*as good a place as any Caolan end*/ -#endif /* XPM */ +static void +DrawValue (LoginWidget w, int cursor, int promptNum) +{ + realizeValue(w, cursor, promptNum, w->login.textGC); +#ifdef DANCING + /*as good a place as any Caolan begin*/ + w->login.lastEventTime = time(NULL); + /*as good a place as any Caolan end*/ +#endif /* DANCING */ } static void @@ -287,62 +439,103 @@ realizeCursor (LoginWidget w, GC gc) int x, y; int height, width; - switch (w->login.state) { - case GET_NAME: - x = LOGIN_TEXT_X (w); - y = LOGIN_Y (w); - height = w->login.font->max_bounds.ascent + w->login.font->max_bounds.descent; - width = 1; - if (w->login.cursor > 0) - x += XTextWidth (w->login.font, w->login.data.name, w->login.cursor); +#ifdef FORCE_CURSOR_FLASH + static int lastx, lasty; + static struct timeval lastFlash; + struct timeval now, timeout; + int sinceLastFlash; +#endif + + if (w->login.state != PROMPTING) { + return; + } + + x = VALUE_X (w, w->login.activePrompt); + y = PROMPT_Y (w, w->login.activePrompt); + height = (F_ASCENT(text) + F_DESCENT(text)); + width = 1; + + switch (PROMPT_STATE(w, w->login.activePrompt)) { + case LOGIN_PROMPT_NOT_SHOWN: + case LOGIN_TEXT_INFO: + return; + case LOGIN_PROMPT_ECHO_ON: + if (CUR_PROMPT_CURSOR(w) > 0) { + x += TEXT_WIDTH (text, + VALUE_TEXT(w, w->login.activePrompt) + + VALUE_SHOW_START(w, w->login.activePrompt), + PROMPT_CURSOR(w, w->login.activePrompt) + - VALUE_SHOW_START(w, w->login.activePrompt) ); + } break; - case GET_PASSWD: - x = PASS_TEXT_X (w); - y = PASS_Y (w); - height = w->login.font->max_bounds.ascent + w->login.font->max_bounds.descent; - width = 1; + case LOGIN_PROMPT_ECHO_OFF: + /* Nothing special needed */ break; - default: - return; } + XFillRectangle (XtDisplay (w), XtWindow (w), gc, -#ifndef XPM - x, y - w->login.font->max_bounds.ascent, width, height); -#else - x, y+1 - w->login.font->max_bounds.ascent, width, height-1); + x, y+1 - F_ASCENT(text), width, height-1); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-1 , y - w->login.font->max_bounds.ascent); + x-1 , y - F_ASCENT(text)); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+1 , y - w->login.font->max_bounds.ascent); + x+1 , y - F_ASCENT(text)); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-1 , y - w->login.font->max_bounds.ascent+height); + x-1 , y - F_ASCENT(text)+height); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+1 , y - w->login.font->max_bounds.ascent+height); + x+1 , y - F_ASCENT(text)+height); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-2 , y - w->login.font->max_bounds.ascent); + x-2 , y - F_ASCENT(text)); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+2 , y - w->login.font->max_bounds.ascent); + x+2 , y - F_ASCENT(text)); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-2 , y - w->login.font->max_bounds.ascent+height); + x-2 , y - F_ASCENT(text)+height); XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+2 , y - w->login.font->max_bounds.ascent+height); -#endif /* XPM */ + x+2 , y - F_ASCENT(text)+height); + +#ifdef FORCE_CURSOR_FLASH + /* Force cursor to flash briefly to give user feedback */ +#define FLASH_MILLIS 100000 /* 0.10 seconds */ +#define MILLIS_PER_SEC 1000000 + X_GETTIMEOFDAY (&now); + + if ((lastx == x) && (lasty == y)) { + if (lastFlash.tv_sec == 0) + sinceLastFlash = 0; + else if ((lastFlash.tv_sec + 1) == now.tv_sec) + sinceLastFlash = + (now.tv_usec + MILLIS_PER_SEC) - lastFlash.tv_usec; + else if (lastFlash.tv_sec == now.tv_sec) + sinceLastFlash = now.tv_usec - lastFlash.tv_usec; + else + sinceLastFlash = (now.tv_sec - lastFlash.tv_sec) * MILLIS_PER_SEC; + + if (sinceLastFlash < FLASH_MILLIS) { + timeout.tv_sec = 0; + timeout.tv_usec = FLASH_MILLIS - sinceLastFlash; + select(0, NULL, NULL, NULL, &timeout); + } + } else { + lastx = x; lasty = y; + } + X_GETTIMEOFDAY (&lastFlash); +#endif /* FORCE_CURSOR_FLASH */ + XFlush (XtDisplay(w)); } static void EraseFail (LoginWidget w) { - int x = FAIL_X(w); - int y = FAIL_Y(w); - +#ifdef USE_XFT + w->login.failUp = 0; + RedrawFail(w); +#else XSetForeground (XtDisplay (w), w->login.failGC, w->core.background_pixel); - XDrawString (XtDisplay (w), XtWindow (w), w->login.failGC, - x, y, - w->login.fail, strlen (w->login.fail)); + RedrawFail(w); w->login.failUp = 0; XSetForeground (XtDisplay (w), w->login.failGC, - w->login.failpixel); + TEXT_COLOR(fail)); +#endif } static void @@ -370,9 +563,11 @@ static void failTimeout (XtPointer client_data, XtIntervalId * id) LoginWidget w = (LoginWidget)client_data; Debug ("failTimeout\n"); + w->login.interval_id = 0; EraseFail (w); } +_X_INTERNAL void DrawFail (Widget ctx) { @@ -382,14 +577,7 @@ DrawFail (Widget ctx) XorCursor (w); ResetLogin (w); XorCursor (w); - w->login.failUp = 1; - RedrawFail (w); - if (w->login.failTimeout > 0) { - Debug ("failTimeout: %d\n", w->login.failTimeout); - XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w), - w->login.failTimeout * 1000, - failTimeout, (XtPointer) w); - } + ErrorMessage(ctx, w->login.failMsg, True); } static void @@ -397,24 +585,120 @@ RedrawFail (LoginWidget w) { int x = FAIL_X(w); int y = FAIL_Y(w); + int maxw = w->core.width - PAD_X(w); +#ifndef USE_XFT if (w->login.failUp) - XDrawString (XtDisplay (w), XtWindow (w), w->login.failGC, - x, y, - w->login.fail, strlen (w->login.fail)); +#endif + { + Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp); + if (ERROR_W(w, w->login.fail) > maxw) { + /* Too long to fit on one line, break into multiple lines */ + char *tempCopy = strdup(w->login.fail); + if (tempCopy != NULL) { + char *start, *next; + char lastspace; + + y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w)); + + for (start = next = tempCopy; start != NULL ; start = next) { + /* search for longest string broken by whitespace that + will fit on a single line */ + do { + if (next != start) { + *next = lastspace; + } + for (next = next + 1; + (*next != '\0') && !isspace(*next) ; next++) + { + /* this loop intentionally left blank */ + } + if (*next != '\0') { + lastspace = *next; + *next = '\0'; + } else { + next = NULL; + } + } while ((next != NULL) && ERROR_W(w, start) < maxw); + + x = ERROR_X(w, start); +#ifdef USE_XFT + if (w->login.failUp == 0) { + XClearArea(XtDisplay(w), XtWindow(w), x, y, + ERROR_W(w, start), FAIL_Y_INC(w), False); + } else +#endif + DRAW_STRING (fail, x, y, start, strlen(start)); + + if (next != NULL) { + next++; + y += FAIL_Y_INC(w); + } + } + free(tempCopy); + return; + } + /* if strdup failed, fall through to draw all at once, even + though we know it can't all fit */ + LogOutOfMem("RedrawFail"); + } + +#ifdef USE_XFT + if (w->login.failUp == 0) { + XClearArea(XtDisplay(w), XtWindow(w), x, y, + ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False); + } else +#endif + DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail)); + } +} + +_X_INTERNAL +void +ErrorMessage(Widget ctx, const char *message, Bool timeout) +{ + LoginWidget w = (LoginWidget) ctx; + +/* Debug("ErrorMessage: %s\n", message); */ + if (w->login.interval_id != 0) { + XtRemoveTimeOut(w->login.interval_id); + w->login.interval_id = 0; + } + RemoveFail(w); + if (w->login.fail != w->login.failMsg) + free(w->login.fail); + w->login.fail = strdup(message); + if (w->login.fail == NULL) + w->login.fail = (char *) w->login.failMsg; + w->login.failUp = 1; + RedrawFail (w); + if (timeout && (w->login.failTimeout > 0)) { + Debug ("failTimeout: %d\n", w->login.failTimeout); + w->login.interval_id = + XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w), + w->login.failTimeout * 1000, + failTimeout, (XtPointer) w); + } +} + +_X_INTERNAL +void +ShowChangePasswdMessage(Widget ctx) +{ + LoginWidget w = (LoginWidget) ctx; + + ErrorMessage(ctx, w->login.passwdChangeMsg, False); } static void draw_it (LoginWidget w) { -#ifdef XPM - int i,in_frame_x,in_login_y,in_pass_y,in_width,in_height; + int p; + int i; int gr_line_x, gr_line_y, gr_line_w; -#endif /* XPM */ EraseCursor (w); -#ifdef XPM if( (w->login.outframewidth) < 1 ) w->login.outframewidth = 1; for(i=1;i<=(w->login.outframewidth);i++) @@ -430,11 +714,15 @@ draw_it (LoginWidget w) } /* make separator line */ - gr_line_x = w->login.outframewidth + w->login.logoPadding; + gr_line_x = w->login.outframewidth; gr_line_y = GREET_Y(w) + GREET_Y_INC(w); - gr_line_w = w->core.width - 2*(w->login.outframewidth) - - (w->login.logoWidth + 3*(w->login.logoPadding)); - + gr_line_w = w->core.width - 2*(w->login.outframewidth); + +#ifdef XPM + gr_line_x += w->login.logoPadding; + gr_line_w -= w->login.logoWidth + (3 * (w->login.logoPadding)); +#endif /* XPM */ + for(i=1;i<=(w->login.sepwidth);i++) { XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, @@ -444,71 +732,68 @@ draw_it (LoginWidget w) gr_line_x, gr_line_y + 2*(w->login.inframeswidth) -i, gr_line_x+gr_line_w, gr_line_y + 2*(w->login.inframeswidth) -i); } - - in_frame_x = LOGIN_TEXT_X(w) - w->login.inframeswidth - 3; - in_login_y = LOGIN_Y(w) - w->login.inframeswidth - 1 - TEXT_Y_INC(w); - in_pass_y = PASS_Y(w) - w->login.inframeswidth - 1 - TEXT_Y_INC(w); - - in_width = LOGIN_W(w) - PROMPT_W(w) - - (w->login.logoWidth + 2*(w->login.logoPadding)); - in_height = LOGIN_H(w) + w->login.inframeswidth + 2; - for(i=1;i<=(w->login.inframeswidth);i++) + for (p = 0; p < NUM_PROMPTS ; p++) { - /* Make top/left sides */ - XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, - in_frame_x + i-1, in_login_y + i-1, - in_frame_x + in_width-i, in_login_y + i-1); - - XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, - in_frame_x + i-1, in_login_y + i-1, - in_frame_x + i-1, in_login_y + in_height-i); + int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth - 3; + int in_frame_y + = PROMPT_Y(w,p) - w->login.inframeswidth - 1 - TEXT_Y_INC(w); + + int in_width = PROMPT_W(w) - VALUE_X(w,p); + int in_height = PROMPT_H(w) + w->login.inframeswidth + 2; + + GC topLeftGC, botRightGC; - XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, - in_frame_x + in_width-i, in_login_y + i-1, - in_frame_x + in_width-i, in_login_y + in_height-i); - - XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, - in_frame_x + i-1, in_login_y + in_height-i, - in_frame_x + in_width-i, in_login_y + in_height-i); +#ifdef XPM + in_width -= (w->login.logoWidth + 2*(w->login.logoPadding)); +#endif /* XPM */ + + if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) || + (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) { + topLeftGC = w->login.shdGC; + botRightGC = w->login.hiGC; + } else { + topLeftGC = botRightGC = w->login.bgGC; + } - /* Make bottom/right sides */ - XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, - in_frame_x + i-1, in_pass_y + i-1, - in_frame_x + in_width-i, in_pass_y + i-1); + for (i=1; i<=(w->login.inframeswidth); i++) + { + /* Make top/left sides */ + XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC, + in_frame_x + i-1, in_frame_y + i-1, + in_frame_x + in_width-i, in_frame_y + i-1); + + XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC, + in_frame_x + i-1, in_frame_y + i-1, + in_frame_x + i-1, in_frame_y + in_height-i); + + /* Make bottom/right sides */ + XDrawLine(XtDisplay (w), XtWindow (w), botRightGC, + in_frame_x + in_width-i, in_frame_y + i-1, + in_frame_x + in_width-i, in_frame_y + in_height-i); + + XDrawLine(XtDisplay (w), XtWindow (w), botRightGC, + in_frame_x + i-1, in_frame_y + in_height-i, + in_frame_x + in_width-i, in_frame_y + in_height-i); + } + } - XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, - in_frame_x + i-1, in_pass_y + i-1, - in_frame_x + i-1, in_pass_y + in_height-i); + if (GREETING(w)[0]) { + int gx = GREET_X(w); - XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, - in_frame_x + in_width-i, in_pass_y + i-1, - in_frame_x + in_width-i, in_pass_y + in_height-i); - - XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, - in_frame_x + i-1, in_pass_y + in_height-i, - in_frame_x + in_width-i, in_pass_y + in_height-i); +#ifdef XPM + gx -= ((w->login.logoWidth/2) + w->login.logoPadding); +#endif + DRAW_STRING (greet, gx, GREET_Y(w), GREETING(w), strlen (GREETING(w))); + } + for (p = 0; p < NUM_PROMPTS ; p++) { + if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) { + DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p), + CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p))); + DrawValue (w, 0, p); + } } -#endif /* XPM */ - - if (GREETING(w)[0]) - XDrawString (XtDisplay (w), XtWindow (w), w->login.greetGC, -#ifndef XPM - GREET_X(w), GREET_Y(w), -#else - GREET_X(w) - - ((w->login.logoWidth/2) + w->login.logoPadding), - GREET_Y(w), -#endif /* XPM */ - GREETING(w), strlen (GREETING(w))); - XDrawString (XtDisplay (w), XtWindow (w), w->login.promptGC, - LOGIN_X(w), LOGIN_Y(w), - w->login.namePrompt, strlen (w->login.namePrompt)); - XDrawString (XtDisplay (w), XtWindow (w), w->login.promptGC, - PASS_X(w), PASS_Y(w), - w->login.passwdPrompt, strlen (w->login.passwdPrompt)); RedrawFail (w); - DrawName (w, 0); XorCursor (w); /* * The GrabKeyboard here is needed only because of @@ -526,28 +811,194 @@ draw_it (LoginWidget w) } } +/* Returns 0 on success, -1 on failure */ +_X_INTERNAL +int +SetPrompt (Widget ctx, int promptNum, const char *message, + loginPromptState state, Boolean minimumTime) +{ + LoginWidget w = (LoginWidget) ctx; + char *prompt; + int messageLen, e; + const char *stateNames[4] = { + "LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON", + "LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" }; + loginPromptState priorState; + + Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum, + message ? message : "<NULL>", stateNames[state], state); + + XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); + + if (PROMPT_TEXT(w, promptNum) != NULL) { + XtFree(PROMPT_TEXT(w, promptNum)); + PROMPT_TEXT(w, promptNum) = NULL; + } + + priorState = PROMPT_STATE(w, promptNum); + PROMPT_STATE(w, promptNum) = state; + + if (state == LOGIN_PROMPT_NOT_SHOWN) { + return 0; + } + + if (message == NULL) { + message = DEF_PROMPT_TEXT(w, promptNum); + } + + messageLen = strlen(message); + + prompt = XtMalloc(messageLen + 3); + if (prompt == NULL) { + LogOutOfMem ("SetPrompt"); + return -1; + } + + strncpy(prompt, message, messageLen); + + /* Make sure text prompts have at least two spaces at end */ + e = messageLen; + + if (!isspace(message[messageLen - 2])) { + prompt[e] = ' '; + e++; + } + if (!isspace(message[messageLen - 1])) { + prompt[e] = ' '; + e++; + } + prompt[e] = '\0'; + + PROMPT_TEXT(w, promptNum) = prompt; + + if (w->login.state == INITIALIZING) { + return 0; + } + + if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) { + time_t now = time(NULL); + int timeleft = w->login.msgTimeout - now; + + if (timeleft > 0) { + sleep(timeleft); + } + w->login.msgTimeout = 0; + } + + if (state == LOGIN_TEXT_INFO) { + if (minimumTime) { + time_t now = time(NULL); + w->login.msgTimeout = now + w->login.failTimeout; + } + w->login.state = SHOW_MESSAGE; + } else { + w->login.activePrompt = promptNum; + w->login.state = PROMPTING; + } + + PROMPT_CURSOR(w, promptNum) = 0; + XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE); + draw_it(w); + return 0; +} + +_X_INTERNAL +const char * +GetPrompt(Widget ctx, int promptNum) +{ + LoginWidget w = (LoginWidget) ctx; + + XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); + + return CUR_PROMPT_TEXT(w,promptNum); +} + +_X_INTERNAL +int +SetValue(Widget ctx, int promptNum, char *value) +{ + LoginWidget w = (LoginWidget) ctx; + + XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); + + if ((promptNum < 0) || (promptNum > LAST_PROMPT)) + return -1; + + XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL); + + if (VALUE_TEXT(w, promptNum) == NULL) + return -1; + + if (value == NULL) { + bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum)); + } else { + strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum)); + VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0'; + } + + VALUE_SHOW_START(w, promptNum) = 0; + VALUE_SHOW_END(w, promptNum) = 0; + PROMPT_CURSOR(w, promptNum) = 0; + + return 0; +} + +_X_INTERNAL +const char * +GetValue(Widget ctx, int promptNum) +{ + LoginWidget w = (LoginWidget) ctx; + + XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); + + if ((promptNum < 0) || (promptNum > LAST_PROMPT)) + return NULL; + + XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL); + + return VALUE_TEXT(w, promptNum); +} + + +static void +realizeDeleteChar (LoginWidget ctx) +{ + if (ctx->login.state == PROMPTING) { + int promptNum = ctx->login.activePrompt; + int redrawFrom = PROMPT_CURSOR(ctx, promptNum); + + if (PROMPT_CURSOR(ctx,promptNum) < (int)strlen(VALUE_TEXT(ctx,promptNum))) { + if (redrawFrom < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) { + redrawFrom = 0; + EraseValue (ctx, redrawFrom, promptNum); + VALUE_SHOW_START(ctx, ctx->login.activePrompt) + = PROMPT_CURSOR(ctx,promptNum); + } else { + EraseValue (ctx, redrawFrom, promptNum); + } + strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum), + VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1); + DrawValue (ctx, redrawFrom, promptNum); + } + } +} + /*ARGSUSED*/ static void DeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - if (ctx->login.cursor > 0) { - ctx->login.cursor--; - switch (ctx->login.state) { - case GET_NAME: - EraseName (ctx, ctx->login.cursor); - strcpy (ctx->login.data.name + ctx->login.cursor, - ctx->login.data.name + ctx->login.cursor + 1); - DrawName (ctx, ctx->login.cursor); - break; - case GET_PASSWD: - strcpy (ctx->login.data.passwd + ctx->login.cursor, - ctx->login.data.passwd + ctx->login.cursor + 1); - break; - } + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + if (CUR_PROMPT_CURSOR(ctx) > 0) { + CUR_PROMPT_CURSOR(ctx) -= 1; + realizeDeleteChar(ctx); } XorCursor (ctx); } @@ -558,24 +1009,14 @@ DeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_par { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - if (ctx->login.cursor < (int)strlen (ctx->login.data.name)) { - EraseName (ctx, ctx->login.cursor); - strcpy (ctx->login.data.name + ctx->login.cursor, - ctx->login.data.name + ctx->login.cursor + 1); - DrawName (ctx, ctx->login.cursor); - } - break; - case GET_PASSWD: - if (ctx->login.cursor < (int)strlen (ctx->login.data.passwd)) { - strcpy (ctx->login.data.passwd + ctx->login.cursor, - ctx->login.data.passwd + ctx->login.cursor + 1); - } - break; + + if (ctx->login.state != PROMPTING) { + return; } + + XorCursor (ctx); + realizeDeleteChar(ctx); XorCursor (ctx); } @@ -589,10 +1030,21 @@ MoveBackwardChar ( { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - if (ctx->login.cursor > 0) - ctx->login.cursor--; + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + if (CUR_PROMPT_CURSOR(ctx) > 0) + CUR_PROMPT_CURSOR(ctx) -= 1; + if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) { + EraseValue(ctx, 0, ctx->login.activePrompt); + VALUE_SHOW_START(ctx, ctx->login.activePrompt) + = CUR_PROMPT_CURSOR(ctx); + DrawValue(ctx, 0, ctx->login.activePrompt); + } XorCursor (ctx); } @@ -606,17 +1058,21 @@ MoveForwardChar ( { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - if (ctx->login.cursor < (int)strlen(ctx->login.data.name)) - ++ctx->login.cursor; - break; - case GET_PASSWD: - if (ctx->login.cursor < (int)strlen(ctx->login.data.passwd)) - ++ctx->login.cursor; - break; + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + if (CUR_PROMPT_CURSOR(ctx) < + (int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) { + CUR_PROMPT_CURSOR(ctx) += 1; + if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) + < CUR_PROMPT_CURSOR(ctx)) { + EraseValue(ctx, 0, ctx->login.activePrompt); + DrawValue(ctx, 0, ctx->login.activePrompt); + } } XorCursor (ctx); } @@ -631,9 +1087,19 @@ MoveToBegining ( { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - ctx->login.cursor = 0; + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + CUR_PROMPT_CURSOR(ctx) = 0; + if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) { + EraseValue(ctx, 0, ctx->login.activePrompt); + VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0; + DrawValue(ctx, 0, ctx->login.activePrompt); + } XorCursor (ctx); } @@ -647,15 +1113,17 @@ MoveToEnd ( { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - ctx->login.cursor = strlen (ctx->login.data.name); - break; - case GET_PASSWD: - ctx->login.cursor = strlen (ctx->login.data.passwd); - break; + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt)); + if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) { + EraseValue(ctx, 0, ctx->login.activePrompt); + DrawValue(ctx, 0, ctx->login.activePrompt); } XorCursor (ctx); } @@ -670,17 +1138,18 @@ EraseToEndOfLine ( { LoginWidget ctx = (LoginWidget)ctxw; - XorCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - EraseName (ctx, ctx->login.cursor); - bzero (ctx->login.data.name, NAME_LEN); - break; - case GET_PASSWD: - bzero (ctx->login.data.passwd, PASSWORD_LEN); - break; + + if (ctx->login.state != PROMPTING) { + return; } + + XorCursor (ctx); + EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt); + bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) + + CUR_PROMPT_CURSOR(ctx), + VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) - + CUR_PROMPT_CURSOR(ctx)); XorCursor (ctx); } @@ -705,45 +1174,64 @@ FinishField ( Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; + int promptNum = ctx->login.activePrompt; + int nextPrompt; - XorCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - ctx->login.state = GET_PASSWD; - ctx->login.cursor = 0; - break; - case GET_PASSWD: + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + + for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) { + if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) || + (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) { + ctx->login.activePrompt = nextPrompt; + break; + } + } + if (nextPrompt > LAST_PROMPT) { ctx->login.state = DONE; - ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK); - break; + Debug("FinishField #%d: now DONE\n", promptNum); + } else { + Debug("FinishField #%d: %d next\n", promptNum, nextPrompt); } + XorCursor (ctx); } -#ifdef XPM /*ARGSUSED*/ static void TabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; + int promptNum = ctx->login.activePrompt; + int nextPrompt; - XorCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - ctx->login.state = GET_PASSWD; - ctx->login.cursor = 0; - break; - case GET_PASSWD: - ctx->login.state = GET_NAME; - ctx->login.cursor = 0; - break; + + if (ctx->login.state != PROMPTING) { + return; + } + + XorCursor (ctx); + + for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) { + if (nextPrompt > LAST_PROMPT) { + nextPrompt = 0; + } + + if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) || + (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) { + ctx->login.activePrompt = nextPrompt; + break; + } } XorCursor (ctx); } -#endif /* XPM */ /*ARGSUSED*/ static void @@ -777,7 +1265,7 @@ SetSessionArgument ( RemoveFail (ctx); if (ctx->login.sessionArg) XtFree (ctx->login.sessionArg); - ctx->login.sessionArg = 0; + ctx->login.sessionArg = NULL; if (*num_params > 0) { ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1); if (ctx->login.sessionArg) @@ -800,7 +1288,6 @@ RestartSession ( XorCursor (ctx); RemoveFail (ctx); ctx->login.state = DONE; - ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART); XorCursor (ctx); } @@ -818,7 +1305,6 @@ AbortSession ( XorCursor (ctx); RemoveFail (ctx); ctx->login.state = DONE; - ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT); XorCursor (ctx); } @@ -836,7 +1322,6 @@ AbortDisplay ( XorCursor (ctx); RemoveFail (ctx); ctx->login.state = DONE; - ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY); XorCursor (ctx); } @@ -844,11 +1329,16 @@ AbortDisplay ( static void ResetLogin (LoginWidget w) { - EraseName (w, 0); - w->login.cursor = 0; - bzero (w->login.data.name, NAME_LEN); - bzero (w->login.data.passwd, PASSWORD_LEN); - w->login.state = GET_NAME; + int i; + + for (i = 0; i < NUM_PROMPTS ; i++) { + EraseValue(w, 0, i); + bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i)); + VALUE_SHOW_START(w, i) = 0; + PROMPT_CURSOR(w, i) = 0; + } + w->login.state = PROMPTING; + w->login.activePrompt = 0; } static void @@ -891,11 +1381,7 @@ InsertChar ( LoginWidget ctx = (LoginWidget)ctxw; char strbuf[128]; -#ifndef XPM - int len; -#else - int len,pixels; -#endif /* XPM */ + int len, promptNum = ctx->login.activePrompt; KeySym keysym = 0; if (ctx->login.xic) { @@ -909,14 +1395,6 @@ InsertChar ( } strbuf[len] = '\0'; -#ifdef XPM - pixels = 3 + ctx->login.font->max_bounds.width * len + - XTextWidth(ctx->login.font, - ctx->login.data.name, - strlen(ctx->login.data.name)); - /* pixels to be added */ -#endif /* XPM */ - /* * Note: You can override this default key handling * by the settings in the translation table @@ -963,56 +1441,232 @@ InsertChar ( break; } - switch (ctx->login.state) { - case GET_NAME: -#ifndef XPM - if (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1) -#else - if ( - (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1)/* && - (pixels <= LOGIN_W(ctx) - PROMPT_W(ctx))*/ - ) -#endif /* XPM */ - len = NAME_LEN - strlen(ctx->login.data.name) - 2; - case GET_PASSWD: - if (len + (int)strlen(ctx->login.data.passwd) >= PASSWORD_LEN - 1) - len = PASSWORD_LEN - strlen(ctx->login.data.passwd) - 2; + if (ctx->login.state == PROMPTING) { + if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >= + (VALUE_TEXT_MAX(ctx,promptNum) - 1))) { + len = VALUE_TEXT_MAX(ctx,promptNum) - + strlen(VALUE_TEXT(ctx, promptNum)) - 2; + } } -#ifndef XPM - if (len == 0) -#else - if (len == 0 || pixels >= LOGIN_W(ctx) - PROMPT_W(ctx)) -#endif /* XPM */ - return; - XorCursor (ctx); + EraseCursor (ctx); RemoveFail (ctx); - switch (ctx->login.state) { - case GET_NAME: - EraseName (ctx, ctx->login.cursor); - memmove( ctx->login.data.name + ctx->login.cursor + len, - ctx->login.data.name + ctx->login.cursor, - strlen (ctx->login.data.name + ctx->login.cursor) + 1); - memmove( ctx->login.data.name + ctx->login.cursor, strbuf, len); - DrawName (ctx, ctx->login.cursor); - ctx->login.cursor += len; - break; - case GET_PASSWD: - memmove( ctx->login.data.passwd + ctx->login.cursor + len, - ctx->login.data.passwd + ctx->login.cursor, - strlen (ctx->login.data.passwd + ctx->login.cursor) + 1); - memmove( ctx->login.data.passwd + ctx->login.cursor, strbuf, len); - ctx->login.cursor += len; - -#ifdef XPM - /*as good a place as any Caolan begin*/ - ctx->login.lastEventTime = time(NULL); - /*as good a place as any Caolan end*/ -#endif /* XPM */ - break; + if (len != 0) + { + if (ctx->login.state == PROMPTING) { + EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum); + memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len, + VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum), + strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1); + memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum), + strbuf, len); + DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum); + PROMPT_CURSOR(ctx, promptNum) += len; + } } XorCursor (ctx); } + +/**** Copied from xclock.c - original author: Keith Packard ****/ +#ifdef USE_XFT +static XtConvertArgRec xftColorConvertArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap)} +}; + +#define donestr(type, value, tstr) \ + { \ + if (toVal->addr != NULL) { \ + if (toVal->size < sizeof(type)) { \ + toVal->size = sizeof(type); \ + XtDisplayStringConversionWarning(dpy, \ + (char*) fromVal->addr, tstr); \ + return False; \ + } \ + *(type*)(toVal->addr) = (value); \ + } \ + else { \ + static type static_val; \ + static_val = (value); \ + toVal->addr = (XPointer)&static_val; \ + } \ + toVal->size = sizeof(type); \ + return True; \ + } + +static void +XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, + XrmValuePtr args, Cardinal *num_args) +{ + Screen *screen; + Colormap colormap; + XftColor *color; + + if (*num_args != 2) + { + XtAppErrorMsg (app, + "freeXftColor", "wrongParameters", + "XtToolkitError", + "Freeing an XftColor requires screen and colormap arguments", + (String *) NULL, (Cardinal *)NULL); + return; + } + + screen = *((Screen **) args[0].addr); + colormap = *((Colormap *) args[1].addr); + color = (XftColor *) toVal->addr; + XftColorFree (DisplayOfScreen (screen), + DefaultVisual (DisplayOfScreen (screen), + XScreenNumberOfScreen (screen)), + colormap, color); +} + +static Boolean +XmuCvtStringToXftColor(Display *dpy, + XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + char *spec; + XRenderColor renderColor; + XftColor xftColor; + Screen *screen; + Colormap colormap; + + if (*num_args != 2) + { + XtAppErrorMsg (XtDisplayToApplicationContext (dpy), + "cvtStringToXftColor", "wrongParameters", + "XtToolkitError", + "String to render color conversion needs screen and colormap arguments", + (String *) NULL, (Cardinal *)NULL); + return False; + } + + screen = *((Screen **) args[0].addr); + colormap = *((Colormap *) args[1].addr); + + spec = (char *) fromVal->addr; + if (strcasecmp (spec, XtDefaultForeground) == 0) + { + renderColor.red = 0; + renderColor.green = 0; + renderColor.blue = 0; + renderColor.alpha = 0xffff; + } + else if (strcasecmp (spec, XtDefaultBackground) == 0) + { + renderColor.red = 0xffff; + renderColor.green = 0xffff; + renderColor.blue = 0xffff; + renderColor.alpha = 0xffff; + } + else if (!XRenderParseColor (dpy, spec, &renderColor)) + return False; + if (!XftColorAllocValue (dpy, + DefaultVisual (dpy, + XScreenNumberOfScreen (screen)), + colormap, + &renderColor, + &xftColor)) + return False; + + donestr (XftColor, xftColor, XtRXftColor); +} + +static void +XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure, + XrmValuePtr args, Cardinal *num_args) +{ + Screen *screen; + XftFont *font; + + if (*num_args != 1) + { + XtAppErrorMsg (app, + "freeXftFont", "wrongParameters", + "XtToolkitError", + "Freeing an XftFont requires screen argument", + (String *) NULL, (Cardinal *)NULL); + return; + } + + screen = *((Screen **) args[0].addr); + font = *((XftFont **) toVal->addr); + if (font) + XftFontClose (DisplayOfScreen (screen), font); +} + +static Boolean +XmuCvtStringToXftFont(Display *dpy, + XrmValue *args, Cardinal *num_args, + XrmValue *fromVal, XrmValue *toVal, + XtPointer *converter_data) +{ + char *name; + XftFont *font; + Screen *screen; + + if (*num_args != 1) + { + XtAppErrorMsg (XtDisplayToApplicationContext (dpy), + "cvtStringToXftFont", "wrongParameters", + "XtToolkitError", + "String to XftFont conversion needs screen argument", + (String *) NULL, (Cardinal *)NULL); + return False; + } + + screen = *((Screen **) args[0].addr); + name = (char *) fromVal->addr; + + font = XftFontOpenName (dpy, + XScreenNumberOfScreen (screen), + name); + if (font) + { + donestr (XftFont *, font, XtRXftFont); + } + XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont); + return False; +} + +static XtConvertArgRec xftFontConvertArgs[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, +}; + + +static int +XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len) +{ + XGlyphInfo extents; + + XftTextExtents8 (dpy, font, string, len, &extents); + + return extents.xOff; +} + +#endif /* USE_XFT */ + +static void +ClassInitialize(void) +{ +#ifdef USE_XFT + XtSetTypeConverter (XtRString, XtRXftColor, + XmuCvtStringToXftColor, + xftColorConvertArgs, XtNumber(xftColorConvertArgs), + XtCacheByDisplay, XmuFreeXftColor); + XtSetTypeConverter (XtRString, XtRXftFont, + XmuCvtStringToXftFont, + xftFontConvertArgs, XtNumber(xftFontConvertArgs), + XtCacheByDisplay, XmuFreeXftFont); +#endif /* USE_XFT */ +} +/**** End of portion borrowed from xclock ****/ + /* ARGSUSED */ static void Initialize ( Widget greq, @@ -1029,8 +1683,6 @@ static void Initialize ( XineramaScreenInfo *screens; int s_num; #endif - -#ifdef XPM int rv = 0; myXGCV.foreground = w->login.hipixel; @@ -1042,62 +1694,64 @@ static void Initialize ( myXGCV.background = w->core.background_pixel; valuemask = GCForeground | GCBackground; w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV); -#endif /* XPM */ - myXGCV.foreground = w->login.textpixel; + myXGCV.foreground = TEXT_COLOR(text); myXGCV.background = w->core.background_pixel; valuemask = GCForeground | GCBackground; - if (w->login.font) { - myXGCV.font = w->login.font->fid; +#ifndef USE_XFT + if (w->login.textFont) { + myXGCV.font = w->login.textFont->fid; valuemask |= GCFont; } +#endif w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV); myXGCV.foreground = w->core.background_pixel; w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV); - myXGCV.foreground = w->login.textpixel ^ w->core.background_pixel; + myXGCV.foreground = TEXT_COLOR(text) ^ w->core.background_pixel; myXGCV.function = GXxor; xvaluemask = valuemask | GCFunction; w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV); +#ifndef USE_XFT /* * Note that the second argument is a GCid -- QueryFont accepts a GCid and * returns the curently contained font. */ - if (w->login.font == NULL) - w->login.font = XQueryFont (XtDisplay (w), + if (w->login.textFont == NULL) + w->login.textFont = XQueryFont (XtDisplay (w), XGContextFromGC (XDefaultGCOfScreen (XtScreen (w)))); xvaluemask = valuemask; if (w->login.promptFont == NULL) - w->login.promptFont = w->login.font; + w->login.promptFont = w->login.textFont; else xvaluemask |= GCFont; - myXGCV.foreground = w->login.promptpixel; + myXGCV.foreground = TEXT_COLOR(prompt); myXGCV.font = w->login.promptFont->fid; w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV); xvaluemask = valuemask; if (w->login.greetFont == NULL) - w->login.greetFont = w->login.font; + w->login.greetFont = w->login.textFont; else xvaluemask |= GCFont; - myXGCV.foreground = w->login.greetpixel; + myXGCV.foreground = TEXT_COLOR(greet); myXGCV.font = w->login.greetFont->fid; w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV); xvaluemask = valuemask; if (w->login.failFont == NULL) - w->login.failFont = w->login.font; + w->login.failFont = w->login.textFont; else xvaluemask |= GCFont; - - myXGCV.foreground = w->login.failpixel; + myXGCV.foreground = TEXT_COLOR(fail); myXGCV.font = w->login.failFont->fid; w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV); +#endif /* USE_XFT */ #ifdef XPM w->login.logoValid = False; @@ -1155,11 +1809,29 @@ static void Initialize ( SkipXpmLoad: #endif /* XPM */ - bzero (w->login.data.name, NAME_LEN); - bzero (w->login.data.passwd, PASSWORD_LEN); - w->login.state = GET_NAME; - w->login.cursor = 0; + w->login.data.name[0] = '\0'; + w->login.data.passwd[0] = '\0'; + w->login.state = INITIALIZING; + w->login.activePrompt = LOGIN_PROMPT_USERNAME; w->login.failUp = 0; + w->login.fail = (char *) w->login.failMsg; + + /* Set prompt defaults */ + PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) = NULL; + DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) = w->login.namePrompt; + VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) = w->login.data.name; + VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME) = sizeof(w->login.data.name); + VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME) = 0; + + PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) = NULL; + DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) = w->login.passwdPrompt; + VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) = w->login.data.passwd; + VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD) = sizeof(w->login.data.passwd); + VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD) = 0; + + SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False); + SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False); + if (w->core.width == 0) w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w); if (w->core.height == 0) { @@ -1200,6 +1872,8 @@ SkipXpmLoad: XtSetArg (position[0], XtNx, x); XtSetArg (position[1], XtNy, y); XtSetValues (XtParent (w), position, (Cardinal) 2); + + w->login.state = PROMPTING; } @@ -1208,17 +1882,24 @@ static void Realize ( XtValueMask *valueMask, XSetWindowAttributes *attrs) { -#ifdef XPM LoginWidget w = (LoginWidget) gw; Cursor cursor; -#endif /* XPM */ + XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent, *valueMask, attrs ); InitI18N(gw); -#ifdef XPM + +#ifdef USE_XFT + w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w), + DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))), + w->core.colormap); + +#endif + cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr); - XDefineCursor(XtDisplay(gw), XtWindow(gw), cursor); + XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor); +#ifdef XPM /* * Check if Pixmap was valid */ @@ -1271,16 +1952,31 @@ static void Destroy (Widget gw) LoginWidget w = (LoginWidget)gw; bzero (w->login.data.name, NAME_LEN); bzero (w->login.data.passwd, PASSWORD_LEN); + + if (PROMPT_TEXT(w,0) != NULL) + XtFree(PROMPT_TEXT(w,0)); + if (PROMPT_TEXT(w,1) != NULL) + XtFree(PROMPT_TEXT(w,1)); + +#ifdef USE_XFT + if (w->login.draw) { + XftDrawDestroy(w->login.draw); + w->login.draw = NULL; + } +#endif + XtReleaseGC(gw, w->login.textGC); XtReleaseGC(gw, w->login.bgGC); XtReleaseGC(gw, w->login.xorGC); +#ifndef USE_XFT XtReleaseGC(gw, w->login.promptGC); XtReleaseGC(gw, w->login.greetGC); XtReleaseGC(gw, w->login.failGC); -#ifdef XPM +#endif XtReleaseGC(gw, w->login.hiGC); XtReleaseGC(gw, w->login.shdGC); +#ifdef XPM if (True == w->login.logoValid) { if (w->login.logoPixmap != 0) @@ -1318,6 +2014,7 @@ static Boolean SetValues ( return False; } +static char defaultLoginTranslations [] = "Ctrl<Key>H: delete-previous-character() \n" "Ctrl<Key>D: delete-character() \n" @@ -1338,14 +2035,11 @@ char defaultLoginTranslations [] = "<Key>Delete: delete-previous-character() \n" #endif "<Key>Return: finish-field() \n" -#ifndef XPM -"<KeyPress>: insert-char()" -#else "<Key>Tab: tab-field() \n" "<KeyPress>: insert-char()" -#endif /* XPM */ ; +static XtActionsRec loginActionsTable [] = { {"delete-previous-character", DeleteBackwardChar}, {"delete-character", DeleteForwardChar}, @@ -1356,9 +2050,7 @@ XtActionsRec loginActionsTable [] = { {"erase-to-end-of-line", EraseToEndOfLine}, {"erase-line", EraseLine}, {"finish-field", FinishField}, -#ifdef XPM {"tab-field", TabField}, -#endif /* XPM */ {"abort-session", AbortSession}, {"abort-display", AbortDisplay}, {"restart-session", RestartSession}, @@ -1372,7 +2064,7 @@ LoginClassRec loginClassRec = { /* superclass */ &widgetClassRec, /* class_name */ "Login", /* size */ sizeof(LoginRec), - /* class_initialize */ NULL, + /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, @@ -1392,11 +2084,7 @@ LoginClassRec loginClassRec = { /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, -#ifndef XPM - /* set_values_almost */ NULL, -#else /* set_values_almost */ XtInheritSetValuesAlmost, -#endif /* XPM */ /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, |