home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / xsaver / part01 / savescreen.c < prev   
Encoding:
C/C++ Source or Header  |  1989-03-10  |  18.3 KB  |  749 lines

  1. /*
  2.  * $Source: /mit/sipbsrc/uus/src/xscreensaver/RCS/savescreen.c,v $
  3.  * $Author: jik $
  4.  *
  5.  * This file is part of xscreensaver.  It contains the code for the
  6.  * actual locking/blanking of the screen, with the floating icon and
  7.  * the handling of passwords.
  8.  *
  9.  * Author: Jonathan Kamens, MIT Project Athena and
  10.  *                          MIT Student Information Processing Board
  11.  *
  12.  * Coyright (c) 1989 by Jonathan Kamens.  This code may be distributed
  13.  * freely as long as this notice is kept intact in its entirety and
  14.  * every effort is made to send all corrections and improvements to
  15.  * the code back to the author.  Also, don't try to make any money off
  16.  * of it or pretend that you wrote it.
  17.  */
  18.  
  19. #ifndef lint
  20.      static char rcsid_savescreen_c[] = "$Header: savescreen.c,v 1.18 89/02/28 06:55:18 jik Exp $";
  21. #endif
  22.  
  23. #include <stdio.h>
  24. #include <X11/Xos.h>
  25. #include <signal.h>
  26. #include <X11/Intrinsic.h>
  27. #include <X11/StringDefs.h>
  28. #include <X11/Command.h>
  29. #include <X11/Shell.h>
  30. #include <X11/List.h>
  31. #include <X11/Form.h>
  32. #include "xsaver.h"
  33. #include "scaling.h"
  34. #include "globals.h"
  35.  
  36.  
  37. extern char *time_string(), *elapsed_string(), *timeleft_string(),
  38.      *malloc();
  39. extern Cursor blank_cursor();
  40. extern Widget PasswordWindow(), PromptBox();
  41. extern long random();
  42. extern Boolean correct_password();
  43. extern void XtMoveWidget();
  44.  
  45. static void build_root(), lock_command(), unlock_command(), build_float(),
  46.      MoveFloat(), ActivateFloat(), ActivateClock(), UpdateClock(),
  47.      ReallyLockScreen(), SaveScreen(), do_timeout(), PasswordTimeout(),
  48.      LockScreen(), UpdateFloat();
  49. static int new_off(), maybe_new_off_opposite_sign();
  50. static char **breakup();
  51.  
  52. void ActivateRoot(), RaiseRoot(), RemoveRoot(), GetPassword();
  53.  
  54. static WidgetandWidth time_w, elapsed_w, timeout_w, icon_w;
  55. static int x_off = 0, y_off = 0;
  56. static int delay;
  57. Boolean activated = False, getting_password = False;
  58. static Dimension max_float_x, max_float_y;
  59. static int lock_command_pid = 0;
  60. static String lockedTransString = 
  61.      "<Key>:            GetPassword(Locked)\n\
  62.       <BtnDown>,<BtnUp>:    GetPassword(Locked)\n\
  63.       <Visible>:        RaiseRoot()\n";
  64. static XtTranslations lockedTrans = (XtTranslations) NULL;
  65. static Widget root_shell = (Widget) NULL, float_widget = (Widget) NULL;
  66.  
  67.  
  68.  
  69.  
  70. #define PASSWORD_TIMEOUT 30    /* time, in seconds, before a password */
  71.                 /* prompt will time out */
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78. static void build_root()
  79. {
  80.      Arg arglist[10];
  81.      int i = 0;
  82.      Cursor cursor;
  83.  
  84.      if (! root_shell) {
  85.       XtSetArg(arglist[i], XtNborderWidth, 0);             i++;
  86.       XtSetArg(arglist[i], XtNx, 0);                 i++;
  87.       XtSetArg(arglist[i], XtNy, 0);                 i++;
  88.       XtSetArg(arglist[i], XtNwidth, display_width);        i++;
  89.       XtSetArg(arglist[i], XtNheight, display_height);        i++;
  90.       if (defs.use_background) {
  91.            XtSetArg(arglist[i], XtNbackgroundPixmap,
  92.             ParentRelative);                 i++;
  93.       }
  94.       root_shell = XtCreatePopupShell("rootShell",
  95.                       overrideShellWidgetClass,
  96.                       top_widget, arglist, i);
  97.      
  98.       root_widget = XtCreateManagedWidget("root", widgetClass,
  99.                           root_shell, arglist, i);    i = 0;
  100.  
  101.       XtRealizeWidget(root_shell);
  102.  
  103.       /* Here lies the direct Xlib trickery your mother warned you */
  104.       /* about when she taught you tou use Xtk. */
  105.       cursor = blank_cursor();
  106.       XDefineCursor(dpy, XtWindow(root_shell), cursor);
  107.       XDefineCursor(dpy, XtWindow(root_widget), cursor);
  108.      }
  109.      
  110.      /* Setting the coordinates to 0, 0 appears not to work in some */
  111.      /* cases, in particular when people specify Geometry *class* in */
  112.      /* the resources, so we are going to reposition the window after */
  113.      /* we create it. */
  114.      XtMoveWidget(root_shell, 0, 0);
  115. }
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122. /* ARGSUSED */
  123. void ActivateRoot()
  124. {
  125.      ActivateClock();
  126.  
  127.      build_root();
  128.      build_float();
  129.  
  130.      activated = True;
  131.      
  132.      XSetScreenSaver(dpy, 0, saver.interval, saver.prefer_blanking,
  133.              saver.allow_exposures);
  134.      XtMapWidget(root_shell);
  135.      if (XGrabPointer(dpy, XtWindow(root_widget), True, ButtonPressMask,
  136.               GrabModeAsync, GrabModeAsync, XtWindow(root_widget),
  137.               blank_cursor(), CurrentTime) != GrabSuccess)
  138.       fprintf(stderr, "%s: Error grabbing pointer!\n", whoami);
  139.      if (XGrabKeyboard(dpy, XtWindow(root_widget), False, GrabModeAsync,
  140.                GrabModeAsync, CurrentTime) != GrabSuccess)
  141.       fprintf(stderr, "%s: Error grabbing keyboard!\n", whoami);
  142.      XtSetKeyboardFocus(root_shell, root_widget);
  143.  
  144.      if (lock_flag)
  145.       LockScreen();
  146.      else
  147.       SaveScreen();
  148. }
  149.  
  150.  
  151.  
  152. static void LockScreen()
  153. {
  154.      if (! lockedTrans)
  155.       lockedTrans = XtParseTranslationTable(lockedTransString);
  156.      if (! (*defs.ekey || *defs.key)) {
  157.       String str = "Initial";
  158.       Cardinal num = 1;
  159.       GetPassword(root_widget, (XEvent *) NULL, &str, &num);
  160.      }
  161.      else
  162.       ReallyLockScreen();
  163. }
  164.  
  165.  
  166.  
  167. static void ReallyLockScreen()
  168. {
  169.      lock_command();
  170.      XtOverrideTranslations(root_widget, lockedTrans);
  171.      ActivateFloat();
  172. }     
  173.  
  174.  
  175. static void SaveScreen()
  176. {
  177.      static String rootTranslations =
  178.       "<Key>:        RemoveRoot()\n\
  179.            <BtnDown>,<BtnUp>:    RemoveRoot()\n\
  180.            <Visible>:        RaiseRoot()\n";
  181.      XtTranslations trans = (XtTranslations) NULL;
  182.  
  183.      if (! trans)
  184.       trans = XtParseTranslationTable(rootTranslations);
  185.      XtOverrideTranslations(root_widget, trans);
  186.      ActivateFloat();
  187. }
  188.  
  189.  
  190.  
  191.  
  192.  
  193. static void PasswordTimeout()
  194. {
  195.      if (getting_password) {
  196.       char *str = "Timeout";
  197.       Cardinal num = 1;
  198.       GetPassword(root_shell, (XEvent *) NULL, &str, &num);
  199.      }
  200. }
  201.  
  202.  
  203.  
  204.  
  205.  
  206. #define DOING_NOTHING 0
  207. #define GETTING_LOCKED_PASSWORD 3
  208. #define GETTING_FIRST_INITIAL_PASSWORD 1
  209. #define GETTING_SECOND_INITIAL_PASSWORD 2
  210.  
  211. /* ARGSUSED */
  212. void GetPassword(w, event, params, num_params)
  213. Widget w;
  214. XEvent *event;
  215. String *params;
  216. Cardinal *num_params;
  217. {
  218.      static char password[MAXPASSWORD];
  219.      static char *ptr;
  220.      static String gettingPasswordTranslations =
  221.       "<Key>Return:        GetPassword(Done)\n\
  222.        <Key>:        GetPassword(Reading)\n\
  223.            <Visible>:        RaiseRoot()\n";
  224.      static XtTranslations gettingPasswordTrans = (XtTranslations) NULL;
  225.      static Widget prompt;
  226.      static int state = DOING_NOTHING;
  227.      Arg arglist[2];
  228.      int i = 0;
  229.      
  230.      if (! gettingPasswordTrans)
  231.       gettingPasswordTrans =
  232.            XtParseTranslationTable(gettingPasswordTranslations);
  233.      if (**params == 'L') {
  234.       ptr = password;
  235.       state = GETTING_LOCKED_PASSWORD;
  236.       getting_password = True;
  237.       prompt = PasswordWindow(state);
  238.       XtSetArg(arglist[i], XtNtranslations, gettingPasswordTrans);    i++;
  239.       XtSetValues(root_shell, arglist, i);
  240.       XtSetValues(root_widget, arglist, i);                i = 0;
  241.       XtMapWidget(prompt);
  242.       XtAddTimeOut(PASSWORD_TIMEOUT * 1000, PasswordTimeout, NULL);
  243.      }
  244.      else if (**params == 'I') {
  245.       ptr = password;
  246.       state = GETTING_FIRST_INITIAL_PASSWORD;
  247.       getting_password = True;
  248.       prompt = PasswordWindow(state);
  249.       XtOverrideTranslations(root_widget, gettingPasswordTrans);
  250.       XtMapWidget(prompt);
  251.       XtAddTimeOut(PASSWORD_TIMEOUT * 1000, PasswordTimeout, NULL);
  252.      }
  253.      else if (**params == 'R') {
  254.       XtAddTimeOut(PASSWORD_TIMEOUT * 1000, PasswordTimeout, NULL);
  255.       if (ptr - password < MAXPASSWORD - 1) {
  256.            char key_buf[5];
  257.            int num_read;
  258.            
  259.            num_read = XLookupString(event, key_buf, 5,
  260.                     (KeySym *) NULL,
  261.                     (XComposeStatus *) NULL);
  262.            if (num_read == 1) {
  263.             *ptr = *key_buf;
  264.             ptr++;
  265.            }
  266.       }
  267.      }
  268.      else if (**params == 'D') {
  269.       XtUnmapWidget(prompt);
  270.       XtDestroyWidget(prompt);
  271.       *ptr = '\0';
  272.       if (state == GETTING_LOCKED_PASSWORD) {
  273.            getting_password = False;
  274.            state = DOING_NOTHING;
  275.            if (correct_password(password)) {
  276.             RemoveRoot(root_shell, (XEvent *) NULL, (String *) NULL,
  277.                    (Cardinal *) NULL);
  278.             bzero(password, strlen(password));
  279.            }
  280.            else {
  281.             ReallyLockScreen();
  282.             bzero(password, strlen(password));
  283.            }
  284.       }
  285.       else if (state == GETTING_FIRST_INITIAL_PASSWORD) {
  286.            ptr = password;
  287.            if (*ptr) {
  288.             state = GETTING_SECOND_INITIAL_PASSWORD;
  289.             strcpy(defs.key, password);
  290.             bzero(password, strlen(password));
  291.             prompt = PasswordWindow(state);
  292.             XtMapWidget(prompt);
  293.            }
  294.            else { /* User just hit return.  That's a no-no, so ask */
  295.               /* for a password again */
  296.             char *param = "Initial";
  297.             Cardinal num = 1;
  298.  
  299.             XBell(dpy, 100);
  300.             state = DOING_NOTHING;
  301.             GetPassword(root_shell, (XEvent *) NULL, ¶m, &num);
  302.            }
  303.       }
  304.       else if (state == GETTING_SECOND_INITIAL_PASSWORD) {
  305.            if (! strcmp(password, defs.key)) {
  306.             getting_password = False;
  307.             install_password();
  308.             bzero(password, strlen(password));
  309.             ReallyLockScreen();
  310.            }
  311.            else {
  312.             char *param = "Initial";
  313.             Cardinal num = 1;
  314.  
  315.             bzero(password, strlen(password));
  316.             bzero(defs.key, strlen(defs.key));
  317.             state = DOING_NOTHING;
  318.             GetPassword(root_shell, (XEvent *) NULL, ¶m, &num);
  319.            }
  320.       }
  321.      }
  322.      else if (**params == 'T') {
  323.       XtUnmapWidget(prompt);
  324.       XtDestroyWidget(prompt);
  325.       getting_password = False;
  326.       bzero(password, ptr - password);
  327.       if (state == GETTING_LOCKED_PASSWORD)
  328.            ReallyLockScreen();
  329.       else if (state == GETTING_FIRST_INITIAL_PASSWORD)
  330.            RemoveRoot((Widget) NULL, (XEvent *) NULL, (String *) NULL,
  331.               (Cardinal *) NULL);
  332.       else if (state == GETTING_SECOND_INITIAL_PASSWORD)
  333.            RemoveRoot((Widget) NULL, (XEvent *) NULL, (String *) NULL,
  334.               (Cardinal *) NULL);
  335.      }
  336. }
  337.      
  338.             
  339.  
  340.  
  341.  
  342. static void ActivateClock()
  343. {
  344.      struct timeval tim;
  345.  
  346.      gettimeofday(&tim, (struct timezone *) NULL);
  347.      times.start = times.current = times.saver = tim.tv_sec;
  348. }     
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355. static void UpdateClock()
  356. {
  357.      struct timeval tim;
  358.      gettimeofday(&tim, (struct timezone *) NULL);
  359.      times.current = tim.tv_sec;
  360. }
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368. static void ActivateFloat()
  369. {
  370.      Arg arglist[5];
  371.      int i = 0;
  372.      Position x, y;
  373.      Dimension width, height, border;
  374.      
  375.      if (! x_off) {
  376.       XtSetArg(arglist[i], XtNwidth, &width);             i++;
  377.       XtSetArg(arglist[i], XtNheight, &height);             i++;
  378.       XtSetArg(arglist[i], XtNborderWidth, &border);         i++;
  379.       XtGetValues(float_widget, arglist, i);             i = 0;
  380.  
  381.       max_float_x = display_width - width - 2 * border;
  382.       max_float_y = display_height - height - 2 * border;
  383.       x = random() % max_float_x;
  384.       y = random() % max_float_y;
  385.       x_off = new_off();
  386.       y_off = new_off();
  387.  
  388.       delay = calc_delay(x_off, y_off, defs.velocity);
  389.       
  390.       XtMoveWidget(float_widget, x, y);
  391.       XtMapWidget(float_widget);
  392.      }
  393.      else
  394.       UpdateFloat();
  395.       
  396.      XtAddTimeOut(delay, MoveFloat, NULL);
  397. }
  398.  
  399.  
  400.  
  401.      
  402.      
  403. static void do_timeout()
  404. {
  405.      unlock_command();
  406.      exit(0);
  407. }
  408.  
  409.  
  410.  
  411. static void MoveFloat()
  412. {
  413.      Arg arglist[5];
  414.      int i = 0;
  415.      Position x, y;
  416.      int changed_off = 0;
  417.  
  418.      if (getting_password || (! activated))
  419.       return;
  420.      if (lock_flag && defs.timeout) {
  421.       if ((times.current - times.start) >= defs.timeout * 60)
  422.            do_timeout();
  423.      }
  424.      UpdateFloat();
  425.      XtSetArg(arglist[i], XtNx, &x); i++;
  426.      XtSetArg(arglist[i], XtNy, &y); i++;
  427.      XtGetValues(float_widget, arglist, i);
  428.      if (x + x_off > max_float_x) {
  429.       changed_off += maybe_new_off_opposite_sign(&x_off);
  430.      }
  431.      else if (x + x_off < 0) {
  432.       changed_off += maybe_new_off_opposite_sign(&x_off);
  433.      }
  434.      if (y + y_off > max_float_y) {
  435.       changed_off += maybe_new_off_opposite_sign(&y_off);
  436.      }
  437.      else if (y + y_off < 0) {
  438.       changed_off += maybe_new_off_opposite_sign(&y_off);
  439.      }
  440.      x += x_off; y += y_off;
  441.      if (changed_off)
  442.       delay = calc_delay(x_off, y_off, defs.velocity);
  443.      XtMoveWidget(float_widget, x, y);
  444.      XtAddTimeOut(delay, MoveFloat, NULL);
  445. }
  446.  
  447.  
  448.  
  449.  
  450. static void UpdateFloat()
  451. {
  452.      Arg arglist[5];
  453.      int i = 0;
  454.      Dimension width, new_width;
  455.      
  456.      XtSetArg(arglist[i], XtNwidth, &width);                i++;
  457.      XtGetValues(float_widget, arglist, i);                i = 0;
  458.      UpdateClock();
  459.      XtFormDoLayout(float_widget, False);
  460.      XtSetArg(arglist[i], XtNwidth, &icon_w.width);            i++;
  461.      XtGetValues(icon_w.widget, arglist, i);                i = 0;
  462.      if (defs.d_time) {
  463.       char *tm = time_string(TIME_FORMAT, NoForce);
  464.       if (tm) {
  465.            XtSetArg(arglist[i], XtNlabel, tm); i++;
  466.            XtSetValues(time_w.widget, arglist, i); i = 0;
  467.            XtSetArg(arglist[i], XtNwidth, &time_w.width);        i++;
  468.            XtGetValues(time_w.widget, arglist, i);            i = 0;
  469.       }
  470.      }
  471.      if (defs.d_elapsed) {
  472.       char *tm = elapsed_string(ELAPSED_FORMAT, NoForce);
  473.       if (tm) {
  474.            XtSetArg(arglist[i], XtNlabel, tm); i++;
  475.            XtSetValues(elapsed_w.widget, arglist, i); i = 0;
  476.            XtSetArg(arglist[i], XtNwidth, &elapsed_w.width);    i++;
  477.            XtGetValues(elapsed_w.widget, arglist, i);        i = 0;
  478.       }
  479.      }
  480.      if (defs.d_timeout && lock_flag && defs.timeout) {
  481.       char *tm = timeleft_string(TIMELEFT_FORMAT, NoForce);
  482.       if (tm) {
  483.            XtSetArg(arglist[i], XtNlabel, tm); i++;
  484.            XtSetValues(timeout_w.widget, arglist, i); i = 0;
  485.            XtSetArg(arglist[i], XtNwidth, &timeout_w.width);    i++;
  486.            XtGetValues(timeout_w.widget, arglist, i);        i = 0;
  487.       }
  488.      }
  489.      XtFormDoLayout(float_widget, True);
  490.      XtSetArg(arglist[i], XtNwidth, &new_width);            i++;
  491.      XtGetValues(float_widget, arglist, i);                i = 0;
  492.      if (new_width != width) {
  493.       XtFormDoLayout(float_widget, False);
  494.       center(icon_w.widget, icon_w.width, new_width);
  495.       if (defs.d_time)
  496.            center(time_w.widget, time_w.width, new_width);
  497.       if (defs.d_elapsed)
  498.            center(elapsed_w.widget, elapsed_w.width, new_width);
  499.       if (defs.d_timeout && lock_flag && defs.timeout)
  500.            center(timeout_w.widget, timeout_w.width, new_width);
  501.       XtFormDoLayout(float_widget, True);
  502.      }
  503. }     
  504.  
  505.  
  506.  
  507.  
  508. static int maybe_new_off_opposite_sign(foo)
  509. int *foo;
  510. {
  511.      int off = - *foo;
  512.      int changed = 0;
  513.      
  514.      if (! (random() % 4)) {
  515.       off = random() % 5 + 1;
  516.       off = (*foo < 0 ? off : - off);
  517.       changed++;
  518.      }
  519.      *foo = off;
  520.      
  521.      return(changed);
  522. }
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530. static int new_off()
  531. {
  532.      int foo;
  533.      
  534.      foo = random() % 11 - 5;
  535.      if (! foo)
  536.       foo = (random() % 1 ? 1 : -1);
  537.      
  538.      return(foo);
  539. }
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548. static void build_float()
  549. {
  550.      PromptLine lines[MAXPROMPT];
  551.      int i = 0, max_strlen = 0;
  552.      Widget *return_widgets;
  553.      static String float_name = "float";
  554.      static String msg_name = "message";
  555.  
  556.      if (! float_widget) {
  557.       
  558.       /* The first one should pick up a bitmap from the defaults */
  559.       lines[i] = default_line;
  560.       lines[i].use_default = True;
  561.       lines[i].name = float_name;
  562.       lines[i].str = "floatIcon";                    i++;
  563.       if (defs.d_time) {
  564.            lines[i] = default_line;
  565.            lines[i].name = float_name;
  566.            lines[i].str = time_string(TIME_FORMAT, Force);
  567.            max_strlen = ((strlen(lines[i].str) > max_strlen) ?
  568.                  strlen(lines[i].str) : max_strlen);    i++;
  569.       }
  570.       if (defs.d_elapsed) {
  571.            lines[i] = default_line;
  572.            lines[i].name = float_name;
  573.            lines[i].str = elapsed_string(ELAPSED_FORMAT, Force);
  574.            max_strlen = ((strlen(lines[i].str) > max_strlen) ?
  575.                  strlen(lines[i].str) : max_strlen);    i++;
  576.       }
  577.      
  578.       if (defs.d_timeout && lock_flag && defs.timeout) {
  579.            lines[i] = default_line;
  580.            lines[i].name = float_name;
  581.            lines[i].str = timeleft_string(TIMELEFT_FORMAT, Force);
  582.            max_strlen = ((strlen(lines[i].str) > max_strlen) ?
  583.                  strlen(lines[i].str) : max_strlen);    i++;
  584.       }
  585.       if (*defs.lock_message) {
  586.            int num_lines;
  587.            char **msg_lines;
  588.            int a;
  589.  
  590.            if (max_strlen < 25)
  591.             max_strlen = 25;
  592.            msg_lines = breakup(defs.lock_message, max_strlen, &num_lines);
  593.            for (a = 0; (a < num_lines) && (i < MAXPROMPT); a++, i++) {
  594.             lines[i] = default_line;
  595.             if (a == 0)
  596.              lines[i].spread = 10;
  597.             lines[i].name = msg_name;
  598.             lines[i].str = msg_lines[a];
  599.            }
  600.       }
  601.       
  602.       return_widgets = (Widget *) malloc(sizeof(Widget) * i);
  603.       if (! return_widgets) {
  604.            perror(whoami);
  605.            exit(1);
  606.       }
  607.       float_widget = PromptBox(root_widget, "float", lines, i,
  608.                    return_widgets);            i = 0;
  609.       icon_w.widget = return_widgets[i];                i++;
  610.       if (defs.d_time) {
  611.            time_w.widget = return_widgets[i];            i++;
  612.       }
  613.       if (defs.d_elapsed) {
  614.            elapsed_w.widget = return_widgets[i];            i++;
  615.       }
  616.       if (defs.d_timeout && lock_flag && defs.timeout) {
  617.            timeout_w.widget = return_widgets[i];            i++;
  618.       }
  619.      }
  620. }
  621.      
  622.  
  623.  
  624.  
  625.  
  626. static char **breakup(str, max, num)
  627. String str;
  628. int max;
  629. int *num;
  630. {
  631.      char **foo;
  632.      int lines = 0;
  633.      char *ptr, *ptr2;
  634.      char temp;
  635.      
  636.      foo = (char **) malloc(0);
  637.  
  638.      ptr = str;
  639.      while (strlen(ptr) > max) {
  640.       lines++;
  641.       for (ptr2 = ptr + max; (ptr2 > ptr) && (*ptr2 != ' '); ptr2--);
  642.       if (ptr2 == ptr) {
  643.            temp = *(ptr + max);
  644.            *(ptr + max) = '\0';
  645.            ptr2 = ptr + max;
  646.       }
  647.       else {
  648.            temp = 0;
  649.            *ptr2 = '\0';
  650.            ptr2++;
  651.       }
  652.       foo = (char **) realloc(foo, sizeof(char *) * lines);
  653.       foo[lines - 1] = malloc(strlen(ptr) + 1);
  654.       strcpy(foo[lines - 1], ptr);
  655.       if (temp)
  656.            *ptr2 = temp;
  657.       ptr = ptr2;
  658.       
  659.      }
  660.      if (*ptr) {
  661.       lines++;
  662.       foo = (char **) realloc(foo, sizeof(char *) * lines);
  663.       foo[lines - 1] = malloc(strlen(ptr) + 1);
  664.       strcpy(foo[lines - 1], ptr);
  665.      }
  666.      *num = lines;
  667.      return(foo);
  668. }
  669.  
  670.  
  671.  
  672.  
  673. /* ARGSUSED */
  674. void RaiseRoot(w, event, params, num_params)
  675. Widget w;
  676. XEvent *event;
  677. String *params;
  678. Cardinal *num_params;
  679. {
  680.      XRaiseWindow(dpy, XtWindow(root_shell));
  681. }
  682.  
  683.  
  684.  
  685. /* ARGSUSED */
  686. void RemoveRoot(w, event, params, num_params)
  687. Widget w;
  688. XEvent *event;
  689. String *params;
  690. Cardinal *num_params;
  691. {
  692.  
  693.      unlock_command();
  694.      XtUnmapWidget(root_shell);
  695.      XUngrabPointer(dpy, CurrentTime);
  696.      XUngrabKeyboard(dpy, CurrentTime);
  697.      XSetScreenSaver(dpy, saver.timeout, saver.interval, saver.prefer_blanking,
  698.              saver.allow_exposures);
  699.      activated = False;
  700. }
  701.  
  702.  
  703.  
  704.  
  705. static void lock_command()
  706. {
  707.      if ((! lock_command_pid) && (*defs.lock_command)) {
  708.       if ((lock_command_pid = fork()) == -1) {
  709.            fprintf(stderr, "%s: Error forking to execute lock command!",
  710.                whoami);
  711.            lock_command_pid = 0;
  712.       }
  713.       else if (! lock_command_pid) {
  714.            setpgrp(getpid(), getpid());
  715.            XtCloseDisplay(dpy);
  716.            system(defs.lock_command);
  717.            exit(0);
  718.       }
  719.      }
  720. }
  721.  
  722.  
  723.  
  724.  
  725.  
  726. static void unlock_command()
  727. {
  728.      if (lock_command_pid) {
  729.       killpg(lock_command_pid, SIGKILL);
  730.       lock_command_pid = 0;
  731.      }
  732.      if (lock_flag && *defs.unlock_command) {
  733.       int pid;
  734.  
  735.       if ((pid = fork()) == -1)
  736.            fprintf(stderr,
  737.                "%s: Error forking to execute unlock command.\n",
  738.                whoami);
  739.       else if (! pid) {
  740.            XtCloseDisplay(dpy);
  741.            system(defs.unlock_command);
  742.            exit(0);
  743.       }
  744.      }
  745. }
  746.  
  747.  
  748.  
  749.