Howdy,

This is a patch against today's snapshot to add support for FvwmForm's
that time out after X number of seconds, and a display of how much time is
left in the form of a text string with a %% in it (the %% is replaced with
the number of seconds left).  The %% is not required, in case someone
might want to just say "This will time out in approximately 5 seconds."
and leave it at that.

Daniel

-- 
/\\\----------------------------------------------------------------------///\
\ \\\      Daniel Henninger           http://www.vorpalcloud.org/        /// /
 \_\\\      North Carolina State University - Systems Programmer        ///_/
    \\\                   Information Technology <IT>                  ///
     """--------------------------------------------------------------"""
diff -ur fvwm-snap-20020314.old/modules/ChangeLog 
fvwm-snap-20020314/modules/ChangeLog
--- fvwm-snap-20020314.old/modules/ChangeLog    Wed Mar 13 07:30:03 2002
+++ fvwm-snap-20020314/modules/ChangeLog        Thu Mar 14 17:39:31 2002
@@ -1,3 +1,51 @@
+2002-03-14  Daniel Henninger  <[EMAIL PROTECTED]>
+
+       * FvwmForm/FvwmForm.1:
+       Added TimeoutFont and Timeout description.
+
+       * FvwmForm/FvwmForm/QuitVerify:
+       Altered to show Timeout example.
+
+       * FvwmForm/FvwmForm.c (global):
+       Added timer global and prototype for TimerHandler.
+
+       * FvwmForm/FvwmForm.c (SetupTimer):
+       Added function.
+
+       * FvwmForm/FvwmForm.c (Command Table):
+       Added ct_Timeout and ct_TimeoutFont
+
+       * FvwmForm/FvwmForm.c (ct_TimeoutFont):
+       Added function.
+
+       * FvwmForm/FvwmForm.c (ct_Timeout):
+       Added function.
+
+       * FvwmForm/FvwmForm.c (CheckAlloc):
+       Added 'if no shadows needed' return for I_TIMEOUT.
+
+       * FvwmForm/FvwmForm.c (InitConstants):
+       Added default for f_timeout (3).
+
+       * FvwmForm/FvwmForm.c (RedrawFrame):
+       Added handling for I_TIMEOUT.
+
+       * FvwmForm/FvwmForm.c (RedrawTimeout):
+       Added function.
+
+       * FvwmForm/FvwmForm.c (TimerHandler):
+       Added function.
+
+       * FvwmForm/FvwmForm.c (main):
+       Added check for timer being set and call to SetupTimer if so.
+
+       * FvwmForm/FvwmForm.h:
+       Added TIMEOUT_COMMAND_EXPANSION, I_TIMEOUT.
+       Added timeout struct to item struct.
+       Added f_timeout to font_names.
+       Added prototype of RedrawTimeout.
+       
+
 2002-03-13  Dominik Vogt  <[EMAIL PROTECTED]>
 
        * FvwmWharf/icons.c (GetXPMData):
