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