home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xdm / Login.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-18  |  24.8 KB  |  901 lines

  1. /*
  2.  * xdm - display manager daemon
  3.  *
  4.  * $XConsortium: Login.c,v 1.35 91/07/18 19:31:10 rws Exp $
  5.  *
  6.  * Copyright 1988 Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of M.I.T. not be used in advertising or
  13.  * publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  M.I.T. makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * Author:  Keith Packard, MIT X Consortium
  19.  */
  20.  
  21. /*
  22.  * Login.c
  23.  */
  24.  
  25. # include <X11/IntrinsicP.h>
  26. # include <X11/StringDefs.h>
  27. # include <X11/keysym.h>
  28. # include <X11/Xfuncs.h>
  29.  
  30. # include <stdio.h>
  31.  
  32. # include "LoginP.h"
  33.  
  34. #define offset(field) XtOffsetOf(LoginRec, login.field)
  35. #define goffset(field) XtOffsetOf(WidgetRec, core.field)
  36.  
  37. static XtResource resources[] = {
  38.     {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  39.     goffset(width), XtRImmediate,    (XtPointer) 0},
  40.     {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  41.     goffset(height), XtRImmediate,    (XtPointer) 0},
  42.     {XtNx, XtCX, XtRPosition, sizeof (Position),
  43.     goffset(x), XtRImmediate,    (XtPointer) -1},
  44.     {XtNy, XtCY, XtRPosition, sizeof (Position),
  45.     goffset(y), XtRImmediate,    (XtPointer) -1},
  46.     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  47.         offset(textpixel), XtRString,    XtDefaultForeground},
  48.     {XtNpromptColor, XtCForeground, XtRPixel, sizeof(Pixel),
  49.         offset(promptpixel), XtRString,    XtDefaultForeground},
  50.     {XtNgreetColor, XtCForeground, XtRPixel, sizeof(Pixel),
  51.         offset(greetpixel), XtRString,    XtDefaultForeground},
  52.     {XtNfailColor, XtCForeground, XtRPixel, sizeof (Pixel),
  53.     offset(failpixel), XtRString,    XtDefaultForeground},
  54.     {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  55.         offset (font), XtRString,    "*-new century schoolbook-medium-r-normal-*-180-*"},
  56.     {XtNpromptFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  57.         offset (promptFont), XtRString, "*-new century schoolbook-bold-r-normal-*-180-*"},
  58.     {XtNgreetFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  59.         offset (greetFont), XtRString,    "*-new century schoolbook-bold-i-normal-*-240-*"},
  60.     {XtNfailFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  61.     offset (failFont), XtRString,    "*-new century schoolbook-bold-r-normal-*-180-*"},
  62.     {XtNgreeting, XtCGreeting, XtRString, sizeof (char *),
  63.         offset(greeting), XtRString, "X Window System"},
  64.     {XtNunsecureGreeting, XtCGreeting, XtRString, sizeof (char *),
  65.     offset(unsecure_greet), XtRString, "This is an unsecure session"},
  66.     {XtNnamePrompt, XtCNamePrompt, XtRString, sizeof (char *),
  67.     offset(namePrompt), XtRString, "Login:  "},
  68.     {XtNpasswdPrompt, XtCNamePrompt, XtRString, sizeof (char *),
  69.     offset(passwdPrompt), XtRString, "Password:  "},
  70.     {XtNfail, XtCFail, XtRString, sizeof (char *),
  71.     offset(fail), XtRString, "Login incorrect"},
  72.     {XtNfailTimeout, XtCFailTimeout, XtRInt, sizeof (int),
  73.     offset(failTimeout), XtRImmediate, (XtPointer) 10},
  74.     {XtNnotifyDone, XtCCallback, XtRFunction, sizeof (XtPointer),
  75.     offset(notify_done), XtRFunction, (XtPointer) 0},
  76.     {XtNsessionArgument, XtCSessionArgument, XtRString,    sizeof (char *),
  77.     offset(sessionArg), XtRString, (XtPointer) 0 },
  78.     {XtNsecureSession, XtCSecureSession, XtRBoolean, sizeof (Boolean),
  79.     offset(secure_session), XtRImmediate, False },
  80.     {XtNallowAccess, XtCAllowAccess, XtRBoolean, sizeof (Boolean),
  81.     offset(allow_access), XtRImmediate, False }
  82. };
  83.  
  84. #undef offset
  85. #undef goffset
  86.  
  87. # define TEXT_X_INC(w)    ((w)->login.font->max_bounds.width)
  88. # define TEXT_Y_INC(w)    ((w)->login.font->max_bounds.ascent +\
  89.              (w)->login.font->max_bounds.descent)
  90. # define PROMPT_X_INC(w)    ((w)->login.promptFont->max_bounds.width)
  91. # define PROMPT_Y_INC(w)    ((w)->login.promptFont->max_bounds.ascent +\
  92.              (w)->login.promptFont->max_bounds.descent)
  93. # define GREET_X_INC(w)    ((w)->login.greetFont->max_bounds.width)
  94. # define GREET_Y_INC(w)    ((w)->login.greetFont->max_bounds.ascent +\
  95.              (w)->login.greetFont->max_bounds.descent)
  96. # define FAIL_X_INC(w)    ((w)->login.failFont->max_bounds.width)
  97. # define FAIL_Y_INC(w)    ((w)->login.failFont->max_bounds.ascent +\
  98.              (w)->login.failFont->max_bounds.descent)
  99.  
  100. # define Y_INC(w)    max (TEXT_Y_INC(w), PROMPT_Y_INC(w))
  101.  
  102. # define LOGIN_PROMPT_W(w) (XTextWidth (w->login.promptFont,\
  103.                  w->login.namePrompt,\
  104.                  strlen (w->login.namePrompt)))
  105. # define PASS_PROMPT_W(w) (XTextWidth (w->login.promptFont,\
  106.                  w->login.passwdPrompt,\
  107.                  strlen (w->login.passwdPrompt)))
  108. # define PROMPT_W(w)    (max(LOGIN_PROMPT_W(w), PASS_PROMPT_W(w)))
  109. # define GREETING(w)    ((w)->login.secure_session  && !(w)->login.allow_access ?\
  110.                 (w)->login.greeting : (w)->login.unsecure_greet)
  111. # define GREET_X(w)    ((int)(w->core.width - XTextWidth (w->login.greetFont,\
  112.               GREETING(w), strlen (GREETING(w)))) / 2)
  113. # define GREET_Y(w)    (GREETING(w)[0] ? 2 * GREET_Y_INC (w) : 0)
  114. # define GREET_W(w)    (max (XTextWidth (w->login.greetFont,\
  115.                   w->login.greeting, strlen (w->login.greeting)), \
  116.                   XTextWidth (w->login.greetFont,\
  117.                   w->login.unsecure_greet, strlen (w->login.unsecure_greet))))
  118. # define LOGIN_X(w)    (2 * PROMPT_X_INC(w))
  119. # define LOGIN_Y(w)    (GREET_Y(w) + GREET_Y_INC(w) +\
  120.              w->login.greetFont->max_bounds.ascent + Y_INC(w))
  121. # define LOGIN_W(w)    (w->core.width - 6 * TEXT_X_INC(w))
  122. # define LOGIN_H(w)    (3 * Y_INC(w) / 2)
  123. # define LOGIN_TEXT_X(w)(LOGIN_X(w) + PROMPT_W(w))
  124. # define PASS_X(w)    (LOGIN_X(w))
  125. # define PASS_Y(w)    (LOGIN_Y(w) + 8 * Y_INC(w) / 5)
  126. # define PASS_W(w)    (LOGIN_W(w))
  127. # define PASS_H(w)    (LOGIN_H(w))
  128. # define PASS_TEXT_X(w)    (PASS_X(w) + PROMPT_W(w))
  129. # define FAIL_X(w)    ((int)(w->core.width - XTextWidth (w->login.failFont,\
  130.                 w->login.fail, strlen (w->login.fail))) / 2)
  131. # define FAIL_Y(w)    (PASS_Y(w) + 2 * FAIL_Y_INC (w) +\
  132.             w->login.failFont->max_bounds.ascent)
  133. # define FAIL_W(w)    (XTextWidth (w->login.failFont,\
  134.              w->login.fail, strlen (w->login.fail)))
  135.  
  136. # define PAD_X(w)    (2 * (LOGIN_X(w) + max (GREET_X_INC(w), FAIL_X_INC(w))))
  137.  
  138. # define PAD_Y(w)    (max (max (Y_INC(w), GREET_Y_INC(w)),\
  139.                  FAIL_Y_INC(w)))
  140.     
  141. static void Initialize(), Realize(), Destroy(), Redisplay();
  142. static Boolean SetValues();
  143. static void draw_it ();
  144.  
  145. static void ClassInitialize();
  146.  
  147. static int max (a,b) { return a > b ? a : b; }
  148.  
  149. static void
  150. EraseName (w, cursor)
  151.     LoginWidget    w;
  152.     int        cursor;
  153. {
  154.     int    x;
  155.  
  156.     x = LOGIN_TEXT_X (w);
  157.     if (cursor > 0)
  158.     x += XTextWidth (w->login.font, w->login.data.name, cursor);
  159.     XDrawString (XtDisplay(w), XtWindow (w), w->login.bgGC, x, LOGIN_Y(w),
  160.         w->login.data.name + cursor, strlen (w->login.data.name + cursor));
  161. }
  162.  
  163. static void
  164. DrawName (w, cursor)
  165.     LoginWidget    w;
  166.     int        cursor;
  167. {
  168.     int    x;
  169.  
  170.     x = LOGIN_TEXT_X (w);
  171.     if (cursor > 0)
  172.     x += XTextWidth (w->login.font, w->login.data.name, cursor);
  173.     XDrawString (XtDisplay(w), XtWindow (w), w->login.textGC, x, LOGIN_Y(w),
  174.         w->login.data.name + cursor, strlen (w->login.data.name + cursor));
  175. }
  176.  
  177. static void
  178. realizeCursor (w, gc)
  179.     LoginWidget    w;
  180.     GC        gc;
  181. {
  182.     int    x, y;
  183.     int height, width;
  184.  
  185.     switch (w->login.state) {
  186.     case GET_NAME:
  187.     x = LOGIN_TEXT_X (w);
  188.     y = LOGIN_Y (w);
  189.     height = w->login.font->max_bounds.ascent + w->login.font->max_bounds.descent;
  190.     width = 1;
  191.     if (w->login.cursor > 0)
  192.         x += XTextWidth (w->login.font, w->login.data.name, w->login.cursor);
  193.     break;
  194.     case GET_PASSWD:
  195.     x = PASS_TEXT_X (w);
  196.     y = PASS_Y (w);
  197.     height = w->login.font->max_bounds.ascent + w->login.font->max_bounds.descent;
  198.     width = 1;
  199.     break;
  200.     default:
  201.     return;
  202.     }
  203.     XFillRectangle (XtDisplay (w), XtWindow (w), gc,
  204.             x, y - w->login.font->max_bounds.ascent, width, height);
  205. }
  206.  
  207. static void
  208. EraseFail (w)
  209.     LoginWidget    w;
  210. {
  211.     int x = FAIL_X(w);
  212.     int y = FAIL_Y(w);
  213.  
  214.     XSetForeground (XtDisplay (w), w->login.failGC,
  215.             w->core.background_pixel);
  216.     XDrawString (XtDisplay (w), XtWindow (w), w->login.failGC,
  217.         x, y,
  218.         w->login.fail, strlen (w->login.fail));
  219.     w->login.failUp = 0;
  220.     XSetForeground (XtDisplay (w), w->login.failGC,
  221.             w->login.failpixel);
  222. }
  223.  
  224. static void
  225. XorCursor (w)
  226.     LoginWidget    w;
  227. {
  228.     realizeCursor (w, w->login.xorGC);
  229. }
  230.  
  231. static void
  232. RemoveFail (w)
  233.     LoginWidget    w;
  234. {
  235.     if (w->login.failUp)
  236.     EraseFail (w);
  237. }
  238.  
  239. static void
  240. EraseCursor (w)
  241.     LoginWidget (w);
  242. {
  243.     realizeCursor (w, w->login.bgGC);
  244. }
  245.  
  246. /*ARGSUSED*/
  247. void failTimeout (client_data, id)
  248.     XtPointer    client_data;
  249.     XtIntervalId *    id;
  250. {
  251.     LoginWidget    w = (LoginWidget)client_data;
  252.  
  253.     Debug ("failTimeout\n");
  254.     EraseFail (w);
  255. }
  256.  
  257. DrawFail (ctx)
  258.     Widget    ctx;
  259. {
  260.     LoginWidget    w;
  261.  
  262.     w = (LoginWidget) ctx;
  263.     XorCursor (w);
  264.     ResetLogin (w);
  265.     XorCursor (w);
  266.     w->login.failUp = 1;
  267.     RedrawFail (w);
  268.     if (w->login.failTimeout > 0) {
  269.     Debug ("failTimeout: %d\n", w->login.failTimeout);
  270.     XtAppAddTimeOut(XtWidgetToApplicationContext ((Widget)w),
  271.             w->login.failTimeout * 1000,
  272.                 failTimeout, (XtPointer) w);
  273.     }
  274. }
  275.  
  276. RedrawFail (w)
  277.     LoginWidget w;
  278. {
  279.     int x = FAIL_X(w);
  280.     int y = FAIL_Y(w);
  281.  
  282.     if (w->login.failUp)
  283.         XDrawString (XtDisplay (w), XtWindow (w), w->login.failGC,
  284.             x, y,
  285.             w->login.fail, strlen (w->login.fail));
  286. }
  287.  
  288. static void
  289. draw_it (w)
  290.     LoginWidget    w;
  291. {
  292.     EraseCursor (w);
  293.     if (GREETING(w)[0])
  294.         XDrawString (XtDisplay (w), XtWindow (w), w->login.greetGC,
  295.             GREET_X(w), GREET_Y(w),
  296.             GREETING(w), strlen (GREETING(w)));
  297.     XDrawString (XtDisplay (w), XtWindow (w), w->login.promptGC,
  298.         LOGIN_X(w), LOGIN_Y(w),
  299.         w->login.namePrompt, strlen (w->login.namePrompt));
  300.     XDrawString (XtDisplay (w), XtWindow (w), w->login.promptGC,
  301.         PASS_X(w), PASS_Y(w),
  302.         w->login.passwdPrompt, strlen (w->login.passwdPrompt));
  303.     RedrawFail (w);
  304.     DrawName (w, 0);
  305.     XorCursor (w);
  306.     /*
  307.      * The GrabKeyboard here is needed only because of
  308.      * a bug in the R3 server -- the keyboard is grabbed on
  309.      * the root window, and the server won't dispatch events
  310.      * to the focus window unless the focus window is a ancestor
  311.      * of the grab window.  Bug in server already found and fixed,
  312.      * compatibility until at least R4.
  313.      */
  314.     if (XGrabKeyboard (XtDisplay (w), XtWindow (w), False, GrabModeAsync,
  315.                GrabModeAsync, CurrentTime) != GrabSuccess)
  316.     {
  317.     XSetInputFocus (XtDisplay (w), XtWindow (w),
  318.             RevertToPointerRoot, CurrentTime);
  319.     }
  320. }
  321.  
  322. /*ARGSUSED*/
  323. static void
  324. DeleteBackwardChar (ctxw, event, params, num_params)
  325.     Widget ctxw;
  326.     XEvent    *event;
  327.     String    *params;
  328.     Cardinal    *num_params;
  329. {
  330.     LoginWidget ctx = (LoginWidget)ctxw;
  331.  
  332.     XorCursor (ctx);
  333.     RemoveFail (ctx);
  334.     if (ctx->login.cursor > 0) {
  335.     ctx->login.cursor--;
  336.     switch (ctx->login.state) {
  337.     case GET_NAME:
  338.         EraseName (ctx, ctx->login.cursor);
  339.         strcpy (ctx->login.data.name + ctx->login.cursor,
  340.             ctx->login.data.name + ctx->login.cursor + 1);
  341.         DrawName (ctx, ctx->login.cursor);
  342.         break;
  343.     case GET_PASSWD:
  344.         strcpy (ctx->login.data.passwd + ctx->login.cursor,
  345.             ctx->login.data.passwd + ctx->login.cursor + 1);
  346.         break;
  347.     }
  348.     }
  349.     XorCursor (ctx);    
  350. }
  351.  
  352. /*ARGSUSED*/
  353. static void
  354. DeleteForwardChar (ctxw, event, params, num_params)
  355.     Widget    ctxw;
  356.     XEvent    *event;
  357.     String    *params;
  358.     Cardinal    *num_params;
  359. {
  360.     LoginWidget ctx = (LoginWidget)ctxw;
  361.  
  362.     XorCursor (ctx);
  363.     RemoveFail (ctx);
  364.     switch (ctx->login.state) {
  365.     case GET_NAME:
  366.     if (ctx->login.cursor < (int)strlen (ctx->login.data.name)) {
  367.         EraseName (ctx, ctx->login.cursor);
  368.         strcpy (ctx->login.data.name + ctx->login.cursor,
  369.             ctx->login.data.name + ctx->login.cursor + 1);
  370.         DrawName (ctx, ctx->login.cursor);
  371.     }
  372.     break;
  373.     case GET_PASSWD:
  374.         if (ctx->login.cursor < (int)strlen (ctx->login.data.passwd)) {
  375.         strcpy (ctx->login.data.passwd + ctx->login.cursor,
  376.             ctx->login.data.passwd + ctx->login.cursor + 1);
  377.     }
  378.     break;
  379.     }
  380.     XorCursor (ctx);    
  381. }
  382.  
  383. /*ARGSUSED*/
  384. static void
  385. MoveBackwardChar (ctxw, event, params, num_params)
  386.     Widget    ctxw;
  387.     XEvent    *event;
  388.     String    *params;
  389.     Cardinal    *num_params;
  390. {
  391.     LoginWidget    ctx = (LoginWidget)ctxw;
  392.  
  393.     XorCursor (ctx);
  394.     RemoveFail (ctx);
  395.     if (ctx->login.cursor > 0)
  396.         ctx->login.cursor--;
  397.     XorCursor (ctx);
  398. }
  399.  
  400. /*ARGSUSED*/
  401. static void
  402. MoveForwardChar (ctxw, event, params, num_params)
  403.     Widget    ctxw;
  404.     XEvent    *event;
  405.     String    *params;
  406.     Cardinal    *num_params;
  407. {
  408.     LoginWidget ctx = (LoginWidget)ctxw;
  409.  
  410.     XorCursor (ctx);
  411.     RemoveFail (ctx);
  412.     switch (ctx->login.state) {
  413.     case GET_NAME:
  414.         if (ctx->login.cursor < (int)strlen(ctx->login.data.name))
  415.         ++ctx->login.cursor;
  416.     break;
  417.     case GET_PASSWD:
  418.         if (ctx->login.cursor < (int)strlen(ctx->login.data.passwd))
  419.         ++ctx->login.cursor;
  420.     break;
  421.     }
  422.     XorCursor (ctx);
  423. }
  424.  
  425. /*ARGSUSED*/
  426. static void
  427. MoveToBegining (ctxw, event, params, num_params)
  428.     Widget    ctxw;
  429.     XEvent    *event;
  430.     String    *params;
  431.     Cardinal    *num_params;
  432. {
  433.     LoginWidget ctx = (LoginWidget)ctxw;
  434.  
  435.     XorCursor (ctx);
  436.     RemoveFail (ctx);
  437.     ctx->login.cursor = 0;
  438.     XorCursor (ctx);
  439. }
  440.  
  441. /*ARGSUSED*/
  442. static void
  443. MoveToEnd (ctxw, event, params, num_params)
  444.     Widget    ctxw;
  445.     XEvent    *event;
  446.     String    *params;
  447.     Cardinal    *num_params;
  448. {
  449.     LoginWidget ctx = (LoginWidget)ctxw;
  450.  
  451.     XorCursor (ctx);
  452.     RemoveFail (ctx);
  453.     switch (ctx->login.state) {
  454.     case GET_NAME:
  455.         ctx->login.cursor = strlen (ctx->login.data.name);
  456.     break;
  457.     case GET_PASSWD:
  458.         ctx->login.cursor = strlen (ctx->login.data.passwd);
  459.     break;
  460.     }
  461.     XorCursor (ctx);
  462. }
  463.  
  464. /*ARGSUSED*/
  465. static void
  466. EraseToEndOfLine (ctxw, event, params, num_params)
  467.     Widget    ctxw;
  468.     XEvent    *event;
  469.     String    *params;
  470.     Cardinal    *num_params;
  471. {
  472.     LoginWidget ctx = (LoginWidget)ctxw;
  473.  
  474.     XorCursor (ctx);
  475.     RemoveFail (ctx);
  476.     switch (ctx->login.state) {
  477.     case GET_NAME:
  478.     EraseName (ctx, ctx->login.cursor);
  479.     ctx->login.data.name[ctx->login.cursor] = '\0';
  480.     break;
  481.     case GET_PASSWD:
  482.     ctx->login.data.passwd[ctx->login.cursor] = '\0';
  483.     break;
  484.     }
  485.     XorCursor (ctx);
  486. }
  487.  
  488. /*ARGSUSED*/
  489. static void
  490. EraseLine (ctxw, event, params, num_params)
  491.     Widget    ctxw;
  492.     XEvent    *event;
  493.     String    *params;
  494.     Cardinal    *num_params;
  495. {
  496.     MoveToBegining (ctxw, event, params, num_params);
  497.     EraseToEndOfLine (ctxw, event, params, num_params);
  498. }
  499.  
  500. /*ARGSUSED*/
  501. static void
  502. FinishField (ctxw, event, params, num_params)
  503.     Widget    ctxw;
  504.     XEvent    *event;
  505.     String    *params;
  506.     Cardinal    *num_params;
  507. {
  508.     LoginWidget ctx = (LoginWidget)ctxw;
  509.  
  510.     XorCursor (ctx);
  511.     RemoveFail (ctx);
  512.     switch (ctx->login.state) {
  513.     case GET_NAME:
  514.     ctx->login.state = GET_PASSWD;
  515.     ctx->login.cursor = 0;
  516.     break;
  517.     case GET_PASSWD:
  518.     ctx->login.state = DONE;
  519.     ctx->login.cursor = 0;
  520.     (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_OK);
  521.     break;
  522.     }
  523.     XorCursor (ctx);
  524. }
  525.  
  526. /*ARGSUSED*/
  527. static void
  528. AllowAccess (ctxw, event, params, num_params)
  529.     Widget    ctxw;
  530.     XEvent    *event;
  531.     String    *params;
  532.     Cardinal    *num_params;
  533. {
  534.     LoginWidget ctx = (LoginWidget)ctxw;
  535.     Arg    arglist[1];
  536.     Boolean allow;
  537.  
  538.     RemoveFail (ctx);
  539.     XtSetArg (arglist[0], XtNallowAccess, (char *) &allow);
  540.     XtGetValues ((Widget) ctx, arglist, 1);
  541.     XtSetArg (arglist[0], XtNallowAccess, !allow);
  542.     XtSetValues ((Widget) ctx, arglist, 1);
  543. }
  544.  
  545. /*ARGSUSED*/
  546. static void
  547. SetSessionArgument (ctxw, event, params, num_params)
  548.     Widget    ctxw;
  549.     XEvent    *event;
  550.     String    *params;
  551.     Cardinal    *num_params;
  552. {
  553.     LoginWidget ctx = (LoginWidget)ctxw;
  554.  
  555.     RemoveFail (ctx);
  556.     if (ctx->login.sessionArg)
  557.     XtFree (ctx->login.sessionArg);
  558.     ctx->login.sessionArg = 0;
  559.     if (*num_params > 0) {
  560.     ctx->login.sessionArg = XtMalloc (strlen (params[0]) + 1);
  561.     if (ctx->login.sessionArg)
  562.         strcpy (ctx->login.sessionArg, params[0]);
  563.     else
  564.         LogOutOfMem ("set session argument");
  565.     }
  566. }
  567.  
  568. /*ARGSUSED*/
  569. static void
  570. RestartSession (ctxw, event, params, num_params)
  571.     Widget    ctxw;
  572.     XEvent    *event;
  573.     String    *params;
  574.     Cardinal    *num_params;
  575. {
  576.     LoginWidget ctx = (LoginWidget)ctxw;
  577.  
  578.     XorCursor (ctx);
  579.     RemoveFail (ctx);
  580.     ctx->login.state = DONE;
  581.     ctx->login.cursor = 0;
  582.     (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_RESTART);
  583.     XorCursor (ctx);
  584. }
  585.  
  586. /*ARGSUSED*/
  587. static void
  588. AbortSession (ctxw, event, params, num_params)
  589.     Widget    ctxw;
  590.     XEvent    *event;
  591.     String    *params;
  592.     Cardinal    *num_params;
  593. {
  594.     LoginWidget ctx = (LoginWidget)ctxw;
  595.  
  596.     XorCursor (ctx);
  597.     RemoveFail (ctx);
  598.     ctx->login.state = DONE;
  599.     ctx->login.cursor = 0;
  600.     (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT);
  601.     XorCursor (ctx);
  602. }
  603.  
  604. /*ARGSUSED*/
  605. static void
  606. AbortDisplay (ctxw, event, params, num_params)
  607.     Widget    ctxw;
  608.     XEvent    *event;
  609.     String    *params;
  610.     Cardinal    *num_params;
  611. {
  612.     LoginWidget ctx = (LoginWidget)ctxw;
  613.  
  614.     XorCursor (ctx);
  615.     RemoveFail (ctx);
  616.     ctx->login.state = DONE;
  617.     ctx->login.cursor = 0;
  618.     (*ctx->login.notify_done) (ctx, &ctx->login.data, NOTIFY_ABORT_DISPLAY);
  619.     XorCursor (ctx);
  620. }
  621.  
  622. ResetLogin (w)
  623.     LoginWidget    w;
  624. {
  625.     EraseName (w, 0);
  626.     w->login.cursor = 0;
  627.     w->login.data.name[0] = '\0';
  628.     w->login.data.passwd[0] = '\0';
  629.     w->login.state = GET_NAME;
  630. }
  631.  
  632. /* ARGSUSED */
  633. static void
  634. InsertChar (ctxw, event, params, num_params)
  635.     Widget    ctxw;
  636.     XEvent    *event;
  637.     String    *params;
  638.     Cardinal    *num_params;
  639. {
  640.     LoginWidget ctx = (LoginWidget)ctxw;
  641.  
  642.     char strbuf[128];
  643.     int  len;
  644.  
  645.     len = XLookupString (&event->xkey, strbuf, sizeof (strbuf), 0, 0);
  646.     strbuf[len] = '\0';
  647.     if (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1)
  648.         len = NAME_LEN - strlen(ctx->login.data.name) - 2;
  649.     if (len == 0)
  650.     return;
  651.     XorCursor (ctx);
  652.     RemoveFail (ctx);
  653.     switch (ctx->login.state) {
  654.     case GET_NAME:
  655.     EraseName (ctx, ctx->login.cursor);
  656.     bcopy (ctx->login.data.name + ctx->login.cursor,
  657.            ctx->login.data.name + ctx->login.cursor + len,
  658.            strlen (ctx->login.data.name + ctx->login.cursor) + 1);
  659.     bcopy (strbuf, ctx->login.data.name + ctx->login.cursor, len);
  660.     DrawName (ctx, ctx->login.cursor);
  661.     ctx->login.cursor += len;
  662.     break;
  663.     case GET_PASSWD:
  664.     bcopy (ctx->login.data.passwd + ctx->login.cursor,
  665.            ctx->login.data.passwd + ctx->login.cursor + len,
  666.            strlen (ctx->login.data.passwd + ctx->login.cursor) + 1);
  667.     bcopy (strbuf, ctx->login.data.passwd + ctx->login.cursor, len);
  668.     ctx->login.cursor += len;
  669.     break;
  670.     }
  671.     XorCursor (ctx);
  672. }
  673.  
  674. /*ARGSUSED*/
  675. static void FetchDisplayArg(widget, size, value)
  676.     Widget widget;
  677.     Cardinal *size;
  678.     XrmValue* value;
  679. {
  680.     value->size = sizeof(Display*);
  681.     value->addr = (caddr_t)&DisplayOfScreen(XtScreenOfObject(widget));
  682. }
  683.  
  684. static XtConvertArgRec displayConvertArg[] = {
  685.     {XtProcedureArg, (XtPointer)FetchDisplayArg, 0},
  686. };
  687.  
  688. /* ARGSUSED */
  689. static void Initialize (greq, gnew, args, num_args)
  690.     Widget greq, gnew;
  691.     ArgList args;
  692.     Cardinal *num_args;
  693. {
  694.     LoginWidget w = (LoginWidget)gnew;
  695.     XtGCMask    valuemask, xvaluemask;
  696.     XGCValues    myXGCV;
  697.     Arg        position[2];
  698.     Position    x, y;
  699.  
  700.     myXGCV.foreground = w->login.textpixel;
  701.     myXGCV.background = w->core.background_pixel;
  702.     valuemask = GCForeground | GCBackground;
  703.     if (w->login.font) {
  704.     myXGCV.font = w->login.font->fid;
  705.     valuemask |= GCFont;
  706.     }
  707.     w->login.textGC = XtGetGC(gnew, valuemask, &myXGCV);
  708.     myXGCV.foreground = w->core.background_pixel;
  709.     w->login.bgGC = XtGetGC(gnew, valuemask, &myXGCV);
  710.  
  711.     myXGCV.foreground = w->login.textpixel ^ w->core.background_pixel;
  712.     myXGCV.function = GXxor;
  713.     xvaluemask = valuemask | GCFunction;
  714.     w->login.xorGC = XtGetGC (gnew, xvaluemask, &myXGCV);
  715.  
  716.     /*
  717.      * Note that the second argument is a GCid -- QueryFont accepts a GCid and
  718.      * returns the curently contained font.
  719.      */
  720.  
  721.     if (w->login.font == NULL)
  722.     w->login.font = XQueryFont (XtDisplay (w),
  723.         XGContextFromGC (DefaultGCOfScreen (XtScreen (w))));
  724.  
  725.     xvaluemask = valuemask;
  726.     if (w->login.promptFont == NULL)
  727.         w->login.promptFont = w->login.font;
  728.     else
  729.     xvaluemask |= GCFont;
  730.  
  731.     myXGCV.foreground = w->login.promptpixel;
  732.     myXGCV.font = w->login.promptFont->fid;
  733.     w->login.promptGC = XtGetGC (gnew, xvaluemask, &myXGCV);
  734.  
  735.     xvaluemask = valuemask;
  736.     if (w->login.greetFont == NULL)
  737.         w->login.greetFont = w->login.font;
  738.     else
  739.     xvaluemask |= GCFont;
  740.  
  741.     myXGCV.foreground = w->login.greetpixel;
  742.     myXGCV.font = w->login.greetFont->fid;
  743.     w->login.greetGC = XtGetGC (gnew, xvaluemask, &myXGCV);
  744.  
  745.     xvaluemask = valuemask;
  746.     if (w->login.failFont == NULL)
  747.     w->login.failFont = w->login.font;
  748.     else
  749.     xvaluemask |= GCFont;
  750.  
  751.     myXGCV.foreground = w->login.failpixel;
  752.     myXGCV.font = w->login.failFont->fid;
  753.     w->login.failGC = XtGetGC (gnew, xvaluemask, &myXGCV);
  754.  
  755.     w->login.data.name[0] = '\0';
  756.     w->login.data.passwd[0] = '\0';
  757.     w->login.state = GET_NAME;
  758.     w->login.cursor = 0;
  759.     w->login.failUp = 0;
  760.     if (w->core.width == 0)
  761.     w->core.width = max (GREET_W(w), FAIL_W(w)) + PAD_X(w);
  762.     if (w->core.height == 0) {
  763.     int fy = FAIL_Y(w);
  764.     int pady = PAD_Y(w);
  765.  
  766.     w->core.height = fy + pady;    /* for stupid compilers */
  767.     }
  768.     if ((x = w->core.x) == -1)
  769.     x = (int)(WidthOfScreen (XtScreen (w)) - w->core.width) / 2;
  770.     if ((y = w->core.y) == -1)
  771.     y = (int)(HeightOfScreen (XtScreen (w)) - w->core.height) / 3;
  772.     XtSetArg (position[0], XtNx, x);
  773.     XtSetArg (position[1], XtNy, y);
  774.     XtSetValues (XtParent (w), position, (Cardinal) 2);
  775. }
  776.  
  777.  
  778. static void Realize (gw, valueMask, attrs)
  779.      Widget gw;
  780.      XtValueMask *valueMask;
  781.      XSetWindowAttributes *attrs;
  782. {
  783.     XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
  784.              *valueMask, attrs );
  785. }
  786.  
  787. static void Destroy (gw)
  788.      Widget gw;
  789. {
  790.     LoginWidget w = (LoginWidget)gw;
  791.     bzero (w->login.data.name, NAME_LEN);
  792.     bzero (w->login.data.passwd, NAME_LEN);
  793.     XtReleaseGC(gw, w->login.textGC);
  794.     XtReleaseGC(gw, w->login.bgGC);
  795.     XtReleaseGC(gw, w->login.xorGC);
  796.     XtReleaseGC(gw, w->login.promptGC);
  797.     XtReleaseGC(gw, w->login.greetGC);
  798.     XtReleaseGC(gw, w->login.failGC);
  799. }
  800.  
  801. /* ARGSUSED */
  802. static void Redisplay(gw, event, region)
  803.      Widget gw;
  804.      XEvent *event;
  805.      Region region;
  806. {
  807.     draw_it ((LoginWidget) gw);
  808. }
  809.  
  810. /*ARGSUSED*/
  811. static Boolean SetValues (current, request, new, args, num_args)
  812.     Widget  current, request, new;
  813.     ArgList args;
  814.     Cardinal *num_args;
  815. {
  816.     LoginWidget currentL, newL;
  817.     
  818.     currentL = (LoginWidget) current;
  819.     newL = (LoginWidget) new;
  820.     if (GREETING (currentL) != GREETING (newL))
  821.     return True;
  822.     return False;
  823. }
  824.  
  825. char defaultLoginTranslations [] =
  826. "\
  827. Ctrl<Key>H:    delete-previous-character() \n\
  828. Ctrl<Key>D:    delete-character() \n\
  829. Ctrl<Key>B:    move-backward-character() \n\
  830. Ctrl<Key>F:    move-forward-character() \n\
  831. Ctrl<Key>A:    move-to-begining() \n\
  832. Ctrl<Key>E:    move-to-end() \n\
  833. Ctrl<Key>K:    erase-to-end-of-line() \n\
  834. Ctrl<Key>U:    erase-line() \n\
  835. Ctrl<Key>X:    erase-line() \n\
  836. Ctrl<Key>C:    restart-session() \n\
  837. Ctrl<Key>\\\\:    abort-session() \n\
  838. :Ctrl<Key>plus:    allow-all-access() \n\
  839. <Key>BackSpace:    delete-previous-character() \n\
  840. <Key>Delete:    delete-previous-character() \n\
  841. <Key>Return:    finish-field() \n\
  842. <Key>:        insert-char() \
  843. ";
  844.  
  845. XtActionsRec loginActionsTable [] = {
  846.   {"delete-previous-character",    DeleteBackwardChar},
  847.   {"delete-character",        DeleteForwardChar},
  848.   {"move-backward-character",    MoveBackwardChar},
  849.   {"move-forward-character",    MoveForwardChar},
  850.   {"move-to-begining",        MoveToBegining},
  851.   {"move-to-end",        MoveToEnd},
  852.   {"erase-to-end-of-line",    EraseToEndOfLine},
  853.   {"erase-line",        EraseLine},
  854.   {"finish-field",         FinishField},
  855.   {"abort-session",        AbortSession},
  856.   {"abort-display",        AbortDisplay},
  857.   {"restart-session",        RestartSession},
  858.   {"insert-char",         InsertChar},
  859.   {"set-session-argument",    SetSessionArgument},
  860.   {"allow-all-access",        AllowAccess},
  861. };
  862.  
  863. LoginClassRec loginClassRec = {
  864.     { /* core fields */
  865.     /* superclass        */    &widgetClassRec,
  866.     /* class_name        */    "Login",
  867.     /* size            */    sizeof(LoginRec),
  868.     /* class_initialize        */    NULL,
  869.     /* class_part_initialize    */    NULL,
  870.     /* class_inited        */    FALSE,
  871.     /* initialize        */    Initialize,
  872.     /* initialize_hook        */    NULL,
  873.     /* realize            */    Realize,
  874.     /* actions            */    loginActionsTable,
  875.     /* num_actions        */    XtNumber (loginActionsTable),
  876.     /* resources        */    resources,
  877.     /* num_resources        */    XtNumber(resources),
  878.     /* xrm_class        */    NULLQUARK,
  879.     /* compress_motion        */    TRUE,
  880.     /* compress_exposure    */    TRUE,
  881.     /* compress_enterleave    */    TRUE,
  882.     /* visible_interest        */    FALSE,
  883.     /* destroy            */    Destroy,
  884.     /* resize            */    NULL,
  885.     /* expose            */    Redisplay,
  886.     /* set_values        */    SetValues,
  887.     /* set_values_hook        */    NULL,
  888.     /* set_values_almost    */    NULL,
  889.     /* get_values_hook        */    NULL,
  890.     /* accept_focus        */    NULL,
  891.     /* version            */    XtVersion,
  892.     /* callback_private        */    NULL,
  893.     /* tm_table            */    defaultLoginTranslations,
  894.     /* query_geometry        */    XtInheritQueryGeometry,
  895.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  896.     /* extension        */    NULL
  897.     }
  898. };
  899.  
  900. WidgetClass loginWidgetClass = (WidgetClass) &loginClassRec;
  901.