diff -ur fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm-QuitVerify 
fvwm-snap-20020314/modules/FvwmForm/FvwmForm-QuitVerify
--- fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm-QuitVerify Wed Nov  8 
16:11:57 2000
+++ fvwm-snap-20020314/modules/FvwmForm/FvwmForm-QuitVerify     Thu Mar 14 
17:24:59 2002
@@ -11,3 +11,5 @@
 *FvwmForm-QuitVerify: Command     Restart
 *FvwmForm-QuitVerify: Button      quit "Cancel" ^[
 *FvwmForm-QuitVerify: Command     Nop
+*FvwmForm-QuitVerify: Timeout     20 Quit "Automatic logout will occur in %% 
sec
+onds."
diff -ur fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm.1 
fvwm-snap-20020314/modules/FvwmForm/FvwmForm.1
--- fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm.1  Sat Oct 27 07:00:09 2001
+++ fvwm-snap-20020314/modules/FvwmForm/FvwmForm.1      Thu Mar 14 17:29:00 2002
@@ -12,7 +12,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH FvwmForm 1 "6 October 2001"
+.TH FvwmForm 1 "14 March 2002"
 .SH NAME
 FvwmForm - input form module for Fvwm
 .SH SYNOPSIS
@@ -37,6 +37,11 @@
 A text label only serves the purpose of explanation.
 It cannot accept any input.
 
+A timeout entry provides a mechanism for timing out the form
+and performing a certain action when the timeout occurs.  The countdown
+is displayed similar to a text label except that it updates with the
+amount of time left.
+
 A text input field can be used to edit a single-line string.
 FvwmForm accepts Emacs-style cursor movement keys.
 See FvwmFormInput for details.
@@ -126,6 +131,7 @@
   *FvwmFormDefault: Font 10x20
   *FvwmFormDefault: InputFont 8x13bold
   *FvwmFormDefault: ButtonFont 10x20
+  *FvwmFormDefault: TimeoutFont 10x20
   *FvwmFormDefault: Fore white
   *FvwmFormDefault: Back cornflowerblue
   *FvwmFormDefault: Colorset -1
@@ -218,6 +224,8 @@
 Position
 Selection
 Text
+Timeout
+TimeoutFont
 Title
 UseData
 WarpPointer
@@ -306,10 +314,14 @@
 Specifies the font for text in the action buttons.
 See DEFAULTS.
 .TP 4
-.B *FvwmForm: Inputfont \fIfont\fP
+.B *FvwmForm: InputFont \fIfont\fP
 Specifies the font for text input.  This font must have fixed width.
 See DEFAULTS.
 .TP 4
+.B *FvwmForm: TimeoutFont \fIfont\fP
+Specifies the font for display the timeout counter and related text.
+See DEFAULTS.
+.TP 4
 .B *FvwmForm: Line \fIjustification\fP
 Starts a new line.
 A line can contain any number of text, input, buttons and choice items.
@@ -560,6 +572,15 @@
 used while the pointer is over a text field.
 See DEFAULTS.
 
+.TP 4
+.B *FvwmForm: Timeout \fIseconds\fP \fIcommand\fP \fI"text"\fP
+Set up FvwmForm to time out after the amount of \fIseconds\fP
+specified.  When the timer hits zero, \fIcommand\fP executes.  The
+\fItext\fP field is displayed much like a \fIText\fP
+field, except that a '%%' in the line is replaced automatically by
+the amount of time left on the timer.  The value gets updated every
+second as the timer counts down.
+
 .SH EXAMPLES
 All of the following "examples" are installed in the
 read-only architecture-independent data directory,
@@ -576,7 +597,8 @@
 .EE
 .SH EXAMPLE 1 - Quit Verify
 This example simulates the mwm way of confirming logout.
-Return does the logout, Escape cancels logout.
+Return does the logout, Escape cancels logout.  It times out after 20
+seconds and performs the equivalent of the 'Logout' button.
 .EX
 DestroyModuleConfig  FvwmForm-QuitVerify: *
 *FvwmForm-QuitVerify: GrabServer
@@ -591,6 +613,7 @@
 *FvwmForm-QuitVerify: Command     Restart
 *FvwmForm-QuitVerify: Button      quit "Cancel" ^[
 *FvwmForm-QuitVerify: Command     Nop
+*FvwmForm-QuitVerify: Timeout     20 Quit "Automatic logout will occur in %% 
seconds."
 .EE
 
 .SH EXAMPLE 2 - Remote Login
diff -ur fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm.c 
fvwm-snap-20020314/modules/FvwmForm/FvwmForm.c
--- fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm.c  Wed Mar 13 07:30:04 2002
+++ fvwm-snap-20020314/modules/FvwmForm/FvwmForm.c      Thu Mar 14 17:40:58 2002
@@ -62,6 +62,7 @@
 char preload_yorn='n';           /* init to non-preload */
 Item *item;                             /* current during parse */
 Item *cur_sel, *cur_button;             /* current during parse */
+Item *timer = NULL;                    /* timeout tracking */
 Display *dpy;
 int fd_x;                  /* fd for X connection */
 Window root, ref;
@@ -72,7 +73,7 @@
   /* s = set by command (must be in "d" state for first "back" cmd to set it) 
*/
   /* u = used (color allocated, too late to accept "back") */
 char endDefaultsRead = 'n';
-char *font_names[3];
+char *font_names[4];
 char *screen_background_color;
 char *MyName;
 int MyNameLen;
@@ -94,6 +95,37 @@
 static void PutDataInForm(char *);
 static void ReadFormData();
 static void FormVarsCheck(char **);
+static RETSIGTYPE TimerHandler(int);
+
+static void SetupTimer()
+{
+#ifdef HAVE_SIGACTION
+  {
+    struct sigaction  sigact;
+
+#ifdef SA_INTERRUPT
+    sigact.sa_flags = SA_INTERRUPT;
+#else
+    sigact.sa_flags = 0;
+#endif
+    sigemptyset(&sigact.sa_mask);
+    sigaddset(&sigact.sa_mask, SIGALRM);
+    sigact.sa_handler = TimerHandler;
+
+    sigaction(SIGALRM, &sigact, NULL);
+  }
+#else
+#ifdef USE_BSD_SIGNALS
+  fvwmSetSignalMask( sigmask(SIGALRM) );
+#endif
+  signal(SIGALRM, TimerHandler);  /* Dead pipe == Fvwm died */
+#ifdef HAVE_SIGINTERRUPT
+  siginterrupt(SIGALRM, 1);
+#endif
+#endif
+
+  alarm(1);
+}
 
 /* copy a string until '"', or '\n', or '\0' */
 static char *CopyQuotedString (char *cp)
@@ -173,6 +205,8 @@
 static void ct_InputPointer(char *);
 static void ct_InputPointerBack(char *);
 static void ct_InputPointerFore(char *);
+static void ct_Timeout(char *);
+static void ct_TimeoutFont(char *);
 static void ct_Title(char *);
 static void ct_UseData(char *);
 static void ct_padVText(char *);
@@ -214,6 +248,8 @@
   {"Position",ct_Position},
   {"Selection",ct_Selection},
   {"Text",ct_Text},
+  {"Timeout",ct_Timeout},
+  {"TimeoutFont",ct_TimeoutFont},
   {"Title",ct_Title},
   {"UseData",ct_UseData},
   {"WarpPointer",ct_WarpPointer}
@@ -241,7 +277,8 @@
   {"ItemBack",ct_ItemBack},
   {"ItemColorset",ct_ItemColorset},
   {"ItemFore",ct_ItemFore},
-  {"Read",ct_Read}
+  {"Read",ct_Read},
+  {"TimeoutFont",ct_TimeoutFont}
 };
 
 /* If there were vars on the command line, do env var sustitution on
@@ -497,6 +534,13 @@
   font_names[f_text] = safestrdup(cp);
   myfprintf((stderr, "Font: %s\n", font_names[f_text]));
 }
+static void ct_TimeoutFont(char *cp)
+{
+  if (font_names[f_timeout])
+    free(font_names[f_timeout]);
+  font_names[f_timeout] = safestrdup(cp);
+  myfprintf((stderr, "TimeoutFont: %s\n", font_names[f_timeout]));
+}
 static void ct_ButtonFont(char *cp)
 {
   if (font_names[f_button])
@@ -650,6 +694,9 @@
   if (this_item->type == I_TEXT) {      /* If no shadows needed */
     return;
   }
