r382 - in trunk: . scripts
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Wed Dec 5 02:26:19 EST 2007
Author: icculus
Date: 2007-12-05 02:26:19 -0500 (Wed, 05 Dec 2007)
New Revision: 382
Modified:
trunk/gui_stdio.c
trunk/scripts/localization.lua
Log:
Bunch of work on the stdio UI: paging of READMEs, default values on promptyn
and promptynan, other tweaks.
Modified: trunk/gui_stdio.c
===================================================================
--- trunk/gui_stdio.c 2007-11-24 17:28:23 UTC (rev 381)
+++ trunk/gui_stdio.c 2007-12-05 07:26:19 UTC (rev 382)
@@ -41,6 +41,10 @@
static int readstr(const char *prompt, char *buf, int len,
boolean back, boolean fwd)
{
+ // !!! FIXME: if read_stdin() returns -1, we return 0, which makes it
+ // !!! FIXME: indistinguishable from "user hit enter" ... maybe we should
+ // !!! FIXME: abort in read_stdin() if i/o fails?
+
int retval = 0;
const char *backstr = NULL;
@@ -65,13 +69,13 @@
if ((retval = read_stdin(buf, len)) >= 0)
{
- if ((back) && (strcmp(buf, backstr) == 0))
+ if ((back) && (strcmp(buf, backstr) == 0)) // !!! FIXME: utf8casecmp?
retval = -1;
} // if
free((void *) backstr);
return retval;
-} // print_prompt
+} // readstr
static uint8 MojoGui_stdio_priority(boolean istty)
@@ -119,25 +123,37 @@
boolean retval = false;
if (!feof(stdin))
{
+ const char *fmt = ((defval) ? "%s\n[Y/n]: " : "%s\n[y/N]: ");
+ const char *localized_fmt = entry->xstrdup(entry->_(fmt));
const char *localized_no = entry->xstrdup(entry->_("N"));
const char *localized_yes = entry->xstrdup(entry->_("Y"));
boolean getout = false;
char buf[128];
+
while (!getout)
{
- // !!! FIXME:
- // We currently ignore defval and make you type out your choice.
- printf(entry->_("%s\n[y/n]: "), text);
+ int rc = 0;
+
+ getout = true; // we may reset this later.
+ printf(localized_fmt, text);
fflush(stdout);
- if (read_stdin(buf, sizeof (buf)) < 0)
- getout = true;
+ rc = read_stdin(buf, sizeof (buf));
+
+ if (rc < 0)
+ retval = false;
+ else if (rc == 0)
+ retval = defval;
else if (strcasecmp(buf, localized_no) == 0)
- getout = true;
+ retval = false;
else if (strcasecmp(buf, localized_yes) == 0)
- retval = getout = true;
+ retval = true;
+ else
+ getout = false; // try again.
} // while
+
+ free((void *) localized_yes);
free((void *) localized_no);
- free((void *) localized_yes);
+ free((void *) localized_fmt);
} // if
return retval;
@@ -150,42 +166,44 @@
MojoGuiYNAN retval = MOJOGUI_NO;
if (!feof(stdin))
{
+ const char *localized_fmt = entry->_("%s\n[y/n/Always/Never]: ");
const char *localized_no = entry->xstrdup(entry->_("N"));
const char *localized_yes = entry->xstrdup(entry->_("Y"));
const char *localized_always = entry->xstrdup(entry->_("Always"));
const char *localized_never = entry->xstrdup(entry->_("Never"));
boolean getout = false;
char buf[128];
+
while (!getout)
{
- // !!! FIXME:
- // We currently ignore defval and make you type out your choice.
- printf(entry->_("%s\n[y/n/Always/Never]: "), txt);
+ int rc = 0;
+
+ getout = true; // we may reset this later.
+ printf(localized_fmt, txt);
fflush(stdout);
- if (read_stdin(buf, sizeof (buf)) < 0)
- getout = true;
+ rc = read_stdin(buf, sizeof (buf));
+
+ if (rc < 0)
+ retval = MOJOGUI_NO;
+ else if (rc == 0)
+ retval = (defval) ? MOJOGUI_YES : MOJOGUI_NO;
else if (strcasecmp(buf, localized_no) == 0)
- getout = true;
+ retval = MOJOGUI_NO;
else if (strcasecmp(buf, localized_yes) == 0)
- {
retval = MOJOGUI_YES;
- getout = true;
- } // else if
else if (strcasecmp(buf, localized_always) == 0)
- {
retval = MOJOGUI_ALWAYS;
- getout = true;
- } // else if
else if (strcasecmp(buf, localized_never) == 0)
- {
retval = MOJOGUI_NEVER;
- getout = true;
- } // else if
+ else
+ getout = false; // try again.
} // while
+
+ free((void *) localized_never);
+ free((void *) localized_always);
+ free((void *) localized_yes);
free((void *) localized_no);
- free((void *) localized_yes);
- free((void *) localized_always);
- free((void *) localized_never);
+ free((void *) localized_fmt);
} // if
return retval;
@@ -206,27 +224,175 @@
} // MojoGui_stdio_stop
-static int MojoGui_stdio_readme(const char *name, const uint8 *data,
- size_t datalen, boolean can_back,
- boolean can_fwd)
+// !!! FIXME: cut and pasted in gui_ncurses.c, too...fix bugs in both copies!
+// !!! FIXME: (or move this somewhere else...)
+// !!! FIXME: this is not really Unicode friendly...
+static char **splitText(const char *_text, int *_count, int *_w)
{
+ char *ptr = entry->xstrdup(_text);
+ char *text = ptr;
+ int i;
+ int scrw = 80;
+ char **retval = NULL;
+ int count = 0;
+ int w = 0;
+
+ *_count = *_w = 0;
+ while (*text)
+ {
+ int pos = 0;
+ int furthest = 0;
+
+ for (i = 0; (text[i]) && (i < (scrw-4)); i++)
+ {
+ const int ch = text[i];
+ if ((ch == '\r') || (ch == '\n'))
+ {
+ count++;
+ retval = (char **) entry->xrealloc(retval,
+ count * sizeof (char *));
+ text[i] = '\0';
+ retval[count-1] = entry->xstrdup(text);
+ text += i;
+ *text = ch;
+ if ((ch == '\r') && (text[1] == '\n'))
+ text++;
+ text++;
+
+ if (i > w)
+ w = i;
+ i = -1; // will be zero on next iteration...
+ } // if
+ else if (isspace(ch))
+ {
+ furthest = i;
+ } // else if
+ } // for
+
+ // line overflow or end of stream...
+ pos = (text[i]) ? furthest : i;
+ if ((text[i]) && (furthest == 0)) // uhoh, no split at all...hack it.
+ {
+ // !!! FIXME: might be chopping in the middle of a UTF-8 seq.
+ pos = strlen(text);
+ if (pos > scrw-4)
+ pos = scrw-4;
+ } // if
+
+ if (pos > 0)
+ {
+ char ch = text[pos];
+ count++;
+ retval = (char **) entry->xrealloc(retval, count * sizeof (char*));
+ text[pos] = '\0';
+ retval[count-1] = entry->xstrdup(text);
+ text += pos;
+ *text = ch;
+ if (pos > w)
+ w = pos;
+ } // if
+ } // while
+
+ free(ptr);
+ *_count = count;
+ *_w = w;
+ return retval;
+} // splitText
+
+
+static void dumb_pager(const char *name, const char *data, size_t datalen)
+{
+ const int MAX_PAGE_LINES = 21;
+ char buf[256];
+ const char *_fmt = entry->_("(%d-%d of %d lines, see more?)"); // !!! FIXME: localization
+ char *fmt = entry->xstrdup(_fmt);
+ int i = 0;
+ int w = 0;
+ int linecount = 0;
boolean getout = false;
- int retval = -1;
- int len = 0;
- char buf[128];
+ char **lines = splitText(data, &linecount, &w);
- while (!getout)
+ assert(linecount >= 0);
+
+ printf("%s\n", name);
+
+ if (lines == NULL) // failed to parse?!
+ printf("%s\n", data); // just dump it all. Oh well.
+ else
{
- printf("%s\n%s\n", name, (const char *) data);
- if ((len = readstr(NULL, buf, sizeof (buf), can_back, true)) < 0)
- getout = true;
- else if (len == 0)
+ int printed = 0;
+ do
{
- getout = true;
- retval = 1;
- } // else if
+ for (i = 0; (i < MAX_PAGE_LINES) && (printed < linecount); i++)
+ printf("%s\n", lines[printed++]);
+
+ if (printed >= linecount)
+ getout = true;
+ else
+ {
+ printf("\n");
+ snprintf(buf, sizeof (buf), fmt,
+ (printed-i)+1, printed, linecount);
+ getout = !MojoGui_stdio_promptyn("", buf, true);
+ printf("\n");
+ } // else
+ } while (!getout);
} // while
+ for (i = 0; i < linecount; i++)
+ free(lines[i]);
+ free(lines);
+ free(fmt);
+} // dumb_pager
+
+
+static int MojoGui_stdio_readme(const char *name, const uint8 *_data,
+ size_t datalen, boolean can_back,
+ boolean can_fwd)
+{
+ const char *data = (const char *) _data;
+ char buf[256];
+ int retval = -1;
+ boolean failed = true;
+
+ #if PLATFORM_UNIX
+ const size_t namelen = strlen(name);
+ const char *programs[] = { getenv("PAGER"), "more", "less -M", "less" };
+ int i = 0;
+
+ // flush streams, so output doesn't mingle with the popen()'d process.
+ fflush(stdout);
+ fflush(stderr);
+
+ for (i = 0; i < STATICARRAYLEN(programs); i++)
+ {
+ const char *cmd = programs[i];
+ if (cmd != NULL)
+ {
+ FILE *io = popen(cmd, "w");
+ if (io != NULL)
+ {
+ failed = false;
+ if (!failed) failed = (fwrite("\n", 1, 1, io) != 1);
+ if (!failed) failed = (fwrite(name, namelen, 1, io) != 1);
+ if (!failed) failed = (fwrite("\n", 1, 1, io) != 1);
+ if (!failed) failed = (fwrite(data, datalen, 1, io) != 1);
+ if (!failed) failed = (fwrite("\n", 1, 1, io) != 1);
+ failed |= (pclose(io) != 0); // call whether we failed or not.
+ if (!failed)
+ break; // it worked, we're done!
+ } // if
+ } // if
+ } // for
+ #endif // PLATFORM_UNIX
+
+ if (failed) // We're not Unix, or none of the pagers worked?
+ dumb_pager(name, data, datalen);
+
+ // Put up the "hit enter to continue (or 'back' to go back)" prompt.
+ if (readstr(NULL, buf, sizeof (buf), can_back, true) >= 0)
+ retval = 1;
+
return retval;
} // MojoGui_stdio_readme
Modified: trunk/scripts/localization.lua
===================================================================
--- trunk/scripts/localization.lua 2007-11-24 17:28:23 UTC (rev 381)
+++ trunk/scripts/localization.lua 2007-12-05 07:26:19 UTC (rev 382)
@@ -45,10 +45,14 @@
["NOTICE: %s\n[hit enter]"] = {
};
- -- stdio GUI plugin says this for yes/no prompts (printf format string).
- ["%s\n[y/n]"] = {
+ -- stdio GUI plugin says this for yes/no prompts that default to yes (printf format string).
+ ["%s\n[Y/n]: "] = {
};
+ -- stdio GUI plugin says this for yes/no prompts that default to no (printf format string).
+ ["%s\n[y/N]: "] = {
+ };
+
-- stdio GUI plugin says this for yes/no/always/never prompts (printf format string).
["%s\n[y/n/Always/Never]: "] = {
};
@@ -61,6 +65,10 @@
["N"] = {
};
+ -- This is shown when using stdio GUI's built-in README pager (printf format).
+ ["(Viewing %d-%d of %d lines, see more?)"] = {
+ };
+
-- This is utf8casecmp()'d for "always" answers in stdio GUI's promptyn().
["Always"] = {
};
More information about the mojosetup-commits
mailing list