/* $XdotOrg: app/xdm/greeter/Login.c,v 1.5 2006/04/14 02:52:02 alanc Exp $ */ /* $Xorg: Login.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ */ /* Copyright 1988, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ /* $XFree86: xc/programs/xdm/greeter/Login.c,v 3.17tsi Exp $ */ /* * xdm - display manager daemon * Author: Keith Packard, MIT X Consortium * * Login.c */ # include # include # include # include # include # include #ifdef XPM # include #endif /* XPM */ # include "dm.h" # include "dm_error.h" # include "greet.h" # include "LoginP.h" #ifdef XPM #include #include #include #include #include #include #endif /* XPM */ #ifdef USE_XINERAMA #include #endif static void RedrawFail (LoginWidget w); static void ResetLogin (LoginWidget w); static void failTimeout (XtPointer client_data, XtIntervalId * id); #define offset(field) XtOffsetOf(LoginRec, login.field) #define goffset(field) XtOffsetOf(WidgetRec, core.field) static XtResource resources[] = { {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), goffset(width), XtRImmediate, (XtPointer) 0}, {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), goffset(height), XtRImmediate, (XtPointer) 0}, {XtNx, XtCX, XtRPosition, sizeof (Position), goffset(x), XtRImmediate, (XtPointer) -1}, {XtNy, XtCY, XtRPosition, sizeof (Position), goffset(y), XtRImmediate, (XtPointer) -1}, {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(textpixel), XtRString, XtDefaultForeground}, {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel), offset(promptpixel), XtRString, XtDefaultForeground}, {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel), offset(greetpixel), XtRString, XtDefaultForeground}, {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel), offset(failpixel), XtRString, XtDefaultForeground}, #ifdef XPM /* added by Caolan McNamara */ {XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int), offset(lastEventTime), XtRImmediate, (XtPointer)0}, /* end (caolan) */ /* added by Ivan Griffin (ivan.griffin@ul.ie) */ {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*), offset(logoFileName), XtRImmediate, (XtPointer)0}, {XtNuseShape, XtCUseShape, XtRBoolean, sizeof(Boolean), offset(useShape), XtRImmediate, (XtPointer) True}, {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int), offset(logoPadding), XtRImmediate, (XtPointer) 5}, /* end (ivan) */ /* added by Amit Margalit */ {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel), offset(hipixel), XtRString, XtDefaultForeground}, {XtNshdColor, XtCForeground, XtRPixel, sizeof (Pixel), offset(shdpixel), XtRString, XtDefaultForeground}, {XtNframeWidth, XtCFrameWidth, XtRInt, sizeof(int), offset(outframewidth), XtRImmediate, (XtPointer) 1}, {XtNinnerFramesWidth, XtCFrameWidth, XtRInt, sizeof(int), offset(inframeswidth), XtRImmediate, (XtPointer) 1}, {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int), offset(sepwidth), XtRImmediate, (XtPointer) 1}, /* end (amit) */ #endif /* XPM */ {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), offset (font), 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-*"}, {XtNgreeting, XtCGreeting, XtRString, sizeof (char *), offset(greeting), XtRString, "X Window System"}, {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *), offset(unsecure_greet), XtRString, "This is an unsecure session"}, {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *), offset(namePrompt), XtRString, "Login: "}, {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *), offset(passwdPrompt), XtRString, "Password: "}, {XtNfail, XtCFail, XtRString, sizeof (char *), offset(fail), XtRString, #if defined(sun) && defined(SVR4) "Login incorrect or not on system console if root"}, #else "Login incorrect"}, #endif {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int), offset(failTimeout), XtRImmediate, (XtPointer) 10}, {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer), offset(notify_done), XtRFunction, (XtPointer) 0}, {XtNsessionArgument, XtCSessionArgument, XtRString, sizeof (char *), offset(sessionArg), XtRString, (XtPointer) 0 }, {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean), offset(secure_session), XtRImmediate, False }, {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean), offset(allow_access), XtRImmediate, False }, {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean), offset(allow_null_passwd), XtRImmediate, False}, {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean), offset(allow_root_login), XtRImmediate, (XtPointer) True} }; #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) # 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))) #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 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_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) #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) #endif /* XPM */ # define PAD_X(w) (2 * (LOGIN_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))) #ifndef max static inline int max (int a, int b) { return a > b ? a : b; } #endif static void EraseName (LoginWidget w, int cursor) { 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.bgGC, x, LOGIN_Y(w), w->login.data.name + cursor, strlen (w->login.data.name + cursor)); } static void DrawName (LoginWidget w, int cursor) { 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)); #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 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); 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; 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); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x-1 , y - w->login.font->max_bounds.ascent); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x+1 , y - w->login.font->max_bounds.ascent); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x-1 , y - w->login.font->max_bounds.ascent+height); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x+1 , y - w->login.font->max_bounds.ascent+height); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x-2 , y - w->login.font->max_bounds.ascent); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x+2 , y - w->login.font->max_bounds.ascent); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x-2 , y - w->login.font->max_bounds.ascent+height); XDrawPoint (XtDisplay (w), XtWindow (w), gc, x+2 , y - w->login.font->max_bounds.ascent+height); #endif /* XPM */ } static void EraseFail (LoginWidget w) { int x = FAIL_X(w); int y = FAIL_Y(w); 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)); w->login.failUp = 0; XSetForeground (XtDisplay (w), w->login.failGC, w->login.failpixel); } static void XorCursor (LoginWidget w) { realizeCursor (w, w->login.xorGC); } static void RemoveFail (LoginWidget w) { if (w->login.failUp) EraseFail (w); } static void EraseCursor (LoginWidget w) { realizeCursor (w, w->login.bgGC); } /*ARGSUSED*/ static void failTimeout (XtPointer client_data, XtIntervalId * id) { LoginWidget w = (LoginWidget)client_data; Debug ("failTimeout\n"); EraseFail (w); } void DrawFail (Widget ctx) { LoginWidget w; w = (LoginWidget) 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); } } static void RedrawFail (LoginWidget w) { int x = FAIL_X(w); int y = FAIL_Y(w); if (w->login.failUp) XDrawString (XtDisplay (w), XtWindow (w), w->login.failGC, x, y, w->login.fail, strlen (w->login.fail)); } static void draw_it (LoginWidget w) { #ifdef XPM int i,in_frame_x,in_login_y,in_pass_y,in_width,in_height; 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++) { XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, i-1,i-1,w->core.width-i,i-1); XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, i-1,i-1,i-1,w->core.height-i); XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, w->core.width-i,i-1,w->core.width-i,w->core.height-i); XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, i-1,w->core.height-i,w->core.width-i,w->core.height-i); } /* make separator line */ gr_line_x = w->login.outframewidth + w->login.logoPadding; 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)); for(i=1;i<=(w->login.sepwidth);i++) { XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, gr_line_x, gr_line_y + i-1, gr_line_x+gr_line_w, gr_line_y + i-1); XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, 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++) { /* 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); 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); /* 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); 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); 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); } #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 * a bug in the R3 server -- the keyboard is grabbed on * the root window, and the server won't dispatch events * to the focus window unless the focus window is a ancestor * of the grab window. Bug in server already found and fixed, * compatibility until at least R4. */ if (XGrabKeyboard (XtDisplay (w), XtWindow (w), False, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { XSetInputFocus (XtDisplay (w), XtWindow (w), RevertToPointerRoot, CurrentTime); } } /*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; } } XorCursor (ctx); } /*ARGSUSED*/ static void DeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { 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; } XorCursor (ctx); } /*ARGSUSED*/ static void MoveBackwardChar ( 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--; XorCursor (ctx); } /*ARGSUSED*/ static void MoveForwardChar ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { 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; } XorCursor (ctx); } /*ARGSUSED*/ static void MoveToBegining ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; XorCursor (ctx); RemoveFail (ctx); ctx->login.cursor = 0; XorCursor (ctx); } /*ARGSUSED*/ static void MoveToEnd ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { 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; } XorCursor (ctx); } /*ARGSUSED*/ static void EraseToEndOfLine ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { 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; } XorCursor (ctx); } /*ARGSUSED*/ static void EraseLine ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { MoveToBegining (ctxw, event, params, num_params); EraseToEndOfLine (ctxw, event, params, num_params); } /*ARGSUSED*/ static void FinishField ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; 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 = DONE; ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK); break; } XorCursor (ctx); } #ifdef XPM /*ARGSUSED*/ static void TabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; 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; } XorCursor (ctx); } #endif /* XPM */ /*ARGSUSED*/ static void AllowAccess ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; Arg arglist[1]; Boolean allow; RemoveFail (ctx); XtSetArg (arglist[0], XtNallowAccess, (char *) &allow); XtGetValues ((Widget) ctx, arglist, 1); XtSetArg (arglist[0], XtNallowAccess, !allow); XtSetValues ((Widget) ctx, arglist, 1); } /*ARGSUSED*/ static void SetSessionArgument ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; RemoveFail (ctx); if (ctx->login.sessionArg) XtFree (ctx->login.sessionArg); ctx->login.sessionArg = 0; if (*num_params > 0) { ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1); if (ctx->login.sessionArg) strcpy (ctx->login.sessionArg, params[0]); else LogOutOfMem ("set session argument"); } } /*ARGSUSED*/ static void RestartSession ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; XorCursor (ctx); RemoveFail (ctx); ctx->login.state = DONE; ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART); XorCursor (ctx); } /*ARGSUSED*/ static void AbortSession ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; XorCursor (ctx); RemoveFail (ctx); ctx->login.state = DONE; ctx->login.cursor = 0; (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT); XorCursor (ctx); } /*ARGSUSED*/ static void AbortDisplay ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; 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); } 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; } static void InitI18N(Widget ctxw) { LoginWidget ctx = (LoginWidget)ctxw; XIM xim = (XIM) NULL; char *p; ctx->login.xic = (XIC) NULL; if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL); if (!xim) { LogError("Failed to open input method\n"); return; } ctx->login.xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing|XIMStatusNothing), XNClientWindow, ctx->core.window, XNFocusWindow, ctx->core.window, NULL); if (!ctx->login.xic) { LogError("Failed to create input context\n"); XCloseIM(xim); } return; } /* ARGSUSED */ static void InsertChar ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; char strbuf[128]; #ifndef XPM int len; #else int len,pixels; #endif /* XPM */ KeySym keysym = 0; if (ctx->login.xic) { static Status status; len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf, sizeof (strbuf), &keysym, &status); } else { static XComposeStatus compose_status = {NULL, 0}; len = XLookupString (&event->xkey, strbuf, sizeof (strbuf), &keysym, &compose_status); } 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 * loginActionsTable at the end of this file. */ switch (keysym) { case XK_Return: case XK_KP_Enter: case XK_Linefeed: case XK_Execute: FinishField(ctxw, event, params, num_params); return; case XK_BackSpace: DeleteBackwardChar(ctxw, event, params, num_params); return; case XK_Delete: case XK_KP_Delete: case DXK_Remove: /* Sorry, it's not a telex machine, it's a terminal */ DeleteForwardChar(ctxw, event, params, num_params); return; case XK_Left: case XK_KP_Left: MoveBackwardChar(ctxw, event, params, num_params); return; case XK_Right: case XK_KP_Right: MoveForwardChar(ctxw, event, params, num_params); return; case XK_End: case XK_KP_End: MoveToEnd(ctxw, event, params, num_params); return; case XK_Home: case XK_KP_Home: MoveToBegining(ctxw, event, params, num_params); return; default: if (len == 0) { if (!IsModifierKey(keysym)) /* it's not a modifier */ XBell(XtDisplay(ctxw), 60); return; } else 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; } #ifndef XPM if (len == 0) #else if (len == 0 || pixels >= LOGIN_W(ctx) - PROMPT_W(ctx)) #endif /* XPM */ return; XorCursor (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; } XorCursor (ctx); } /* ARGSUSED */ static void Initialize ( Widget greq, Widget gnew, ArgList args, Cardinal *num_args) { LoginWidget w = (LoginWidget)gnew; XtGCMask valuemask, xvaluemask; XGCValues myXGCV; Arg position[2]; Position x, y; #ifdef USE_XINERAMA XineramaScreenInfo *screens; int s_num; #endif #ifdef XPM int rv = 0; myXGCV.foreground = w->login.hipixel; myXGCV.background = w->core.background_pixel; valuemask = GCForeground | GCBackground; w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV); myXGCV.foreground = w->login.shdpixel; myXGCV.background = w->core.background_pixel; valuemask = GCForeground | GCBackground; w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV); #endif /* XPM */ myXGCV.foreground = w->login.textpixel; myXGCV.background = w->core.background_pixel; valuemask = GCForeground | GCBackground; if (w->login.font) { myXGCV.font = w->login.font->fid; valuemask |= GCFont; } 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.function = GXxor; xvaluemask = valuemask | GCFunction; w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV); /* * 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), XGContextFromGC (XDefaultGCOfScreen (XtScreen (w)))); xvaluemask = valuemask; if (w->login.promptFont == NULL) w->login.promptFont = w->login.font; else xvaluemask |= GCFont; myXGCV.foreground = w->login.promptpixel; 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; else xvaluemask |= GCFont; myXGCV.foreground = w->login.greetpixel; 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; else xvaluemask |= GCFont; myXGCV.foreground = w->login.failpixel; myXGCV.font = w->login.failFont->fid; w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV); #ifdef XPM w->login.logoValid = False; if (NULL != w->login.logoFileName) { XpmAttributes myAttributes = { 0 }; Window tmpWindow = { 0 }; struct stat myBuffer = { 0 }; unsigned int myPixmapDepth = 0; if (0 != stat(w->login.logoFileName, &myBuffer)) { LogError("Unable to stat() pixmap file %s\n", w->login.logoFileName); w->login.logoValid = False; goto SkipXpmLoad; } myAttributes.valuemask |= XpmReturnPixels; myAttributes.valuemask |= XpmReturnExtensions; rv = XpmReadFileToPixmap(XtDisplay(w), /* display */ RootWindowOfScreen(XtScreen(w)), /* window */ w->login.logoFileName, /* XPM filename */ &(w->login.logoPixmap), /* pixmap */ &(w->login.logoMask), /* pixmap mask */ &myAttributes); /* XPM attributes */ if ( rv < 0 ) { LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName, XpmGetErrorString(rv)); goto SkipXpmLoad; } w->login.logoValid = True; XGetGeometry(XtDisplay(w), w->login.logoPixmap, &tmpWindow, &(w->login.logoX), &(w->login.logoY), &(w->login.logoWidth), &(w->login.logoHeight), &(w->login.logoBorderWidth), &myPixmapDepth); } else { w->login.logoX = 0; w->login.logoY = 0; w->login.logoWidth = 0; w->login.logoHeight = 0; w->login.logoBorderWidth = 0; } 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.failUp = 0; if (w->core.width == 0) w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w); if (w->core.height == 0) { int fy = FAIL_Y(w); int pady = PAD_Y(w); #ifndef XPM w->core.height = fy + pady; /* for stupid compilers */ #else /* w->core.height = fy + pady; * for stupid compilers */ w->core.height = max(fy + pady, (w->login.logoHeight + (2*w->login.logoPadding)) + pady); #endif /* XPM */ } #ifdef USE_XINERAMA if ( XineramaIsActive(XtDisplay(w)) && (screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL ) { if ((x = w->core.x) == -1) x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2; if ((y = w->core.y) == -1) y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3; XFree(screens); } else #endif { if ((x = w->core.x) == -1) x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2; if ((y = w->core.y) == -1) y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3; } XtSetArg (position[0], XtNx, x); XtSetArg (position[1], XtNy, y); XtSetValues (XtParent (w), position, (Cardinal) 2); } static void Realize ( Widget gw, 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 cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr); XDefineCursor(XtDisplay(gw), XtWindow(gw), cursor); /* * Check if Pixmap was valid */ if (True == w->login.logoValid) { /* * Create pixmap window */ { unsigned long valueMask = CWBackPixel | CWBackPixmap; XSetWindowAttributes windowAttributes = { 0 }; windowAttributes.background_pixel = w->core.background_pixel; windowAttributes.background_pixmap = None; w->login.logoWindow = XCreateWindow(XtDisplay(w), XtWindow(w), w->core.width - w->login.outframewidth - w->login.logoWidth - w->login.logoPadding, (w->core.height - w->login.logoHeight) /2, w->login.logoWidth, w->login.logoHeight, 0, CopyFromParent, InputOutput, CopyFromParent, valueMask, &windowAttributes); } /* * check if we can use shape extension */ if (True == w->login.useShape) { int foo, bar; if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE) { XShapeCombineMask(XtDisplay(w), w->login.logoWindow, ShapeBounding, w->login.logoX, w->login.logoY, w->login.logoMask, ShapeSet); } } XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow, w->login.logoPixmap); XMapWindow(XtDisplay(w), w->login.logoWindow); } #endif /* XPM */ } static void Destroy (Widget gw) { LoginWidget w = (LoginWidget)gw; bzero (w->login.data.name, NAME_LEN); bzero (w->login.data.passwd, PASSWORD_LEN); XtReleaseGC(gw, w->login.textGC); XtReleaseGC(gw, w->login.bgGC); XtReleaseGC(gw, w->login.xorGC); XtReleaseGC(gw, w->login.promptGC); XtReleaseGC(gw, w->login.greetGC); XtReleaseGC(gw, w->login.failGC); #ifdef XPM XtReleaseGC(gw, w->login.hiGC); XtReleaseGC(gw, w->login.shdGC); if (True == w->login.logoValid) { if (w->login.logoPixmap != 0) XFreePixmap(XtDisplay(w), w->login.logoPixmap); if (w->login.logoMask != 0) XFreePixmap(XtDisplay(w), w->login.logoMask); } #endif /* XPM */ } /* ARGSUSED */ static void Redisplay( Widget gw, XEvent *event, Region region) { draw_it ((LoginWidget) gw); } /*ARGSUSED*/ static Boolean SetValues ( Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args) { LoginWidget currentL, newL; currentL = (LoginWidget) current; newL = (LoginWidget) new; if (GREETING (currentL) != GREETING (newL)) return True; return False; } char defaultLoginTranslations [] = "CtrlH: delete-previous-character() \n" "CtrlD: delete-character() \n" "CtrlB: move-backward-character() \n" "CtrlF: move-forward-character() \n" "CtrlA: move-to-begining() \n" "CtrlE: move-to-end() \n" "CtrlK: erase-to-end-of-line() \n" "CtrlU: erase-line() \n" "CtrlX: erase-line() \n" "CtrlC: restart-session() \n" "Ctrl\\\\: abort-session() \n" ":Ctrlplus: allow-all-access() \n" "BackSpace: delete-previous-character() \n" #ifdef linux "Delete: delete-character() \n" #else "Delete: delete-previous-character() \n" #endif "Return: finish-field() \n" #ifndef XPM ": insert-char()" #else "Tab: tab-field() \n" ": insert-char()" #endif /* XPM */ ; XtActionsRec loginActionsTable [] = { {"delete-previous-character", DeleteBackwardChar}, {"delete-character", DeleteForwardChar}, {"move-backward-character", MoveBackwardChar}, {"move-forward-character", MoveForwardChar}, {"move-to-begining", MoveToBegining}, {"move-to-end", MoveToEnd}, {"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}, {"insert-char", InsertChar}, {"set-session-argument", SetSessionArgument}, {"allow-all-access", AllowAccess}, }; LoginClassRec loginClassRec = { { /* core fields */ /* superclass */ &widgetClassRec, /* class_name */ "Login", /* size */ sizeof(LoginRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ loginActionsTable, /* num_actions */ XtNumber (loginActionsTable), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ NULL, /* 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, /* callback_private */ NULL, /* tm_table */ defaultLoginTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL } }; WidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;