+  if (this_item->type == I_TIMEOUT) {      /* If no shadows needed */
+    return;
+  }
   dt->dt_colors[c_item_fg] = (itemcolorset < 0)
     ? GetColor(dt->dt_color_names[c_item_fg])
     : Colorset[itemcolorset].fg;
@@ -697,6 +744,8 @@
   match_item_back = color_names[c_item_bg];
   if (adt_item->type == I_TEXT) {
     match_font = font_names[f_text];
+  } else if (adt_item->type == I_TIMEOUT) {
+    match_font = font_names[f_timeout];
   } else if (adt_item->type == I_INPUT) {
     match_font = font_names[f_input];
   } else {
@@ -795,6 +844,69 @@
     CF.title = "";
   myfprintf((stderr, "Title \"%s\"\n", CF.title));
 }
+static void ct_Timeout(char *cp)
+{
+  char *tmpcp, *tmpbuf;
+
+  if (timer != NULL) {
+    /* Sorry, only one timer please. */
+    return;
+  }
+
+  /* syntax: *FFTimeout seconds <Command> "Text" */
+  AddItem();
+  bg_state = 'u';                       /* indicate b/g color now used. */
+  item->type = I_TIMEOUT;
+  /* Item now added to list of items, now it needs a pointer
+     to the correct DrawTable. */
+  AssignDrawTable(item);
+  item->header.name = "";
+
+  item->timeout.timeleft = atoi(cp);
+  if (item->timeout.timeleft < 0)
+  {
+    item->timeout.timeleft = 0;
+  }
+  else if (item->timeout.timeleft > 99999)
+  {
+    item->timeout.timeleft = 99999;
+  }
+  timer = item;
+
+  while (!isspace((unsigned char)*cp)) cp++;
+  while (isspace((unsigned char)*cp)) cp++;
+
+  tmpbuf = safestrdup(cp);
+  tmpcp = tmpbuf; while (!isspace((unsigned char)*tmpcp)) tmpcp++;
+  *tmpcp = '\0';
+  item->timeout.timeout_array_size += TIMEOUT_COMMAND_EXPANSION;
+  item->timeout.commands =
+    (char **)saferealloc((void *)item->timeout.commands,
+                          sizeof(char *) *
+                          item->timeout.timeout_array_size);
+  item->timeout.commands[item->timeout.numcommands++] = safestrdup(tmpbuf);
+  free(tmpbuf);
+
+  while (!isspace((unsigned char)*cp)) cp++;
+  while (isspace((unsigned char)*cp)) cp++;
+
+  if (*cp == '\"') {
+    item->timeout.text = CopyQuotedString(++cp);
+    cp += strlen(item->timeout.text) + 1;
+    while (isspace((unsigned char)*cp)) cp++;
+  } else
+    item->timeout.text = "";
+  item->timeout.len = strlen(item->timeout.text);
+
+  item->header.size_x = FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
+                                   item->timeout.text,
+                                   item->timeout.len) + 2 * TEXT_SPC;
+  item->header.size_y = item->header.dt_ptr->dt_Ffont->height
+     + CF.padVText;
+  myfprintf((stderr, "Timeout %d \"%s\" [%d, %d]\n", item->timeout.timeleft,
+               item->timeout.text, item->header.size_x, item->header.size_y));
+  AddToLine(item);
+}
 static void ct_padVText(char *cp)
 {
   /* syntax: *FFText "<padVText pixels>" */
@@ -1115,6 +1227,7 @@
   font_names[0]=safestrdup("8x13bold");
   font_names[1]=safestrdup("8x13bold");
   font_names[2]=safestrdup("8x13bold");
+  font_names[3]=safestrdup("8x13bold");
   screen_background_color=safestrdup("Light Gray");
   CF.p_c[input_fore].pointer_color.pixel = WhitePixel(dpy, screen);
   CF.p_c[input_back].pointer_color.pixel = BlackPixel(dpy, screen);
@@ -1365,6 +1478,9 @@
     case I_TEXT:
       RedrawText(item);
       break;
+    case I_TIMEOUT:
+      RedrawTimeout(item);
+      break;
     case I_CHOICE:
       item->header.dt_ptr->dt_Fstr->win = CF.frame;
       item->header.dt_ptr->dt_Fstr->gc  = item->header.dt_ptr->dt_GC;
@@ -1403,6 +1519,60 @@
   return;
 }
 
