Login.c revision 1cacedb1
1d514b0f3Smrg/* 2d514b0f3Smrg 3d514b0f3SmrgCopyright 1988, 1998 The Open Group 4d514b0f3Smrg 5d514b0f3SmrgPermission to use, copy, modify, distribute, and sell this software and its 6d514b0f3Smrgdocumentation for any purpose is hereby granted without fee, provided that 7d514b0f3Smrgthe above copyright notice appear in all copies and that both that 8d514b0f3Smrgcopyright notice and this permission notice appear in supporting 9d514b0f3Smrgdocumentation. 10d514b0f3Smrg 11d514b0f3SmrgThe above copyright notice and this permission notice shall be included 12d514b0f3Smrgin all copies or substantial portions of the Software. 13d514b0f3Smrg 14d514b0f3SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15d514b0f3SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16d514b0f3SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17d514b0f3SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18d514b0f3SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28/* 29 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 30 * 31 * Permission is hereby granted, free of charge, to any person obtaining a 32 * copy of this software and associated documentation files (the "Software"), 33 * to deal in the Software without restriction, including without limitation 34 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 35 * and/or sell copies of the Software, and to permit persons to whom the 36 * Software is furnished to do so, subject to the following conditions: 37 * 38 * The above copyright notice and this permission notice (including the next 39 * paragraph) shall be included in all copies or substantial portions of the 40 * Software. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 45 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 47 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 48 * DEALINGS IN THE SOFTWARE. 49 */ 50 51 52/* 53 * xdm - display manager daemon 54 * Author: Keith Packard, MIT X Consortium 55 * 56 * Login.c 57 */ 58 59#include <X11/IntrinsicP.h> 60#include <X11/StringDefs.h> 61#include <X11/keysym.h> 62#include <X11/DECkeysym.h> 63#include <X11/Xfuncs.h> 64 65#include <stdio.h> 66#include <ctype.h> 67#include <time.h> 68#include <string.h> 69 70#include "dm.h" 71#include "dm_error.h" 72#include "greet.h" 73#include "LoginP.h" 74 75#ifdef XPM 76# include <sys/stat.h> 77# include <unistd.h> 78# include <X11/Xlib.h> 79# include <X11/xpm.h> 80# include <X11/extensions/shape.h> 81#endif /* XPM */ 82 83#include <X11/cursorfont.h> 84 85#ifdef USE_XINERAMA 86# include <X11/extensions/Xinerama.h> 87#endif 88 89#ifdef USE_XFT 90# include <X11/extensions/Xrender.h> 91#endif 92 93#ifndef DEBUG 94# define XDM_ASSERT(a) /* do nothing */ 95#else 96# if defined(__STDC__) && __STDC_VERSION__ - 0 >= 199901L 97# define XDM_ASSERT(a) if (!(a)) { \ 98 Debug("Assertion failed in %s() at file %s line %d\n", \ 99 __func__, __FILE__, __LINE__); } 100# else 101# define XDM_ASSERT(a) if (!(a)) { \ 102 Debug("Assertion failed at file %s line %d\n", __FILE__, __LINE__); } 103# endif 104#endif 105 106static void RedrawFail (LoginWidget w); 107static void ResetLogin (LoginWidget w); 108static void failTimeout (XtPointer client_data, XtIntervalId * id); 109static void EraseCursor (LoginWidget w); 110static void XorCursor (LoginWidget w); 111 112#define offset(field) XtOffsetOf(LoginRec, login.field) 113#define goffset(field) XtOffsetOf(WidgetRec, core.field) 114 115 116static XtResource resources[] = { 117 {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), 118 goffset(width), XtRImmediate, (XtPointer) 0}, 119 {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), 120 goffset(height), XtRImmediate, (XtPointer) 0}, 121 {XtNx, XtCX, XtRPosition, sizeof (Position), 122 goffset(x), XtRImmediate, (XtPointer) -1}, 123 {XtNy, XtCY, XtRPosition, sizeof (Position), 124 goffset(y), XtRImmediate, (XtPointer) -1}, 125#ifndef USE_XFT 126 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 127 offset(textpixel), XtRString, XtDefaultForeground}, 128 {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel), 129 offset(promptpixel), XtRString, XtDefaultForeground}, 130 {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel), 131 offset(greetpixel), XtRString, XtDefaultForeground}, 132 {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel), 133 offset(failpixel), XtRString, XtDefaultForeground}, 134#endif 135 136#ifdef DANCING 137/* added by Caolan McNamara */ 138 {XtNlastEventTime, XtCLastEventTime, XtRInt , sizeof (int), 139 offset(lastEventTime), XtRImmediate, (XtPointer)0}, 140/* end (caolan) */ 141#endif /* DANCING */ 142 143#ifdef XPM 144/* added by Ivan Griffin (ivan.griffin@ul.ie) */ 145 {XtNlogoFileName, XtCLogoFileName, XtRString, sizeof(char*), 146 offset(logoFileName), XtRImmediate, (XtPointer)0}, 147 {XtNuseShape, XtCUseShape, XtRBoolean, sizeof(Boolean), 148 offset(useShape), XtRImmediate, (XtPointer) True}, 149 {XtNlogoPadding, XtCLogoPadding, XtRInt, sizeof(int), 150 offset(logoPadding), XtRImmediate, (XtPointer) 5}, 151/* end (ivan) */ 152#endif /* XPM */ 153 154/* added by Amit Margalit */ 155 {XtNhiColor, XtCForeground, XtRPixel, sizeof (Pixel), 156 offset(hipixel), XtRString, XtDefaultForeground}, 157 {XtNshdColor, XtCForeground, XtRPixel, sizeof (Pixel), 158 offset(shdpixel), XtRString, XtDefaultForeground}, 159 {XtNinpColor, XtCForeground, XtRPixel, sizeof (Pixel), 160 offset(inppixel), XtRString, XtDefaultBackground}, 161 {XtNframeWidth, XtCFrameWidth, XtRInt, sizeof(int), 162 offset(outframewidth), XtRImmediate, (XtPointer) 1}, 163 {XtNinnerFramesWidth, XtCFrameWidth, XtRInt, sizeof(int), 164 offset(inframeswidth), XtRImmediate, (XtPointer) 1}, 165 {XtNsepWidth, XtCFrameWidth, XtRInt, sizeof(int), 166 offset(sepwidth), XtRImmediate, (XtPointer) 1}, 167/* end (amit) */ 168 169#ifndef USE_XFT 170 {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), 171 offset (textFont), XtRString, "*-new century schoolbook-medium-r-normal-*-180-*"}, 172 {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), 173 offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"}, 174 {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), 175 offset (greetFont), XtRString, "*-new century schoolbook-bold-i-normal-*-240-*"}, 176 {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), 177 offset (failFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"}, 178#else /* USE_XFT */ 179 {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *), 180 offset (textFace), XtRString, "Serif-18"}, 181 {XtNpromptFace, XtCFace, XtRXftFont, sizeof (XftFont *), 182 offset (promptFace), XtRString, "Serif-18:bold"}, 183 {XtNgreetFace, XtCFace, XtRXftFont, sizeof (XftFont *), 184 offset (greetFace), XtRString, "Serif-24:italic"}, 185 {XtNfailFace, XtCFace, XtRXftFont, sizeof (XftFont *), 186 offset (failFace), XtRString, "Serif-18:bold"}, 187 {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor), 188 offset(textcolor), XtRString, XtDefaultForeground}, 189 {XtNpromptColor, XtCForeground, XtRXftColor, sizeof(XftColor), 190 offset(promptcolor), XtRString, XtDefaultForeground}, 191 {XtNgreetColor, XtCForeground, XtRXftColor, sizeof(XftColor), 192 offset(greetcolor), XtRString, XtDefaultForeground}, 193 {XtNfailColor, XtCForeground, XtRXftColor, sizeof (XftColor), 194 offset(failcolor), XtRString, XtDefaultForeground}, 195#endif 196 {XtNgreeting, XtCGreeting, XtRString, sizeof (char *), 197 offset(greeting), XtRString, "X Window System"}, 198 {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *), 199 offset(unsecure_greet), XtRString, "This is an unsecure session"}, 200 {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *), 201 offset(namePrompt), XtRString, "Login: "}, 202 {XtNpasswdPrompt, XtCPasswdPrompt, XtRString, sizeof (char *), 203 offset(passwdPrompt), XtRString, "Password: "}, 204 {XtNfail, XtCFail, XtRString, sizeof (char *), 205 offset(failMsg), XtRString, 206 "Login incorrect or forbidden by policy" 207 }, 208 {XtNchangePasswdMessage, XtCChangePasswdMessage, XtRString, 209 sizeof (char *), offset(passwdChangeMsg), XtRString, 210 (XtPointer) "Password Change Required" }, 211 {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int), 212 offset(failTimeout), XtRImmediate, (XtPointer) 10}, 213 {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer), 214 offset(notify_done), XtRFunction, (XtPointer) 0}, 215 {XtNsessionArgument, XtCSessionArgument, XtRString, sizeof (char *), 216 offset(sessionArg), XtRString, (XtPointer) 0 }, 217 {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean), 218 offset(secure_session), XtRImmediate, (XtPointer) False }, 219 {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean), 220 offset(allow_access), XtRImmediate, (XtPointer) False }, 221 {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean), 222 offset(allow_null_passwd), XtRImmediate, (XtPointer) False}, 223 {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean), 224 offset(allow_root_login), XtRImmediate, (XtPointer) True}, 225 {XtNechoPasswd, XtCEchoPasswd, XtRBoolean, sizeof(Boolean), 226 offset(echo_passwd), XtRImmediate, (XtPointer) False}, 227 {XtNechoPasswdChar, XtCEchoPasswdChar, XtRString, sizeof (char *), 228 offset(echo_passwd_char), XtRString, (XtPointer) "*" } 229}; 230 231#undef offset 232#undef goffset 233 234#ifdef USE_XFT 235# define F_MAX_WIDTH(f) ((w)->login.f##Face->max_advance_width) 236# define F_ASCENT(f) ((w)->login.f##Face->ascent) 237# define F_DESCENT(f) ((w)->login.f##Face->descent) 238#else 239# define F_MAX_WIDTH(f) ((w)->login.f##Font->max_bounds.width) 240# define F_ASCENT(f) ((w)->login.f##Font->max_bounds.ascent) 241# define F_DESCENT(f) ((w)->login.f##Font->max_bounds.descent) 242#endif 243 244#define TEXT_X_INC(w) F_MAX_WIDTH(text) 245#define TEXT_Y_INC(w) (F_ASCENT(text) + F_DESCENT(text)) 246 247#define PROMPT_X_INC(w) F_MAX_WIDTH(prompt) 248#define PROMPT_Y_INC(w) (F_ASCENT(prompt) + F_DESCENT(prompt)) 249 250#define GREET_X_INC(w) F_MAX_WIDTH(greet) 251#define GREET_Y_INC(w) (F_ASCENT(greet) + F_DESCENT(greet)) 252 253#define FAIL_X_INC(w) F_MAX_WIDTH(fail) 254#define FAIL_Y_INC(w) (F_ASCENT(fail) + F_DESCENT(fail)) 255 256#define Y_ASCENT(w) max (F_ASCENT(prompt), F_ASCENT(text)) 257#define Y_DESCENT(w) max (F_DESCENT(prompt), F_DESCENT(text)) 258#define Y_INC(w) (Y_ASCENT(w) + Y_DESCENT(w)) 259 260#define CURSOR_W 5 261 262#define PROMPT_TEXT(w,n) ((w)->login.prompts[n].promptText) 263#define DEF_PROMPT_TEXT(w,n) ((w)->login.prompts[n].defaultPrompt) 264#define VALUE_TEXT(w,n) ((w)->login.prompts[n].valueText) 265#define VALUE_TEXT_MAX(w,n) ((w)->login.prompts[n].valueTextMax) 266#define VALUE_SHOW_START(w,n) ((w)->login.prompts[n].valueShownStart) 267#define VALUE_SHOW_END(w,n) ((w)->login.prompts[n].valueShownEnd) 268#define PROMPT_STATE(w,n) ((w)->login.prompts[n].state) 269#define PROMPT_CURSOR(w,n) ((w)->login.prompts[n].cursor) 270 271#define CUR_PROMPT_CURSOR(w) PROMPT_CURSOR(w,w->login.activePrompt) 272 273#define CUR_PROMPT_TEXT(w, n) (PROMPT_TEXT(w,n) != NULL ? \ 274 PROMPT_TEXT(w,n) : DEF_PROMPT_TEXT(w,n)) 275 276#ifdef USE_XFT 277 278static int 279XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len); 280 281# define TEXT_COLOR(f) (w->login.f##color.pixel) 282# define TEXT_WIDTH(f, m, l) XmuXftTextWidth(XtDisplay (w), \ 283 w->login.f##Face, (FcChar8 *) m, l) 284# define DRAW_STRING(f, x, y, m, l) \ 285 /* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \ 286 XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \ 287 x, y, (FcChar8 *) m, l) 288 289#else 290 291# define TEXT_COLOR(f) (w->login.f##pixel) 292# define TEXT_WIDTH(f, m, l) (XTextWidth (w->login.f##Font, m, l)) 293# define DRAW_STRING(f, x, y, m, l) \ 294 XDrawString (XtDisplay (w), XtWindow (w), w->login.f##GC, x, y, m, l) 295 296#endif 297 298 299#define STRING_WIDTH(f, s) TEXT_WIDTH (f, s, strlen(s)) 300 301/* Padded width of logo image, if compiled with XPM support */ 302#ifdef XPM 303# define LOGO_PAD(w) ((w)->login.logoPadding) 304# define LOGO_W(w) ((w)->login.logoWidth + (LOGO_PAD(w) * 2)) 305#else 306# define LOGO_PAD(w) 0 307# define LOGO_W(w) 0 308#endif 309 310#define TEXT_PROMPT_W(w, m) (STRING_WIDTH(prompt, m) + w->login.inframeswidth) 311 312#define DEF_PROMPT_W(w,n) TEXT_PROMPT_W(w, w->login.prompts[n].defaultPrompt) 313#define MAX_DEF_PROMPT_W(w) (max(DEF_PROMPT_W(w,0), DEF_PROMPT_W(w,1))) 314#define CUR_PROMPT_W(w,n) (max(MAX_DEF_PROMPT_W(w), PROMPT_TEXT(w,n) ? \ 315 TEXT_PROMPT_W(w, PROMPT_TEXT(w,n)) : 0)) 316 317#define GREETING(w) ((w)->login.secure_session && !(w)->login.allow_access ?\ 318 (w)->login.greeting : (w)->login.unsecure_greet) 319#define GREET_X(w) ((int)((w->core.width - LOGO_W(w) + LOGO_PAD(w) - \ 320 STRING_WIDTH (greet, GREETING(w))) / 2)) 321#define GREET_Y(w) (GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0) 322#define GREET_W(w) (max (STRING_WIDTH (greet, w->login.greeting), \ 323 STRING_WIDTH (greet, w->login.unsecure_greet))) 324 325#define SEP_X(w) ((w)->login.outframewidth + LOGO_PAD(w)) 326#define SEP_Y(w) (GREET_Y(w) + GREET_Y_INC(w)) 327#define SEP_W(w) ((w)->core.width - 2*(w->login.outframewidth) - LOGO_W(w) - LOGO_PAD(w)) 328#define SEP_H(w) ((w)->login.inframeswidth * 2) 329 330#define PROMPT_X(w) (2 * PROMPT_X_INC(w)) 331#define PROMPT_Y(w,n) ((SEP_Y(w) + ((n)+1) * GREET_Y_INC(w) + 2 * (w)->login.inframeswidth)) 332#define PROMPT_W(w) (w->core.width - PROMPT_X(w) - 2 * TEXT_X_INC(w) - LOGO_W(w)) 333#define PROMPT_H(w) Y_INC(w) 334 335#define VALUE_HPAD(w,n) (TEXT_X_INC(w)/8) 336#define VALUE_VPAD(w,n) ((Y_INC(w)+3)/4) 337#define VALUE_X(w,n) (PROMPT_X(w) + CUR_PROMPT_W(w,n) + VALUE_HPAD(w,n)) 338#define VALUE_Y(w,n) (PROMPT_Y(w,n)) 339#define VALUE_W(w,n) (PROMPT_W(w) - VALUE_X(w,n) + PROMPT_X(w) - CURSOR_W) 340#define VALUE_H(w,n) Y_INC(w) 341 342#define ERROR_X(w,m) ((int)(w->core.width - LOGO_W(w) - STRING_WIDTH (fail, m)) / 2) 343#define ERROR_W(w,m) (STRING_WIDTH (fail, m) + LOGO_W(w)) 344 345#define FAIL_X(w) ERROR_X(w, w->login.fail) 346#define FAIL_Y(w) (PROMPT_Y(w,1) + 2 * FAIL_Y_INC (w) + F_ASCENT(fail)) 347#define FAIL_W(w) max(ERROR_W(w, w->login.failMsg), \ 348 ERROR_W(w, w->login.passwdChangeMsg)) 349 350#define PAD_X(w) (2 * (PROMPT_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w)) + 4*w->login.outframewidth)) 351#define PAD_Y(w) (max (max (Y_INC(w), GREET_Y_INC(w)),\ 352 FAIL_Y_INC(w))) 353 354#ifndef max 355static inline int max (int a, int b) { return a > b ? a : b; } 356#endif 357 358static void 359realizeValue (LoginWidget w, int cursor, int promptNum, GC gc) 360{ 361 loginPromptState state = PROMPT_STATE(w, promptNum); 362 char *text = VALUE_TEXT(w, promptNum); 363 int x, y, height, width, curoff, offset, textlen; 364 365 XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); 366 367 /* replace all password characters with asterisks */ 368 if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)) 369 { 370 Cardinal length = strlen(text); 371 Cardinal i = 0; 372 373 text = XtMalloc(length + 1); 374 375 if (text == NULL) 376 { 377 LogOutOfMem("realizeValue"); 378 return; 379 } 380 381 while (i < length) 382 { 383 text[i++] = w->login.echo_passwd_char[0]; 384 } 385 386 text[i] = 0; 387 } 388 389 x = VALUE_X (w,promptNum) + VALUE_HPAD(w,promptNum); 390 y = VALUE_Y (w,promptNum); 391 392 height = VALUE_H(w,promptNum); 393 width = VALUE_W(w,promptNum); 394 395 offset = VALUE_SHOW_START(w, promptNum); 396 if (cursor > offset) 397 curoff = TEXT_WIDTH (text, text + offset, cursor - offset); 398 else 399 curoff = 0; 400 401 if (gc == w->login.bgGC) { 402 if (curoff < width) { 403 XFillRectangle (XtDisplay (w), XtWindow (w), gc, 404 x + curoff, y - Y_ASCENT(w), 405 width - curoff, height); 406 } 407 } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) || 408 ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True))) 409 { 410 offset = max(cursor, VALUE_SHOW_START(w, promptNum)); 411 textlen = strlen (text + offset); 412 413 if (TEXT_WIDTH (text, text + offset, textlen) > (width - curoff)) { 414 /* Recalculate amount of text that can fit in field */ 415 offset = VALUE_SHOW_START(w, promptNum); 416 textlen = strlen (text + offset); 417 418 while ((textlen > 0) && 419 (TEXT_WIDTH (text, text + offset, textlen) > width)) 420 { 421 if (offset < PROMPT_CURSOR(w, promptNum)) { 422 offset++; 423 } 424 textlen--; 425 } 426 427 VALUE_SHOW_START(w, promptNum) = offset; 428 VALUE_SHOW_END(w, promptNum) = offset + textlen; 429 430 /* Erase old string */ 431 XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC, 432 x, y - Y_ASCENT(w), width, height); 433 434 DRAW_STRING(text, x, y, text + offset, textlen); 435 } else { 436 DRAW_STRING(text, x + curoff, y, text + offset, textlen); 437 } 438 } 439 /* free memory */ 440 if ((state == LOGIN_PROMPT_ECHO_OFF) && (w->login.echo_passwd == True)) 441 { 442 XtFree(text); 443 } 444} 445 446static void 447EraseValue (LoginWidget w, int cursor, int promptNum) 448{ 449 realizeValue(w, cursor, promptNum, w->login.bgGC); 450} 451 452static void 453DrawValue (LoginWidget w, int cursor, int promptNum) 454{ 455 realizeValue(w, cursor, promptNum, w->login.textGC); 456#ifdef DANCING 457 /*as good a place as any Caolan begin*/ 458 w->login.lastEventTime = time(NULL); 459 /*as good a place as any Caolan end*/ 460#endif /* DANCING */ 461} 462 463static void 464realizeCursor (LoginWidget w, GC gc) 465{ 466 int x, y; 467 int ascent, descent; 468 469 if (w->login.state != PROMPTING) { 470 return; 471 } 472 473 x = VALUE_X (w, w->login.activePrompt) 474 + VALUE_HPAD(w, w->login.activePrompt); 475 y = VALUE_Y (w, w->login.activePrompt); 476 ascent = F_ASCENT(text); 477 descent = F_DESCENT(text); 478 479 switch (PROMPT_STATE(w, w->login.activePrompt)) { 480 case LOGIN_PROMPT_NOT_SHOWN: 481 case LOGIN_TEXT_INFO: 482 return; 483 case LOGIN_PROMPT_ECHO_ON: 484 if (CUR_PROMPT_CURSOR(w) > 0) { 485 x += TEXT_WIDTH (text, 486 VALUE_TEXT(w, w->login.activePrompt) 487 + VALUE_SHOW_START(w, w->login.activePrompt), 488 PROMPT_CURSOR(w, w->login.activePrompt) 489 - VALUE_SHOW_START(w, w->login.activePrompt) ); 490 } 491 break; 492 case LOGIN_PROMPT_ECHO_OFF: 493 if (w->login.echo_passwd == True) { 494 if (w->login.echo_passwd_char[0] != 0) { 495 int len = PROMPT_CURSOR(w, w->login.activePrompt) - 496 VALUE_SHOW_START(w, w->login.activePrompt); 497 498 x += len*TEXT_WIDTH(text, w->login.echo_passwd_char, 1); 499 } else { 500 /* Move cursor one pixel per character to give some feedback 501 without giving away the password length */ 502 if (PROMPT_CURSOR(w, w->login.activePrompt) < 503 VALUE_W(w, w->login.activePrompt)) 504 x += PROMPT_CURSOR(w, w->login.activePrompt); 505 else 506 x += VALUE_W(w, w->login.activePrompt); 507 } 508 } 509 break; 510 } 511 512 x += 2; 513 514 XFillRectangle (XtDisplay (w), XtWindow (w), gc, 515 x, y - ascent + 1, 1, ascent + descent - 2); 516 517 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 518 x-1 , y - ascent); 519 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 520 x+1 , y - ascent); 521 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 522 x-1 , y + descent - 1); 523 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 524 x+1 , y - descent - 1); 525 526 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 527 x-2 , y - ascent); 528 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 529 x+2 , y - ascent); 530 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 531 x-2 , y + descent - 1); 532 XDrawPoint (XtDisplay (w), XtWindow (w), gc, 533 x+2 , y + descent - 1); 534 535 XFlush (XtDisplay(w)); 536} 537 538static void 539EraseFail (LoginWidget w) 540{ 541#ifdef USE_XFT 542 w->login.failUp = 0; 543 RedrawFail(w); 544#else 545 XSetForeground (XtDisplay (w), w->login.failGC, 546 w->core.background_pixel); 547 RedrawFail(w); 548 w->login.failUp = 0; 549 XSetForeground (XtDisplay (w), w->login.failGC, 550 TEXT_COLOR(fail)); 551#endif 552} 553 554static void 555XorCursor (LoginWidget w) 556{ 557 realizeCursor (w, w->login.xorGC); 558} 559 560static void 561RemoveFail (LoginWidget w) 562{ 563 if (w->login.failUp) 564 EraseFail (w); 565} 566 567static void 568EraseCursor (LoginWidget w) 569{ 570 realizeCursor (w, w->login.bgGC); 571} 572 573/*ARGSUSED*/ 574static void failTimeout (XtPointer client_data, XtIntervalId * id) 575{ 576 LoginWidget w = (LoginWidget)client_data; 577 578 Debug ("failTimeout\n"); 579 w->login.interval_id = 0; 580 EraseFail (w); 581} 582 583_X_INTERNAL 584void 585DrawFail (Widget ctx) 586{ 587 LoginWidget w; 588 589 w = (LoginWidget) ctx; 590 XorCursor (w); 591 ResetLogin (w); 592 XorCursor (w); 593 ErrorMessage(ctx, w->login.failMsg, True); 594} 595 596static void 597RedrawFail (LoginWidget w) 598{ 599 int x = FAIL_X(w); 600 int y = FAIL_Y(w); 601 int maxw = w->core.width - PAD_X(w); 602 603#ifndef USE_XFT 604 if (w->login.failUp) 605#endif 606 { 607 Debug("RedrawFail('%s', %d)\n", w->login.fail, w->login.failUp); 608 if (ERROR_W(w, w->login.fail) > maxw) { 609 /* Too long to fit on one line, break into multiple lines */ 610 char *tempCopy = strdup(w->login.fail); 611 if (tempCopy != NULL) { 612 char *start, *next; 613 char lastspace = ' '; 614 615 y = PROMPT_Y(w,LAST_PROMPT) + (2 * PROMPT_Y_INC(w)); 616 617 for (start = next = tempCopy; start != NULL ; start = next) { 618 /* search for longest string broken by whitespace that 619 will fit on a single line */ 620 do { 621 if (next != start) { 622 *next = lastspace; 623 } 624 for (next = next + 1; 625 (*next != '\0') && !isspace(*next) ; next++) 626 { 627 /* this loop intentionally left blank */ 628 } 629 if (*next != '\0') { 630 lastspace = *next; 631 *next = '\0'; 632 } else { 633 next = NULL; 634 } 635 } while ((next != NULL) && ERROR_W(w, start) < maxw); 636 637 x = ERROR_X(w, start); 638#ifdef USE_XFT 639 if (w->login.failUp == 0) { 640 XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail), 641 ERROR_W(w, start), FAIL_Y_INC(w), False); 642 } else 643#endif 644 DRAW_STRING (fail, x, y, start, strlen(start)); 645 646 if (next != NULL) { 647 next++; 648 y += FAIL_Y_INC(w); 649 } 650 } 651 free(tempCopy); 652 return; 653 } 654 /* if strdup failed, fall through to draw all at once, even 655 though we know it can't all fit */ 656 LogOutOfMem("RedrawFail"); 657 } 658 659#ifdef USE_XFT 660 if (w->login.failUp == 0) { 661 XClearArea(XtDisplay(w), XtWindow(w), x, y - F_ASCENT(fail), 662 ERROR_W(w, w->login.fail), FAIL_Y_INC(w), False); 663 } else 664#endif 665 DRAW_STRING (fail, x, y, w->login.fail, strlen (w->login.fail)); 666 } 667} 668 669_X_INTERNAL 670void 671ErrorMessage(Widget ctx, const char *message, Bool timeout) 672{ 673 LoginWidget w = (LoginWidget) ctx; 674 675/* Debug("ErrorMessage: %s\n", message); */ 676 if (w->login.interval_id != 0) { 677 XtRemoveTimeOut(w->login.interval_id); 678 w->login.interval_id = 0; 679 } 680 RemoveFail(w); 681 if (w->login.fail != w->login.failMsg) 682 free(w->login.fail); 683 w->login.fail = strdup(message); 684 if (w->login.fail == NULL) 685 w->login.fail = (char *) w->login.failMsg; 686 w->login.failUp = 1; 687 RedrawFail (w); 688 if (timeout && (w->login.failTimeout > 0)) { 689 Debug ("failTimeout: %d\n", w->login.failTimeout); 690 w->login.interval_id = 691 XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w), 692 w->login.failTimeout * 1000, 693 failTimeout, (XtPointer) w); 694 } 695} 696 697_X_INTERNAL 698void 699ShowChangePasswdMessage(Widget ctx) 700{ 701 LoginWidget w = (LoginWidget) ctx; 702 703 ErrorMessage(ctx, w->login.passwdChangeMsg, False); 704} 705 706static void 707draw_it (LoginWidget w) 708{ 709 int p; 710 int i; 711 int gr_line_x, gr_line_y, gr_line_w; 712 713 EraseCursor (w); 714 715 /* draw window borders */ 716 for(i=1;i<=(w->login.outframewidth);i++) 717 { 718 XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, 719 i-1,i-1,w->core.width-i,i-1); 720 XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, 721 i-1,i-1,i-1,w->core.height-i); 722 XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, 723 w->core.width-i,i-1,w->core.width-i,w->core.height-i); 724 XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, 725 i-1,w->core.height-i,w->core.width-i,w->core.height-i); 726 } 727 728 /* make separator line */ 729 gr_line_x = SEP_X(w); 730 gr_line_y = SEP_Y(w); 731 gr_line_w = SEP_W(w); 732 733 for(i=1;i<=(w->login.sepwidth);i++) 734 { 735 XDrawLine(XtDisplay (w), XtWindow (w), w->login.shdGC, 736 gr_line_x, gr_line_y + i-1, 737 gr_line_x+gr_line_w, gr_line_y + i-1); 738 XDrawLine(XtDisplay (w), XtWindow (w), w->login.hiGC, 739 gr_line_x, gr_line_y + SEP_H(w) -i, 740 gr_line_x+gr_line_w, gr_line_y + SEP_H(w) -i); 741 } 742 743 for (p = 0; p < NUM_PROMPTS ; p++) 744 { 745 int in_frame_x = VALUE_X(w,p) - w->login.inframeswidth; 746 int in_frame_y = VALUE_Y(w,p) - Y_ASCENT(w) - w->login.inframeswidth 747 - VALUE_VPAD(w,p); 748 749 int in_width = VALUE_W(w,p) + CURSOR_W + 2 * w->login.inframeswidth 750 + 2 * VALUE_HPAD(w,p); 751 int in_height = VALUE_H(w,p) + 2 * w->login.inframeswidth 752 + 2 * VALUE_VPAD(w,p); 753 754 GC topLeftGC, botRightGC, inpGC; 755 756 if ((PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_ON) || 757 (PROMPT_STATE(w, p) == LOGIN_PROMPT_ECHO_OFF)) { 758 topLeftGC = w->login.shdGC; 759 botRightGC = w->login.hiGC; 760 inpGC = w->login.inpGC; 761 } else { 762 topLeftGC = botRightGC = inpGC = w->login.bgGC; 763 } 764 765 /* draw borders of editboxes */ 766 for (i=1; i<=(w->login.inframeswidth); i++) 767 { 768 /* Make top/left sides */ 769 XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC, 770 in_frame_x + i-1, in_frame_y + i-1, 771 in_frame_x + in_width-i, in_frame_y + i-1); 772 773 XDrawLine(XtDisplay (w), XtWindow (w), topLeftGC, 774 in_frame_x + i-1, in_frame_y + i-1, 775 in_frame_x + i-1, in_frame_y + in_height-i); 776 777 /* Make bottom/right sides */ 778 XDrawLine(XtDisplay (w), XtWindow (w), botRightGC, 779 in_frame_x + in_width-i, in_frame_y + i-1, 780 in_frame_x + in_width-i, in_frame_y + in_height-i); 781 782 XDrawLine(XtDisplay (w), XtWindow (w), botRightGC, 783 in_frame_x + i-1, in_frame_y + in_height-i, 784 in_frame_x + in_width-i, in_frame_y + in_height-i); 785 } 786 XFillRectangle(XtDisplay (w), XtWindow (w), inpGC, 787 in_frame_x + w->login.inframeswidth, 788 in_frame_y + w->login.inframeswidth, 789 in_width - 2*w->login.inframeswidth, 790 in_height - 2*w->login.inframeswidth); 791 } 792 793 if (GREETING(w)[0]) { 794 DRAW_STRING (greet, GREET_X(w), GREET_Y(w), 795 GREETING(w), strlen (GREETING(w))); 796 } 797 for (p = 0; p < NUM_PROMPTS ; p++) { 798 if (PROMPT_STATE(w, p) != LOGIN_PROMPT_NOT_SHOWN) { 799 DRAW_STRING (prompt, PROMPT_X(w), PROMPT_Y(w,p), 800 CUR_PROMPT_TEXT(w,p), strlen (CUR_PROMPT_TEXT(w,p))); 801 DrawValue (w, 0, p); 802 } 803 } 804 RedrawFail (w); 805 XorCursor (w); 806 XSetInputFocus (XtDisplay (w), XtWindow (w), 807 RevertToPointerRoot, CurrentTime); 808} 809 810/* Returns 0 on success, -1 on failure */ 811_X_INTERNAL 812int 813SetPrompt (Widget ctx, int promptNum, const char *message, 814 loginPromptState state, Boolean minimumTime) 815{ 816 LoginWidget w = (LoginWidget) ctx; 817 char *prompt; 818 int messageLen, e; 819 const char *stateNames[4] = { 820 "LOGIN_PROMPT_NOT_SHOWN", "LOGIN_PROMPT_ECHO_ON", 821 "LOGIN_PROMPT_ECHO_OFF", "LOGIN_TEXT_INFO" }; 822 loginPromptState priorState; 823 824 Debug("SetPrompt(%d, %s, %s(%d))\n", promptNum, 825 message ? message : "<NULL>", stateNames[state], state); 826 827 XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); 828 829 if (PROMPT_TEXT(w, promptNum) != NULL) { 830 XtFree(PROMPT_TEXT(w, promptNum)); 831 PROMPT_TEXT(w, promptNum) = NULL; 832 } 833 834 priorState = PROMPT_STATE(w, promptNum); 835 PROMPT_STATE(w, promptNum) = state; 836 837 if (state == LOGIN_PROMPT_NOT_SHOWN) { 838 return 0; 839 } 840 841 if (message == NULL) { 842 message = DEF_PROMPT_TEXT(w, promptNum); 843 } 844 845 messageLen = strlen(message); 846 847 prompt = XtMalloc(messageLen + 3); 848 if (prompt == NULL) { 849 LogOutOfMem ("SetPrompt"); 850 return -1; 851 } 852 853 strncpy(prompt, message, messageLen); 854 855 /* Make sure text prompts have at least two spaces at end */ 856 e = messageLen; 857 858 if (!isspace(message[messageLen - 2])) { 859 prompt[e] = ' '; 860 e++; 861 } 862 if (!isspace(message[messageLen - 1])) { 863 prompt[e] = ' '; 864 e++; 865 } 866 prompt[e] = '\0'; 867 868 PROMPT_TEXT(w, promptNum) = prompt; 869 870 if (w->login.state == INITIALIZING) { 871 return 0; 872 } 873 874 if ((priorState == LOGIN_TEXT_INFO) && (w->login.msgTimeout != 0)) { 875 time_t now = time(NULL); 876 int timeleft = w->login.msgTimeout - now; 877 878 if (timeleft > 0) { 879 sleep(timeleft); 880 } 881 w->login.msgTimeout = 0; 882 } 883 884 if (state == LOGIN_TEXT_INFO) { 885 if (minimumTime) { 886 time_t now = time(NULL); 887 w->login.msgTimeout = now + w->login.failTimeout; 888 } 889 w->login.state = SHOW_MESSAGE; 890 } else { 891 w->login.activePrompt = promptNum; 892 w->login.state = PROMPTING; 893 } 894 895 PROMPT_CURSOR(w, promptNum) = 0; 896 XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, FALSE); 897 draw_it(w); 898 return 0; 899} 900 901_X_INTERNAL 902const char * 903GetPrompt(Widget ctx, int promptNum) 904{ 905 LoginWidget w = (LoginWidget) ctx; 906 907 XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); 908 909 return CUR_PROMPT_TEXT(w,promptNum); 910} 911 912_X_INTERNAL 913int 914SetValue(Widget ctx, int promptNum, char *value) 915{ 916 LoginWidget w = (LoginWidget) ctx; 917 918 XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); 919 920 if ((promptNum < 0) || (promptNum > LAST_PROMPT)) 921 return -1; 922 923 XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL); 924 925 if (VALUE_TEXT(w, promptNum) == NULL) 926 return -1; 927 928 if (value == NULL) { 929 bzero(VALUE_TEXT(w, promptNum), VALUE_TEXT_MAX(w, promptNum)); 930 } else { 931 strncpy(VALUE_TEXT(w, promptNum), value, VALUE_TEXT_MAX(w, promptNum)); 932 VALUE_TEXT(w, promptNum)[VALUE_TEXT_MAX(w, promptNum)] = '\0'; 933 } 934 935 VALUE_SHOW_START(w, promptNum) = 0; 936 VALUE_SHOW_END(w, promptNum) = 0; 937 PROMPT_CURSOR(w, promptNum) = 0; 938 939 return 0; 940} 941 942_X_INTERNAL 943const char * 944GetValue(Widget ctx, int promptNum) 945{ 946 LoginWidget w = (LoginWidget) ctx; 947 948 XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); 949 950 if ((promptNum < 0) || (promptNum > LAST_PROMPT)) 951 return NULL; 952 953 XDM_ASSERT(VALUE_TEXT(w, promptNum) != NULL); 954 955 return VALUE_TEXT(w, promptNum); 956} 957 958 959static void 960realizeDeleteChar (LoginWidget ctx) 961{ 962 if (ctx->login.state == PROMPTING) { 963 int promptNum = ctx->login.activePrompt; 964 int redrawFrom = PROMPT_CURSOR(ctx, promptNum); 965 966 if (PROMPT_CURSOR(ctx,promptNum) < (int)strlen(VALUE_TEXT(ctx,promptNum))) { 967 if (redrawFrom <= VALUE_SHOW_START(ctx, ctx->login.activePrompt)) { 968 if (redrawFrom > 0) 969 redrawFrom--; 970 EraseValue (ctx, 0, promptNum); 971 VALUE_SHOW_START(ctx, ctx->login.activePrompt) = redrawFrom; 972 } else { 973 EraseValue (ctx, redrawFrom, promptNum); 974 } 975 strcpy(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum), 976 VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + 1); 977 DrawValue (ctx, redrawFrom, promptNum); 978 } 979 } 980} 981 982/*ARGSUSED*/ 983static void 984DeleteBackwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params) 985{ 986 LoginWidget ctx = (LoginWidget)ctxw; 987 988 RemoveFail (ctx); 989 990 if (ctx->login.state != PROMPTING) { 991 return; 992 } 993 994 XorCursor (ctx); 995 if (CUR_PROMPT_CURSOR(ctx) > 0) { 996 CUR_PROMPT_CURSOR(ctx) -= 1; 997 realizeDeleteChar(ctx); 998 } 999 XorCursor (ctx); 1000} 1001 1002/*ARGSUSED*/ 1003static void 1004DeleteForwardChar (Widget ctxw, XEvent *event, String *params, Cardinal *num_params) 1005{ 1006 LoginWidget ctx = (LoginWidget)ctxw; 1007 1008 RemoveFail (ctx); 1009 1010 if (ctx->login.state != PROMPTING) { 1011 return; 1012 } 1013 1014 XorCursor (ctx); 1015 realizeDeleteChar(ctx); 1016 XorCursor (ctx); 1017} 1018 1019/*ARGSUSED*/ 1020static void 1021MoveBackwardChar ( 1022 Widget ctxw, 1023 XEvent *event, 1024 String *params, 1025 Cardinal *num_params) 1026{ 1027 LoginWidget ctx = (LoginWidget)ctxw; 1028 1029 RemoveFail (ctx); 1030 1031 if (ctx->login.state != PROMPTING) { 1032 return; 1033 } 1034 1035 XorCursor (ctx); 1036 if (CUR_PROMPT_CURSOR(ctx) > 0) 1037 CUR_PROMPT_CURSOR(ctx) -= 1; 1038 if (CUR_PROMPT_CURSOR(ctx) < VALUE_SHOW_START(ctx, ctx->login.activePrompt)) { 1039 EraseValue(ctx, 0, ctx->login.activePrompt); 1040 VALUE_SHOW_START(ctx, ctx->login.activePrompt) 1041 = CUR_PROMPT_CURSOR(ctx); 1042 DrawValue(ctx, 0, ctx->login.activePrompt); 1043 } 1044 XorCursor (ctx); 1045} 1046 1047/*ARGSUSED*/ 1048static void 1049MoveForwardChar ( 1050 Widget ctxw, 1051 XEvent *event, 1052 String *params, 1053 Cardinal *num_params) 1054{ 1055 LoginWidget ctx = (LoginWidget)ctxw; 1056 1057 RemoveFail (ctx); 1058 1059 if (ctx->login.state != PROMPTING) { 1060 return; 1061 } 1062 1063 XorCursor (ctx); 1064 if (CUR_PROMPT_CURSOR(ctx) < 1065 (int)strlen(VALUE_TEXT(ctx,ctx->login.activePrompt))) { 1066 CUR_PROMPT_CURSOR(ctx) += 1; 1067 if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) 1068 < CUR_PROMPT_CURSOR(ctx)) { 1069 EraseValue(ctx, 0, ctx->login.activePrompt); 1070 DrawValue(ctx, 0, ctx->login.activePrompt); 1071 } 1072 } 1073 XorCursor (ctx); 1074} 1075 1076/*ARGSUSED*/ 1077static void 1078MoveToBegining ( 1079 Widget ctxw, 1080 XEvent *event, 1081 String *params, 1082 Cardinal *num_params) 1083{ 1084 LoginWidget ctx = (LoginWidget)ctxw; 1085 1086 RemoveFail (ctx); 1087 1088 if (ctx->login.state != PROMPTING) { 1089 return; 1090 } 1091 1092 XorCursor (ctx); 1093 CUR_PROMPT_CURSOR(ctx) = 0; 1094 if (VALUE_SHOW_START(ctx, ctx->login.activePrompt) > 0) { 1095 EraseValue(ctx, 0, ctx->login.activePrompt); 1096 VALUE_SHOW_START(ctx, ctx->login.activePrompt) = 0; 1097 DrawValue(ctx, 0, ctx->login.activePrompt); 1098 } 1099 XorCursor (ctx); 1100} 1101 1102/*ARGSUSED*/ 1103static void 1104MoveToEnd ( 1105 Widget ctxw, 1106 XEvent *event, 1107 String *params, 1108 Cardinal *num_params) 1109{ 1110 LoginWidget ctx = (LoginWidget)ctxw; 1111 1112 RemoveFail (ctx); 1113 1114 if (ctx->login.state != PROMPTING) { 1115 return; 1116 } 1117 1118 XorCursor (ctx); 1119 CUR_PROMPT_CURSOR(ctx) = strlen (VALUE_TEXT(ctx, ctx->login.activePrompt)); 1120 if (VALUE_SHOW_END(ctx, ctx->login.activePrompt) < CUR_PROMPT_CURSOR(ctx)) { 1121 EraseValue(ctx, 0, ctx->login.activePrompt); 1122 DrawValue(ctx, 0, ctx->login.activePrompt); 1123 } 1124 XorCursor (ctx); 1125} 1126 1127/*ARGSUSED*/ 1128static void 1129EraseToEndOfLine ( 1130 Widget ctxw, 1131 XEvent *event, 1132 String *params, 1133 Cardinal *num_params) 1134{ 1135 LoginWidget ctx = (LoginWidget)ctxw; 1136 1137 RemoveFail (ctx); 1138 1139 if (ctx->login.state != PROMPTING) { 1140 return; 1141 } 1142 1143 XorCursor (ctx); 1144 EraseValue (ctx, CUR_PROMPT_CURSOR(ctx), ctx->login.activePrompt); 1145 bzero(VALUE_TEXT(ctx, ctx->login.activePrompt) + 1146 CUR_PROMPT_CURSOR(ctx), 1147 VALUE_TEXT_MAX(ctx, ctx->login.activePrompt) - 1148 CUR_PROMPT_CURSOR(ctx)); 1149 XorCursor (ctx); 1150} 1151 1152/*ARGSUSED*/ 1153static void 1154EraseLine ( 1155 Widget ctxw, 1156 XEvent *event, 1157 String *params, 1158 Cardinal *num_params) 1159{ 1160 MoveToBegining (ctxw, event, params, num_params); 1161 EraseToEndOfLine (ctxw, event, params, num_params); 1162} 1163 1164/*ARGSUSED*/ 1165static void 1166FinishField ( 1167 Widget ctxw, 1168 XEvent *event, 1169 String *params, 1170 Cardinal *num_params) 1171{ 1172 LoginWidget ctx = (LoginWidget)ctxw; 1173 int promptNum = ctx->login.activePrompt; 1174 int nextPrompt; 1175 1176 RemoveFail (ctx); 1177 1178 if (ctx->login.state != PROMPTING) { 1179 return; 1180 } 1181 1182 XorCursor (ctx); 1183 1184 for (nextPrompt = promptNum + 1; nextPrompt <= LAST_PROMPT; nextPrompt++) { 1185 if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) || 1186 (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) { 1187 ctx->login.activePrompt = nextPrompt; 1188 break; 1189 } 1190 } 1191 if (nextPrompt > LAST_PROMPT) { 1192 ctx->login.state = DONE; 1193 (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK); 1194 Debug("FinishField #%d: now DONE\n", promptNum); 1195 } else { 1196 Debug("FinishField #%d: %d next\n", promptNum, nextPrompt); 1197 } 1198 1199 XorCursor (ctx); 1200} 1201 1202/*ARGSUSED*/ 1203static void 1204TabField(Widget ctxw, XEvent *event, String *params, Cardinal *num_params) 1205{ 1206 LoginWidget ctx = (LoginWidget)ctxw; 1207 int promptNum = ctx->login.activePrompt; 1208 int nextPrompt; 1209 1210 RemoveFail (ctx); 1211 1212 if (ctx->login.state != PROMPTING) { 1213 return; 1214 } 1215 1216 XorCursor (ctx); 1217 1218 for (nextPrompt = promptNum + 1; nextPrompt != promptNum; nextPrompt++) { 1219 if (nextPrompt > LAST_PROMPT) { 1220 nextPrompt = 0; 1221 } 1222 1223 if ((PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_ON) || 1224 (PROMPT_STATE(ctx, nextPrompt) == LOGIN_PROMPT_ECHO_OFF)) { 1225 ctx->login.activePrompt = nextPrompt; 1226 break; 1227 } 1228 } 1229 XorCursor (ctx); 1230} 1231 1232/*ARGSUSED*/ 1233static void 1234AllowAccess ( 1235 Widget ctxw, 1236 XEvent *event, 1237 String *params, 1238 Cardinal *num_params) 1239{ 1240 LoginWidget ctx = (LoginWidget)ctxw; 1241 Arg arglist[1]; 1242 Boolean allow; 1243 1244 RemoveFail (ctx); 1245 XtSetArg (arglist[0], XtNallowAccess, (char *) &allow); 1246 XtGetValues ((Widget) ctx, arglist, 1); 1247 XtSetArg (arglist[0], XtNallowAccess, !allow); 1248 XtSetValues ((Widget) ctx, arglist, 1); 1249} 1250 1251/*ARGSUSED*/ 1252static void 1253SetSessionArgument ( 1254 Widget ctxw, 1255 XEvent *event, 1256 String *params, 1257 Cardinal *num_params) 1258{ 1259 LoginWidget ctx = (LoginWidget)ctxw; 1260 1261 RemoveFail (ctx); 1262 if (ctx->login.sessionArg) 1263 XtFree (ctx->login.sessionArg); 1264 ctx->login.sessionArg = NULL; 1265 if (*num_params > 0) { 1266 ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1); 1267 if (ctx->login.sessionArg) 1268 strcpy (ctx->login.sessionArg, params[0]); 1269 else 1270 LogOutOfMem ("set session argument"); 1271 } 1272} 1273 1274/*ARGSUSED*/ 1275static void 1276RestartSession ( 1277 Widget ctxw, 1278 XEvent *event, 1279 String *params, 1280 Cardinal *num_params) 1281{ 1282 LoginWidget ctx = (LoginWidget)ctxw; 1283 1284 XorCursor (ctx); 1285 RemoveFail (ctx); 1286 ctx->login.state = DONE; 1287 (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART); 1288 XorCursor (ctx); 1289} 1290 1291/*ARGSUSED*/ 1292static void 1293AbortSession ( 1294 Widget ctxw, 1295 XEvent *event, 1296 String *params, 1297 Cardinal *num_params) 1298{ 1299 LoginWidget ctx = (LoginWidget)ctxw; 1300 1301 XorCursor (ctx); 1302 RemoveFail (ctx); 1303 ctx->login.state = DONE; 1304 (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT); 1305 XorCursor (ctx); 1306} 1307 1308/*ARGSUSED*/ 1309static void 1310AbortDisplay ( 1311 Widget ctxw, 1312 XEvent *event, 1313 String *params, 1314 Cardinal *num_params) 1315{ 1316 LoginWidget ctx = (LoginWidget)ctxw; 1317 1318 XorCursor (ctx); 1319 RemoveFail (ctx); 1320 ctx->login.state = DONE; 1321 (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY); 1322 XorCursor (ctx); 1323} 1324 1325static void 1326ResetLogin (LoginWidget w) 1327{ 1328 int i; 1329 1330 for (i = 0; i < NUM_PROMPTS ; i++) { 1331 EraseValue(w, 0, i); 1332 bzero(VALUE_TEXT(w, i), VALUE_TEXT_MAX(w, i)); 1333 VALUE_SHOW_START(w, i) = 0; 1334 PROMPT_CURSOR(w, i) = 0; 1335 } 1336 w->login.state = PROMPTING; 1337 w->login.activePrompt = 0; 1338} 1339 1340static void 1341InitI18N(Widget ctxw) 1342{ 1343 LoginWidget ctx = (LoginWidget)ctxw; 1344 XIM xim = (XIM) NULL; 1345 char *p; 1346 1347 ctx->login.xic = (XIC) NULL; 1348 1349 if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) 1350 xim = XOpenIM(XtDisplay(ctx), NULL, NULL, NULL); 1351 1352 if (!xim) { 1353 LogError("Failed to open input method\n"); 1354 return; 1355 } 1356 1357 ctx->login.xic = XCreateIC(xim, 1358 XNInputStyle, (XIMPreeditNothing|XIMStatusNothing), 1359 XNClientWindow, ctx->core.window, 1360 XNFocusWindow, ctx->core.window, NULL); 1361 1362 if (!ctx->login.xic) { 1363 LogError("Failed to create input context\n"); 1364 XCloseIM(xim); 1365 } 1366 return; 1367} 1368 1369/* ARGSUSED */ 1370static void 1371InsertChar ( 1372 Widget ctxw, 1373 XEvent *event, 1374 String *params, 1375 Cardinal *num_params) 1376{ 1377 LoginWidget ctx = (LoginWidget)ctxw; 1378 1379 char strbuf[128]; 1380 int len, promptNum = ctx->login.activePrompt; 1381 KeySym keysym = 0; 1382 1383 if (ctx->login.xic) { 1384 static Status status; 1385 len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf, 1386 sizeof (strbuf), &keysym, &status); 1387 } else { 1388 static XComposeStatus compose_status = {NULL, 0}; 1389 len = XLookupString (&event->xkey, strbuf, sizeof (strbuf), 1390 &keysym, &compose_status); 1391 } 1392 strbuf[len] = '\0'; 1393 1394 /* 1395 * Note: You can override this default key handling 1396 * by the settings in the translation table 1397 * loginActionsTable at the end of this file. 1398 */ 1399 switch (keysym) { 1400 case XK_Return: 1401 case XK_KP_Enter: 1402 case XK_Linefeed: 1403 case XK_Execute: 1404 FinishField(ctxw, event, params, num_params); 1405 return; 1406 case XK_BackSpace: 1407 DeleteBackwardChar(ctxw, event, params, num_params); 1408 return; 1409 case XK_Delete: 1410 case XK_KP_Delete: 1411 case DXK_Remove: 1412 /* Sorry, it's not a telex machine, it's a terminal */ 1413 DeleteForwardChar(ctxw, event, params, num_params); 1414 return; 1415 case XK_Left: 1416 case XK_KP_Left: 1417 MoveBackwardChar(ctxw, event, params, num_params); 1418 return; 1419 case XK_Right: 1420 case XK_KP_Right: 1421 MoveForwardChar(ctxw, event, params, num_params); 1422 return; 1423 case XK_End: 1424 case XK_KP_End: 1425 MoveToEnd(ctxw, event, params, num_params); 1426 return; 1427 case XK_Home: 1428 case XK_KP_Home: 1429 MoveToBegining(ctxw, event, params, num_params); 1430 return; 1431 default: 1432 if (len == 0) { 1433 if (!IsModifierKey(keysym)) /* it's not a modifier */ 1434 XBell(XtDisplay(ctxw), 60); 1435 return; 1436 } else 1437 break; 1438 } 1439 1440 if (ctx->login.state == PROMPTING) { 1441 if ((len + (int)strlen(VALUE_TEXT(ctx, promptNum)) >= 1442 (VALUE_TEXT_MAX(ctx,promptNum) - 1))) { 1443 len = VALUE_TEXT_MAX(ctx,promptNum) - 1444 strlen(VALUE_TEXT(ctx, promptNum)) - 2; 1445 } 1446 } 1447 EraseCursor (ctx); 1448 RemoveFail (ctx); 1449 if (len != 0) 1450 { 1451 if (ctx->login.state == PROMPTING) { 1452 EraseValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum); 1453 memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum) + len, 1454 VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum), 1455 strlen (VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum))+1); 1456 memmove(VALUE_TEXT(ctx, promptNum) + PROMPT_CURSOR(ctx, promptNum), 1457 strbuf, len); 1458 DrawValue (ctx, PROMPT_CURSOR(ctx, promptNum), promptNum); 1459 PROMPT_CURSOR(ctx, promptNum) += len; 1460 } 1461 } 1462 XorCursor (ctx); 1463} 1464 1465 1466/**** Copied from xclock.c - original author: Keith Packard ****/ 1467#ifdef USE_XFT 1468static XtConvertArgRec xftColorConvertArgs[] = { 1469 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 1470 sizeof(Screen *)}, 1471 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 1472 sizeof(Colormap)} 1473}; 1474 1475# define donestr(type, value, tstr) \ 1476 { \ 1477 if (toVal->addr != NULL) { \ 1478 if (toVal->size < sizeof(type)) { \ 1479 toVal->size = sizeof(type); \ 1480 XtDisplayStringConversionWarning(dpy, \ 1481 (char*) fromVal->addr, tstr); \ 1482 return False; \ 1483 } \ 1484 *(type*)(toVal->addr) = (value); \ 1485 } \ 1486 else { \ 1487 static type static_val; \ 1488 static_val = (value); \ 1489 toVal->addr = (XPointer)&static_val; \ 1490 } \ 1491 toVal->size = sizeof(type); \ 1492 return True; \ 1493 } 1494 1495static void 1496XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure, 1497 XrmValuePtr args, Cardinal *num_args) 1498{ 1499 Screen *screen; 1500 Colormap colormap; 1501 XftColor *color; 1502 1503 if (*num_args != 2) 1504 { 1505 XtAppErrorMsg (app, 1506 "freeXftColor", "wrongParameters", 1507 "XtToolkitError", 1508 "Freeing an XftColor requires screen and colormap arguments", 1509 (String *) NULL, (Cardinal *)NULL); 1510 return; 1511 } 1512 1513 screen = *((Screen **) args[0].addr); 1514 colormap = *((Colormap *) args[1].addr); 1515 color = (XftColor *) toVal->addr; 1516 XftColorFree (DisplayOfScreen (screen), 1517 DefaultVisual (DisplayOfScreen (screen), 1518 XScreenNumberOfScreen (screen)), 1519 colormap, color); 1520} 1521 1522static Boolean 1523XmuCvtStringToXftColor(Display *dpy, 1524 XrmValue *args, Cardinal *num_args, 1525 XrmValue *fromVal, XrmValue *toVal, 1526 XtPointer *converter_data) 1527{ 1528 char *spec; 1529 XRenderColor renderColor; 1530 XftColor xftColor; 1531 Screen *screen; 1532 Colormap colormap; 1533 1534 if (*num_args != 2) 1535 { 1536 XtAppErrorMsg (XtDisplayToApplicationContext (dpy), 1537 "cvtStringToXftColor", "wrongParameters", 1538 "XtToolkitError", 1539 "String to render color conversion needs screen and colormap arguments", 1540 (String *) NULL, (Cardinal *)NULL); 1541 return False; 1542 } 1543 1544 screen = *((Screen **) args[0].addr); 1545 colormap = *((Colormap *) args[1].addr); 1546 1547 spec = (char *) fromVal->addr; 1548 if (strcasecmp (spec, XtDefaultForeground) == 0) 1549 { 1550 renderColor.red = 0; 1551 renderColor.green = 0; 1552 renderColor.blue = 0; 1553 renderColor.alpha = 0xffff; 1554 } 1555 else if (strcasecmp (spec, XtDefaultBackground) == 0) 1556 { 1557 renderColor.red = 0xffff; 1558 renderColor.green = 0xffff; 1559 renderColor.blue = 0xffff; 1560 renderColor.alpha = 0xffff; 1561 } 1562 else if (!XRenderParseColor (dpy, spec, &renderColor)) 1563 return False; 1564 if (!XftColorAllocValue (dpy, 1565 DefaultVisual (dpy, 1566 XScreenNumberOfScreen (screen)), 1567 colormap, 1568 &renderColor, 1569 &xftColor)) 1570 return False; 1571 1572 donestr (XftColor, xftColor, XtRXftColor); 1573} 1574 1575static void 1576XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure, 1577 XrmValuePtr args, Cardinal *num_args) 1578{ 1579 Screen *screen; 1580 XftFont *font; 1581 1582 if (*num_args != 1) 1583 { 1584 XtAppErrorMsg (app, 1585 "freeXftFont", "wrongParameters", 1586 "XtToolkitError", 1587 "Freeing an XftFont requires screen argument", 1588 (String *) NULL, (Cardinal *)NULL); 1589 return; 1590 } 1591 1592 screen = *((Screen **) args[0].addr); 1593 font = *((XftFont **) toVal->addr); 1594 if (font) 1595 XftFontClose (DisplayOfScreen (screen), font); 1596} 1597 1598static Boolean 1599XmuCvtStringToXftFont(Display *dpy, 1600 XrmValue *args, Cardinal *num_args, 1601 XrmValue *fromVal, XrmValue *toVal, 1602 XtPointer *converter_data) 1603{ 1604 char *name; 1605 XftFont *font; 1606 Screen *screen; 1607 1608 if (*num_args != 1) 1609 { 1610 XtAppErrorMsg (XtDisplayToApplicationContext (dpy), 1611 "cvtStringToXftFont", "wrongParameters", 1612 "XtToolkitError", 1613 "String to XftFont conversion needs screen argument", 1614 (String *) NULL, (Cardinal *)NULL); 1615 return False; 1616 } 1617 1618 screen = *((Screen **) args[0].addr); 1619 name = (char *) fromVal->addr; 1620 1621 font = XftFontOpenName (dpy, 1622 XScreenNumberOfScreen (screen), 1623 name); 1624 if (font) 1625 { 1626 donestr (XftFont *, font, XtRXftFont); 1627 } 1628 XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont); 1629 return False; 1630} 1631 1632static XtConvertArgRec xftFontConvertArgs[] = { 1633 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), 1634 sizeof(Screen *)}, 1635}; 1636 1637 1638static int 1639XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len) 1640{ 1641 XGlyphInfo extents; 1642 1643 XftTextExtents8 (dpy, font, string, len, &extents); 1644 1645 return extents.xOff; 1646} 1647 1648#endif /* USE_XFT */ 1649 1650static void 1651ClassInitialize(void) 1652{ 1653#ifdef USE_XFT 1654 XtSetTypeConverter (XtRString, XtRXftColor, 1655 XmuCvtStringToXftColor, 1656 xftColorConvertArgs, XtNumber(xftColorConvertArgs), 1657 XtCacheByDisplay, XmuFreeXftColor); 1658 XtSetTypeConverter (XtRString, XtRXftFont, 1659 XmuCvtStringToXftFont, 1660 xftFontConvertArgs, XtNumber(xftFontConvertArgs), 1661 XtCacheByDisplay, XmuFreeXftFont); 1662#endif /* USE_XFT */ 1663} 1664/**** End of portion borrowed from xclock ****/ 1665 1666/* ARGSUSED */ 1667static void Initialize ( 1668 Widget greq, 1669 Widget gnew, 1670 ArgList args, 1671 Cardinal *num_args) 1672{ 1673 LoginWidget w = (LoginWidget)gnew; 1674 XtGCMask valuemask, xvaluemask; 1675 XGCValues myXGCV; 1676 Arg position[2]; 1677 Position x, y; 1678#ifdef USE_XINERAMA 1679 XineramaScreenInfo *screens; 1680 int s_num; 1681#endif 1682 int rv = 0; 1683 1684 myXGCV.foreground = w->login.hipixel; 1685 myXGCV.background = w->core.background_pixel; 1686 valuemask = GCForeground | GCBackground; 1687 w->login.hiGC = XtGetGC(gnew, valuemask, &myXGCV); 1688 1689 myXGCV.foreground = w->login.shdpixel; 1690 myXGCV.background = w->core.background_pixel; 1691 valuemask = GCForeground | GCBackground; 1692 w->login.shdGC = XtGetGC(gnew, valuemask, &myXGCV); 1693 1694 myXGCV.foreground = w->login.inppixel; 1695 myXGCV.background = w->core.background_pixel; 1696 valuemask = GCForeground | GCBackground; 1697 w->login.inpGC = XtGetGC(gnew, valuemask, &myXGCV); 1698 1699 myXGCV.foreground = TEXT_COLOR(text); 1700 myXGCV.background = w->core.background_pixel; 1701 valuemask = GCForeground | GCBackground; 1702#ifndef USE_XFT 1703 if (w->login.textFont) { 1704 myXGCV.font = w->login.textFont->fid; 1705 valuemask |= GCFont; 1706 } 1707#endif 1708 w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV); 1709 myXGCV.foreground = w->login.inppixel; 1710 w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV); 1711 1712 myXGCV.foreground = TEXT_COLOR(text) ^ w->login.inppixel; 1713 myXGCV.function = GXxor; 1714 xvaluemask = valuemask | GCFunction; 1715 w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV); 1716 1717#ifndef USE_XFT 1718 /* 1719 * Note that the second argument is a GCid -- QueryFont accepts a GCid and 1720 * returns the curently contained font. 1721 */ 1722 1723 if (w->login.textFont == NULL) 1724 w->login.textFont = XQueryFont (XtDisplay (w), 1725 XGContextFromGC (XDefaultGCOfScreen (XtScreen (w)))); 1726 1727 xvaluemask = valuemask; 1728 if (w->login.promptFont == NULL) 1729 w->login.promptFont = w->login.textFont; 1730 else 1731 xvaluemask |= GCFont; 1732 1733 myXGCV.foreground = TEXT_COLOR(prompt); 1734 myXGCV.font = w->login.promptFont->fid; 1735 w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV); 1736 1737 xvaluemask = valuemask; 1738 if (w->login.greetFont == NULL) 1739 w->login.greetFont = w->login.textFont; 1740 else 1741 xvaluemask |= GCFont; 1742 1743 myXGCV.foreground = TEXT_COLOR(greet); 1744 myXGCV.font = w->login.greetFont->fid; 1745 w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV); 1746 1747 xvaluemask = valuemask; 1748 if (w->login.failFont == NULL) 1749 w->login.failFont = w->login.textFont; 1750 else 1751 xvaluemask |= GCFont; 1752 myXGCV.foreground = TEXT_COLOR(fail); 1753 myXGCV.font = w->login.failFont->fid; 1754 w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV); 1755#endif /* USE_XFT */ 1756 1757#ifdef XPM 1758 w->login.logoValid = False; 1759 1760 if (NULL != w->login.logoFileName) 1761 { 1762 XpmAttributes myAttributes = { 0 }; 1763 Window tmpWindow = { 0 }; 1764 struct stat myBuffer = { 0 }; 1765 unsigned int myPixmapDepth = 0; 1766 1767 if (0 != stat(w->login.logoFileName, &myBuffer)) 1768 { 1769 LogError("Unable to stat() pixmap file %s\n", 1770 w->login.logoFileName); 1771 w->login.logoValid = False; 1772 goto SkipXpmLoad; 1773 } 1774 1775 myAttributes.valuemask |= XpmReturnPixels; 1776 myAttributes.valuemask |= XpmReturnExtensions; 1777 1778 rv = XpmReadFileToPixmap(XtDisplay(w), /* display */ 1779 RootWindowOfScreen(XtScreen(w)), /* window */ 1780 w->login.logoFileName, /* XPM filename */ 1781 &(w->login.logoPixmap), /* pixmap */ 1782 &(w->login.logoMask), /* pixmap mask */ 1783 &myAttributes); /* XPM attributes */ 1784 1785 if ( rv < 0 ) 1786 { 1787 LogError("Cannot load xpm file %s: %s.\n", w->login.logoFileName, 1788 XpmGetErrorString(rv)); 1789 goto SkipXpmLoad; 1790 } 1791 1792 w->login.logoValid = True; 1793 1794 XGetGeometry(XtDisplay(w), w->login.logoPixmap, 1795 &tmpWindow, 1796 &(w->login.logoX), 1797 &(w->login.logoY), 1798 &(w->login.logoWidth), 1799 &(w->login.logoHeight), 1800 &(w->login.logoBorderWidth), 1801 &myPixmapDepth); 1802 } else { 1803 w->login.logoX = 0; 1804 w->login.logoY = 0; 1805 w->login.logoWidth = 0; 1806 w->login.logoHeight = 0; 1807 w->login.logoBorderWidth = 0; 1808 } 1809 1810 1811SkipXpmLoad: 1812#endif /* XPM */ 1813 w->login.data.name[0] = '\0'; 1814 w->login.data.passwd[0] = '\0'; 1815 w->login.state = INITIALIZING; 1816 w->login.activePrompt = LOGIN_PROMPT_USERNAME; 1817 w->login.failUp = 0; 1818 w->login.fail = (char *) w->login.failMsg; 1819 1820 /* Set prompt defaults */ 1821 PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) = NULL; 1822 DEF_PROMPT_TEXT(w, LOGIN_PROMPT_USERNAME) = w->login.namePrompt; 1823 VALUE_TEXT(w, LOGIN_PROMPT_USERNAME) = w->login.data.name; 1824 VALUE_TEXT_MAX(w, LOGIN_PROMPT_USERNAME) = sizeof(w->login.data.name); 1825 VALUE_SHOW_START(w, LOGIN_PROMPT_USERNAME) = 0; 1826 1827 PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) = NULL; 1828 DEF_PROMPT_TEXT(w, LOGIN_PROMPT_PASSWORD) = w->login.passwdPrompt; 1829 VALUE_TEXT(w, LOGIN_PROMPT_PASSWORD) = w->login.data.passwd; 1830 VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD) = sizeof(w->login.data.passwd); 1831 VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD) = 0; 1832 1833 SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False); 1834 SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False); 1835 1836 if (w->core.width == 0) 1837 w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w); 1838 if (w->core.height == 0) { 1839 int fy = FAIL_Y(w); 1840 int pady = PAD_Y(w); 1841 1842#ifndef XPM 1843 w->core.height = fy + pady; /* for stupid compilers */ 1844#else 1845/* w->core.height = fy + pady; * for stupid compilers */ 1846 1847 w->core.height = max(fy + pady, 1848 (w->login.logoHeight + (2*w->login.logoPadding)) + pady); 1849 1850#endif /* XPM */ 1851 } 1852#ifdef USE_XINERAMA 1853 if ( 1854 XineramaIsActive(XtDisplay(w)) && 1855 (screens = XineramaQueryScreens(XtDisplay(w), &s_num)) != NULL 1856 ) 1857 { 1858 if ((x = w->core.x) == -1) 1859 x = screens[0].x_org + (int)(screens[0].width - w->core.width) / 2; 1860 if ((y = w->core.y) == -1) 1861 y = screens[0].y_org + (int)(screens[0].height - w->core.height) / 3; 1862 1863 XFree(screens); 1864 } 1865 else 1866#endif 1867 { 1868 if ((x = w->core.x) == -1) 1869 x = (int)(XWidthOfScreen (XtScreen (w)) - w->core.width) / 2; 1870 if ((y = w->core.y) == -1) 1871 y = (int)(XHeightOfScreen (XtScreen (w)) - w->core.height) / 3; 1872 } 1873 XtSetArg (position[0], XtNx, x); 1874 XtSetArg (position[1], XtNy, y); 1875 XtSetValues (XtParent (w), position, (Cardinal) 2); 1876 1877 w->login.state = PROMPTING; 1878} 1879 1880 1881static void Realize ( 1882 Widget gw, 1883 XtValueMask *valueMask, 1884 XSetWindowAttributes *attrs) 1885{ 1886 LoginWidget w = (LoginWidget) gw; 1887 Cursor cursor; 1888 1889 XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent, 1890 *valueMask, attrs ); 1891 InitI18N(gw); 1892 1893#ifdef USE_XFT 1894 w->login.draw = XftDrawCreate (XtDisplay (w), XtWindow(w), 1895 DefaultVisual (XtDisplay (w), DefaultScreen(XtDisplay (w))), 1896 w->core.colormap); 1897 1898#endif 1899 1900 cursor = XCreateFontCursor(XtDisplay(gw), XC_left_ptr); 1901 XDefineCursor(XtDisplay(gw), DefaultRootWindow(XtDisplay(gw)), cursor); 1902 1903#ifdef XPM 1904 /* 1905 * Check if Pixmap was valid 1906 */ 1907 if (True == w->login.logoValid) 1908 { 1909 /* 1910 * Create pixmap window 1911 */ 1912 { 1913 XSetWindowAttributes windowAttributes = { 1914 .background_pixel = w->core.background_pixel, 1915 .background_pixmap = None 1916 }; 1917 1918 w->login.logoWindow = XCreateWindow(XtDisplay(w), 1919 XtWindow(w), 1920 w->core.width - w->login.outframewidth - 1921 w->login.logoWidth - w->login.logoPadding, 1922 (w->core.height - w->login.logoHeight) /2, 1923 w->login.logoWidth, w->login.logoHeight, 0, 1924 CopyFromParent, InputOutput, CopyFromParent, 1925 CWBackPixel | CWBackPixmap, &windowAttributes); 1926 } 1927 1928 /* 1929 * check if we can use shape extension 1930 */ 1931 if (True == w->login.useShape) 1932 { 1933 int foo, bar; 1934 1935 if (XShapeQueryExtension(XtDisplay(w), &foo, &bar) == TRUE) 1936 { 1937 XShapeCombineMask(XtDisplay(w), w->login.logoWindow, 1938 ShapeBounding, w->login.logoX, w->login.logoY, 1939 w->login.logoMask, ShapeSet); 1940 } 1941 } 1942 1943 XSetWindowBackgroundPixmap(XtDisplay(w), w->login.logoWindow, 1944 w->login.logoPixmap); 1945 XMapWindow(XtDisplay(w), w->login.logoWindow); 1946 } 1947#endif /* XPM */ 1948} 1949 1950static void Destroy (Widget gw) 1951{ 1952 LoginWidget w = (LoginWidget)gw; 1953 bzero (w->login.data.name, NAME_LEN); 1954 bzero (w->login.data.passwd, PASSWORD_LEN); 1955 1956 if (PROMPT_TEXT(w,0) != NULL) 1957 XtFree(PROMPT_TEXT(w,0)); 1958 if (PROMPT_TEXT(w,1) != NULL) 1959 XtFree(PROMPT_TEXT(w,1)); 1960 1961#ifdef USE_XFT 1962 if (w->login.draw) { 1963 XftDrawDestroy(w->login.draw); 1964 w->login.draw = NULL; 1965 } 1966#endif 1967 1968 XtReleaseGC(gw, w->login.textGC); 1969 XtReleaseGC(gw, w->login.bgGC); 1970 XtReleaseGC(gw, w->login.xorGC); 1971#ifndef USE_XFT 1972 XtReleaseGC(gw, w->login.promptGC); 1973 XtReleaseGC(gw, w->login.greetGC); 1974 XtReleaseGC(gw, w->login.failGC); 1975#endif 1976 XtReleaseGC(gw, w->login.hiGC); 1977 XtReleaseGC(gw, w->login.shdGC); 1978 XtReleaseGC(gw, w->login.inpGC); 1979 1980#ifdef XPM 1981 if (True == w->login.logoValid) 1982 { 1983 if (w->login.logoPixmap != 0) 1984 XFreePixmap(XtDisplay(w), w->login.logoPixmap); 1985 1986 if (w->login.logoMask != 0) 1987 XFreePixmap(XtDisplay(w), w->login.logoMask); 1988 } 1989#endif /* XPM */ 1990} 1991 1992/* ARGSUSED */ 1993static void Redisplay( 1994 Widget gw, 1995 XEvent *event, 1996 Region region) 1997{ 1998 draw_it ((LoginWidget) gw); 1999} 2000 2001/*ARGSUSED*/ 2002static Boolean SetValues ( 2003 Widget current, 2004 Widget request, 2005 Widget new, 2006 ArgList args, 2007 Cardinal *num_args) 2008{ 2009 LoginWidget currentL, newL; 2010 2011 currentL = (LoginWidget) current; 2012 newL = (LoginWidget) new; 2013 if (GREETING (currentL) != GREETING (newL)) 2014 return True; 2015 return False; 2016} 2017 2018static 2019char defaultLoginTranslations [] = 2020"Ctrl<Key>H: delete-previous-character() \n" 2021"Ctrl<Key>D: delete-character() \n" 2022"Ctrl<Key>B: move-backward-character() \n" 2023"Ctrl<Key>F: move-forward-character() \n" 2024"Ctrl<Key>A: move-to-begining() \n" 2025"Ctrl<Key>E: move-to-end() \n" 2026"Ctrl<Key>K: erase-to-end-of-line() \n" 2027"Ctrl<Key>U: erase-line() \n" 2028"Ctrl<Key>X: erase-line() \n" 2029"Ctrl<Key>C: restart-session() \n" 2030"Ctrl<Key>\\\\: abort-session() \n" 2031":Ctrl<Key>plus: allow-all-access() \n" 2032"<Key>BackSpace: delete-previous-character() \n" 2033#ifdef linux 2034"<Key>Delete: delete-character() \n" 2035#else 2036"<Key>Delete: delete-previous-character() \n" 2037#endif 2038"<Key>Return: finish-field() \n" 2039"<Key>Tab: tab-field() \n" 2040"<KeyPress>: insert-char()" 2041; 2042 2043static 2044XtActionsRec loginActionsTable [] = { 2045 {"delete-previous-character", DeleteBackwardChar}, 2046 {"delete-character", DeleteForwardChar}, 2047 {"move-backward-character", MoveBackwardChar}, 2048 {"move-forward-character", MoveForwardChar}, 2049 {"move-to-begining", MoveToBegining}, 2050 {"move-to-end", MoveToEnd}, 2051 {"erase-to-end-of-line", EraseToEndOfLine}, 2052 {"erase-line", EraseLine}, 2053 {"finish-field", FinishField}, 2054 {"tab-field", TabField}, 2055 {"abort-session", AbortSession}, 2056 {"abort-display", AbortDisplay}, 2057 {"restart-session", RestartSession}, 2058 {"insert-char", InsertChar}, 2059 {"set-session-argument", SetSessionArgument}, 2060 {"allow-all-access", AllowAccess}, 2061}; 2062 2063LoginClassRec loginClassRec = { 2064 { /* core fields */ 2065 /* superclass */ &widgetClassRec, 2066 /* class_name */ "Login", 2067 /* size */ sizeof(LoginRec), 2068 /* class_initialize */ ClassInitialize, 2069 /* class_part_initialize */ NULL, 2070 /* class_inited */ FALSE, 2071 /* initialize */ Initialize, 2072 /* initialize_hook */ NULL, 2073 /* realize */ Realize, 2074 /* actions */ loginActionsTable, 2075 /* num_actions */ XtNumber (loginActionsTable), 2076 /* resources */ resources, 2077 /* num_resources */ XtNumber(resources), 2078 /* xrm_class */ NULLQUARK, 2079 /* compress_motion */ TRUE, 2080 /* compress_exposure */ TRUE, 2081 /* compress_enterleave */ TRUE, 2082 /* visible_interest */ FALSE, 2083 /* destroy */ Destroy, 2084 /* resize */ NULL, 2085 /* expose */ Redisplay, 2086 /* set_values */ SetValues, 2087 /* set_values_hook */ NULL, 2088 /* set_values_almost */ XtInheritSetValuesAlmost, 2089 /* get_values_hook */ NULL, 2090 /* accept_focus */ NULL, 2091 /* version */ XtVersion, 2092 /* callback_private */ NULL, 2093 /* tm_table */ defaultLoginTranslations, 2094 /* query_geometry */ XtInheritQueryGeometry, 2095 /* display_accelerator */ XtInheritDisplayAccelerator, 2096 /* extension */ NULL 2097 } 2098}; 2099 2100WidgetClass loginWidgetClass = (WidgetClass) &loginClassRec; 2101