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 */