+void RedrawTimeout(Item *item)
+{
+  char *p;
+  char *tmpbuf, *tmpptr, *tmpbptr;
+  int reallen;
+
+  XClearArea(dpy, CF.frame,
+               item->header.pos_x, item->header.pos_y,
+               item->header.size_x, item->header.size_y,
+               False);
+
+  tmpbuf = safemalloc(item->timeout.len + 6);
+  tmpbptr = tmpbuf;
+  for (tmpptr = item->timeout.text; *tmpptr != '\0' &&
+               !(tmpptr[0] == '%' && tmpptr[1] == '%'); tmpptr++) {
+    *tmpbptr = *tmpptr;
+    tmpbptr++;
+  }
+  if (tmpptr[0] == '%') {
+    tmpptr++; tmpptr++;
+    sprintf(tmpbptr, "%d", item->timeout.timeleft);
+    tmpbptr += strlen(tmpbptr);
+  }
+  for (; *tmpptr != '\0'; tmpptr++) {
+    *tmpbptr = *tmpptr;
+    tmpbptr++;
+  }
+  *tmpbptr = '\0';
+  
+  reallen = strlen(tmpbuf);
+  item->header.size_x = FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
+                                   tmpbuf, reallen) + 2 * TEXT_SPC;
+  item->header.size_y = item->header.dt_ptr->dt_Ffont->height + CF.padVText;
+
+  CheckAlloc(item,item->header.dt_ptr); /* alloc colors and fonts needed */
+  item->header.dt_ptr->dt_Fstr->len = reallen;
+  if ((p = memchr(item->timeout.text, '\0', item->header.dt_ptr->dt_Fstr->len))
+      != NULL)
+    item->header.dt_ptr->dt_Fstr->len = p - tmpbuf;
+  item->header.dt_ptr->dt_Fstr->win = CF.frame;
+  item->header.dt_ptr->dt_Fstr->gc  = item->header.dt_ptr->dt_GC;
+  if (item->header.dt_ptr->dt_Fstr->str != NULL)
+    free(item->header.dt_ptr->dt_Fstr->str);
+  item->header.dt_ptr->dt_Fstr->str = safestrdup(tmpbuf);
+  item->header.dt_ptr->dt_Fstr->x   = item->header.pos_x + TEXT_SPC;
+  item->header.dt_ptr->dt_Fstr->y   = item->header.pos_y + ( CF.padVText / 2 ) 
+
+    item->header.dt_ptr->dt_Ffont->ascent;
+  FlocaleDrawString(dpy,
+                    item->header.dt_ptr->dt_Ffont,
+                    item->header.dt_ptr->dt_Fstr, FWS_HAVE_LENGTH);
+  free(tmpbuf);
+  return;
+}
+
 /* redraw an item */
 void RedrawItem (Item *item, int click)
 {
@@ -2100,6 +2270,63 @@
   fvwmSetTerminate(sig);
 }
 
+/* signal-handler to make the timer work */
+static RETSIGTYPE
+TimerHandler(int sig)
+{
+  int k, dn;
+  char *sp;
+
+  timer->timeout.timeleft--;
+  if (timer->timeout.timeleft <= 0) {
+    /* pre-command */
+    if (!XWithdrawWindow(dpy, CF.frame, screen))
+    {
+      /* hm, what can we do now? just ignore this situation. */
+    }
+
+    for (k = 0; k < timer->timeout.numcommands; k++) {
+      char *parsed_command;
+      /* construct command */
+      parsed_command = ParseCommand(0, timer->timeout.commands[k], '\0', &dn, 
&sp);
+      myfprintf((stderr, "Final command[%d]: [%s]\n", k, parsed_command));
+
+      /* send command */
+      if ( parsed_command[0] == '!') {    /* If command starts with ! */
+        system(parsed_command+1);         /* Need synchronous execution */
+      } else {
+        SendText(Channel,parsed_command, ref);
+      }
+    }
+
+    /* post-command */
+    if (CF.last_error) {                  /* if form has last_error field */
+      memset(CF.last_error->text.value, ' ', CF.last_error->text.n); /* clear 
*/
+      /* To do this more elegantly, the window resize logic should recalculate
+         size_x for the Message as the window resizes.  Right now, just clear
+         a nice wide area. dje */
+      XClearArea(dpy,CF.frame,
+                 CF.last_error->header.pos_x,
+                 CF.last_error->header.pos_y,
+                 /* CF.last_error->header.size_x, */
+                 2000,
+                 CF.last_error->header.size_y, False);
+    } /* end form has last_error field */
+    if (CF.grab_server)
+      XUngrabServer(dpy);
+    /* This is a temporary bug workaround for the pipe drainage problem */
+    SendQuitNotification(Channel);    /* let commands complete */
+    /* Note how the window is withdrawn, but execution continues until
+       the quit notifcation catches up with this module...
+       Should not be a problem, there shouldn't be any more commands
+       coming into FvwmForm.  dje */
+  }
+  else {
+    RedrawTimeout(timer);
+    alarm(1);
+  }
+}
+
 
 /* main procedure */
 int main (int argc, char **argv)
@@ -2225,6 +2452,9 @@
   SetMessageMask(Channel, MX_PROPERTY_CHANGE);
   OpenWindows();                        /* create initial window */
   SendFinishedStartupNotification(Channel);/* tell fvwm we're running */
+  if (timer != NULL) {
+     SetupTimer();
+  }
   MainLoop();                           /* start */
 
   return 0;                             /* */
diff -ur fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm.h 
fvwm-snap-20020314/modules/FvwmForm/FvwmForm.h
--- fvwm-snap-20020314.old/modules/FvwmForm/FvwmForm.h  Tue Feb 12 07:30:03 2002
+++ fvwm-snap-20020314/modules/FvwmForm/FvwmForm.h      Thu Mar 14 17:03:27 2002
@@ -44,12 +44,14 @@
 #define ITEMS_PER_EXPANSION 32
 #define CHOICES_PER_SEL_EXPANSION 8
 #define BUTTON_COMMAND_EXPANSION 8
+#define TIMEOUT_COMMAND_EXPANSION 8
 
 #define I_TEXT          1
 #define I_INPUT         2
 #define I_SELECT        3
 #define I_CHOICE        4
 #define I_BUTTON        5
+#define I_TIMEOUT       6
 
 #define IS_SINGLE       1
 #define IS_MULTIPLE     2
@@ -138,6 +140,15 @@
     int button_array_size;              /* current size of next array */
     char **commands;    /* Fvwm command to execute */
   } button;
+  struct {
+    struct _head head;
+    int timeleft;       /* seconds left on timer */
+    int len;            /* text length */
+    char *text;         /* text string */
+    int numcommands;   /* # of commands */
+    int timeout_array_size;  /* current size of next array */
+    char **commands;    /* Fvwm command(s) to execute */
+  } timeout;
 } Item;
 
 #define L_LEFT        1
@@ -224,8 +235,8 @@
 extern char *color_names[4];
 extern char bg_state;
 extern char endDefaultsRead;
-enum { f_text, f_input, f_button };
-extern char *font_names[3];
+enum { f_text, f_input, f_button, f_timeout };
+extern char *font_names[4];
 extern char *screen_background_color;
 
 extern int colorset;
@@ -255,6 +266,7 @@
 /* prototypes */
 void ReadXServer();                     /* ReadXServer.c */
 void RedrawText(Item *item);            /* FvwmForm.c */
+void RedrawTimeout(Item *item);         /* FvwmForm.c */
 void RedrawItem (Item *item, int click); /* FvwmForm.c */
 void UpdateRootTransapency(void);        /* FvwmForm.c */
 void DoCommand (Item *cmd);             /* FvwmForm.c */

Reply via email to