r295 - in trunk: . scripts
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sun May 20 05:01:30 EDT 2007
Author: icculus
Date: 2007-05-20 05:01:30 -0400 (Sun, 20 May 2007)
New Revision: 295
Modified:
trunk/gui_ncurses.c
trunk/gui_stdio.c
trunk/scripts/localization.lua
Log:
Bunch More Work on the ncurses UI...lots of fixes and tweaks, and a working
Options page.
Modified: trunk/gui_ncurses.c
===================================================================
--- trunk/gui_ncurses.c 2007-05-20 08:14:11 UTC (rev 294)
+++ trunk/gui_ncurses.c 2007-05-20 09:01:30 UTC (rev 295)
@@ -31,7 +31,8 @@
//
// ncurses is almost always installed as a shared library, though, so we'll
// just talk to it directly. Fortunately we don't need much of what dialog(1)
-// offers, so rolling our own isn't too painful.
+// offers, so rolling our own isn't too painful (well, compared to massive
+// head trauma, I guess).
//
// Pradeep Padala's ncurses HOWTO was very helpful in teaching me curses
// quickly: http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/index.html
@@ -74,6 +75,11 @@
} MojoBox;
+static char *lastComponent = NULL;
+static uint32 percentTicks = 0;
+static char *title = NULL;
+
+
// !!! FIXME: this is not really Unicode friendly...
static char **splitText(char *text, int *_count, int *_w)
{
@@ -182,6 +188,18 @@
} // drawText
+static void drawBackground(WINDOW *win)
+{
+ wclear(win);
+ if (title != NULL)
+ {
+ wattron(win, COLOR_PAIR(MOJOCOLOR_BACKGROUND) | A_BOLD);
+ mvwaddstr(win, 0, 0, title);
+ wattroff(win, COLOR_PAIR(MOJOCOLOR_BACKGROUND) | A_BOLD);
+ } // if
+} // drawBackground
+
+
static MojoBox *makeBox(const char *title, const char *text,
char **buttons, int bcount,
boolean ndelay, boolean hidecursor)
@@ -197,7 +215,8 @@
int i;
getmaxyx(stdscr, scrh, scrw);
- if (scrw < 16)
+ scrh--; // -1 to save the title at the top of the screen...
+ if ((scrw < 16) || (scrh < 16))
return NULL;
retval = (MojoBox *) entry->xmalloc(sizeof (MojoBox));
@@ -242,7 +261,7 @@
if (h > scrh)
h = scrh;
- win = retval->mainwin = newwin(h, w, (scrh - h) / 2, (scrw - w) / 2);
+ win = retval->mainwin = newwin(h, w, ((scrh - h) / 2)+1, (scrw - w) / 2);
keypad(win, TRUE);
nodelay(win, ndelay);
wbkgdset(win, COLOR_PAIR(MOJOCOLOR_TEXT));
@@ -270,7 +289,7 @@
if (bcount > 0)
{
- const int buttony = (((scrh - h) / 2) + h)-2;
+ const int buttony = (((scrh - h) / 2) + h)-1;
int buttonx = (((scrw - w) / 2) + w) - ((w - buttonsw) / 2);
wmove(win, h-3, 1);
whline(win, ACS_HLINE | A_BOLD | COLOR_PAIR(MOJOCOLOR_BORDERTOP), w-2);
@@ -279,7 +298,6 @@
len = strcells(buttons[i]) + 4;
buttonx -= len+1;
win = retval->buttons[i] = newwin(1, len, buttony, buttonx);
- buttonx -= 1;
keypad(win, TRUE);
nodelay(win, ndelay);
} // for
@@ -288,13 +306,13 @@
texth = h-2;
if (bcount > 0)
texth -= 2;
- win = retval->textwin = newwin(texth, w-4, ((scrh-h)/2)+1, ((scrw-w)/2)+2);
+ win = retval->textwin = newwin(texth, w-4, ((scrh-h)/2)+2, ((scrw-w)/2)+2);
keypad(win, TRUE);
nodelay(win, ndelay);
wbkgdset(win, COLOR_PAIR(MOJOCOLOR_TEXT));
drawText(retval);
- wclear(stdscr);
+ drawBackground(stdscr);
wrefresh(stdscr);
wrefresh(retval->mainwin);
wrefresh(retval->textwin);
@@ -357,14 +375,16 @@
if (mojobox == NULL)
return -2;
+ if (justResized) // !!! FIXME: this is a kludge.
+ {
+ justResized = false;
+ if (ch == ERR)
+ return -1;
+ } // if
+
switch (ch)
{
case ERR:
- if (justResized) // !!! FIXME: this is a kludge.
- {
- justResized = false;
- return -1;
- } // if
return -2;
case '\r':
@@ -448,15 +468,16 @@
return -1;
case KEY_RESIZE:
- justResized = true; // !!! FIXME: kludge.
mojobox = makeBox(mojobox->title, mojobox->text,
mojobox->buttontext, mojobox->buttoncount,
mojobox->ndelay, mojobox->hidecursor);
mojobox->cursval = (*_mojobox)->cursval; // keep this sane.
+ mojobox->hoverover = (*_mojobox)->hoverover;
freeBox(*_mojobox, false);
if (mojobox->hidecursor)
curs_set(0); // make sure this stays sane.
*_mojobox = mojobox;
+ justResized = true; // !!! FIXME: kludge.
return -1;
} // switch
@@ -464,9 +485,6 @@
} // upkeepBox
-static char *lastComponent = NULL;
-static uint32 percentTicks = 0;
-
static uint8 MojoGui_ncurses_priority(void)
{
if (getenv("DISPLAY") != NULL)
@@ -498,15 +516,15 @@
cbreak();
keypad(stdscr, TRUE);
noecho();
- //nodelay(stdscr, TRUE);
start_color();
- init_pair(MOJOCOLOR_BACKGROUND, COLOR_BLUE, COLOR_BLUE);
+ init_pair(MOJOCOLOR_BACKGROUND, COLOR_CYAN, COLOR_BLUE);
init_pair(MOJOCOLOR_BORDERTOP, COLOR_WHITE, COLOR_WHITE);
init_pair(MOJOCOLOR_BORDERBOTTOM, COLOR_BLACK, COLOR_WHITE);
init_pair(MOJOCOLOR_BORDERSHADOW, COLOR_BLACK, COLOR_BLACK);
init_pair(MOJOCOLOR_TEXT, COLOR_BLACK, COLOR_WHITE);
init_pair(MOJOCOLOR_BUTTONHOVER, COLOR_WHITE, COLOR_BLUE);
init_pair(MOJOCOLOR_BUTTONNORMAL, COLOR_BLACK, COLOR_WHITE);
+
wbkgdset(stdscr, COLOR_PAIR(MOJOCOLOR_BACKGROUND));
wclear(stdscr);
wrefresh(stdscr);
@@ -521,6 +539,8 @@
endwin();
delwin(stdscr); // not sure if this is safe, but valgrind said it leaks.
stdscr = NULL;
+ free(title);
+ title = NULL;
free(lastComponent);
lastComponent = NULL;
} // MojoGui_ncurses_deinit
@@ -581,9 +601,11 @@
} // MojoGui_ncurses_promptynan
-static boolean MojoGui_ncurses_start(const char *title, const char *splash)
+static boolean MojoGui_ncurses_start(const char *_title, const char *splash)
{
- wclear(stdscr);
+ free(title);
+ title = entry->xstrdup(_title);
+ drawBackground(stdscr);
wrefresh(stdscr);
return true;
} // MojoGui_ncurses_start
@@ -591,7 +613,9 @@
static void MojoGui_ncurses_stop(void)
{
- wclear(stdscr);
+ free(title);
+ title = NULL;
+ drawBackground(stdscr);
wrefresh(stdscr);
} // MojoGui_ncurses_stop
@@ -638,10 +662,287 @@
} // MojoGui_ncurses_readme
+static int toggle_option(MojoGuiSetupOptions *parent,
+ MojoGuiSetupOptions *opts, int *line, int target)
+{
+ int rc = -1;
+ if ((opts != NULL) && (target > *line))
+ {
+ if (++(*line) == target)
+ {
+ const boolean toggled = ((opts->value) ? false : true);
+
+ if (opts->is_group_parent)
+ return 0;
+
+ // "radio buttons" in a group?
+ if ((parent) && (parent->is_group_parent))
+ {
+ if (toggled) // drop unless we weren't the current toggle.
+ {
+ // set all siblings to false...
+ MojoGuiSetupOptions *i = parent->child;
+ while (i != NULL)
+ {
+ i->value = false;
+ i = i->next_sibling;
+ } // while
+ opts->value = true; // reset us to be true.
+ } // if
+ } // if
+
+ else // individual "check box" was chosen.
+ {
+ opts->value = toggled;
+ } // else
+
+ return 1; // we found it, bail.
+ } // if
+
+ if (opts->value) // if option is toggled on, descend to children.
+ rc = toggle_option(opts, opts->child, line, target);
+ if (rc == -1)
+ rc = toggle_option(parent, opts->next_sibling, line, target);
+ } // if
+
+ return rc;
+} // toggle_option
+
+
+// This code is pretty scary.
+static void build_options(MojoGuiSetupOptions *opts, int *line, int level,
+ int maxw, char **lines)
+{
+ if (opts != NULL)
+ {
+ char *spacebuf = (char *) entry->xmalloc(maxw+1);
+ char *buf = (char *) entry->xmalloc(maxw+1);
+ int len = 0;
+ int spacing = 1+level;
+
+ if (spacing > (maxw-5))
+ spacing = 0; // oh well.
+
+ if (spacing > 0)
+ memset(spacebuf, ' ', spacing); // null-term'd by xmalloc().
+
+ if (opts->is_group_parent)
+ len = snprintf(buf, maxw-2, "%s%s", spacebuf, opts->description);
+ else
+ {
+ (*line)++;
+ len = snprintf(buf, maxw-2, "%s[%c] %s", spacebuf,
+ opts->value ? 'X' : ' ',
+ opts->description);
+ } // else
+
+ free(spacebuf);
+
+ if (len >= maxw-1)
+ strcpy(buf+(maxw-4), "..."); // !!! FIXME: Unicode issues!
+
+ *lines = (char*) entry->xrealloc(*lines, strlen(*lines)+strlen(buf)+2);
+ strcat(*lines, buf);
+ strcat(*lines, "\n"); // I'm sorry, Joel Spolsky!
+
+ if ((opts->value) || (opts->is_group_parent))
+ build_options(opts->child, line, level+1, maxw, lines);
+ build_options(opts->next_sibling, line, level, maxw, lines);
+ } // if
+} // build_options
+
+
static int MojoGui_ncurses_options(MojoGuiSetupOptions *opts,
boolean can_back, boolean can_fwd)
{
- return 1;
+ char *title = entry->xstrdup(entry->_("Options"));
+ MojoBox *mojobox = NULL;
+ char *buttons[4] = { NULL, NULL, NULL, NULL };
+ boolean ignoreerr = false;
+ int lasthoverover = 0;
+ int lasttextpos = 0;
+ int bcount = 0;
+ int backbutton = -99;
+ int fwdbutton = -99;
+ int togglebutton = -99;
+ int cancelbutton = -99;
+ int selected = 0;
+ int ch = 0;
+ int rc = -1;
+ int i = 0;
+
+ if (can_fwd)
+ {
+ fwdbutton = bcount++;
+ buttons[fwdbutton] = entry->xstrdup(entry->_("Next"));
+ } // if
+
+ if (can_back)
+ {
+ backbutton = bcount++;
+ buttons[backbutton] = entry->xstrdup(entry->_("Back"));
+ } // if
+
+ lasthoverover = togglebutton = bcount++;
+ buttons[togglebutton] = entry->xstrdup(entry->_("Toggle"));
+ cancelbutton = bcount++;
+ buttons[cancelbutton] = entry->xstrdup(entry->_("Cancel"));
+
+ do
+ {
+ if (mojobox == NULL)
+ {
+ int y = 0;
+ int line = 0;
+ int maxw, maxh;
+ getmaxyx(stdscr, maxh, maxw);
+ char *text = entry->xstrdup("");
+ build_options(opts, &line, 1, maxw-6, &text);
+ mojobox = makeBox(title, text, buttons, bcount, false, true);
+ free(text);
+
+ getmaxyx(mojobox->textwin, maxh, maxw);
+
+ if (lasthoverover != mojobox->hoverover)
+ {
+ const int orighover = mojobox->hoverover;
+ mojobox->hoverover = lasthoverover;
+ drawButton(mojobox, orighover);
+ drawButton(mojobox, lasthoverover);
+ wrefresh(mojobox->buttons[orighover]);
+ wrefresh(mojobox->buttons[lasthoverover]);
+ } // if
+
+ if (lasttextpos != mojobox->textpos)
+ {
+ mojobox->textpos = lasttextpos;
+ drawText(mojobox);
+ } // if
+
+ if (selected >= (mojobox->textlinecount - 1))
+ selected = mojobox->textlinecount - 1;
+ if (selected >= mojobox->textpos+maxh)
+ selected = (mojobox->textpos+maxh) - 1;
+ y = selected - lasttextpos;
+
+ wattron(mojobox->textwin, COLOR_PAIR(MOJOCOLOR_BUTTONHOVER));
+ mvwhline(mojobox->textwin, y, 0, ' ', maxw);
+ mvwaddstr(mojobox->textwin, y, 0, mojobox->textlines[selected]);
+ wattroff(mojobox->textwin, COLOR_PAIR(MOJOCOLOR_BUTTONHOVER));
+ wrefresh(mojobox->textwin);
+ } // if
+
+ lasttextpos = mojobox->textpos;
+ lasthoverover = mojobox->hoverover;
+
+ ch = wgetch(mojobox->mainwin);
+
+ if (ignoreerr) // kludge.
+ {
+ ignoreerr = false;
+ if (ch == ERR)
+ continue;
+ } // if
+
+ if (ch == KEY_RESIZE)
+ {
+ freeBox(mojobox, false); // catch and rebuild without upkeepBox,
+ mojobox = NULL; // so we can rebuild the text ourself.
+ ignoreerr = true; // kludge.
+ } // if
+
+ else if (ch == KEY_UP)
+ {
+ if (selected > 0)
+ {
+ WINDOW *win = mojobox->textwin;
+ int maxw, maxh;
+ int y = --selected - mojobox->textpos;
+ getmaxyx(win, maxh, maxw);
+ if (selected < mojobox->textpos)
+ {
+ upkeepBox(&mojobox, ch); // upkeepBox does scrolling
+ y++;
+ } // if
+ else
+ {
+ wattron(win, COLOR_PAIR(MOJOCOLOR_TEXT));
+ mvwhline(win, y+1, 0, ' ', maxw);
+ mvwaddstr(win, y+1, 0, mojobox->textlines[selected+1]);
+ wattroff(win, COLOR_PAIR(MOJOCOLOR_TEXT));
+ } // else
+ wattron(win, COLOR_PAIR(MOJOCOLOR_BUTTONHOVER));
+ mvwhline(win, y, 0, ' ', maxw);
+ mvwaddstr(win, y, 0, mojobox->textlines[selected]);
+ wattroff(win, COLOR_PAIR(MOJOCOLOR_BUTTONHOVER));
+ wrefresh(win);
+ } // if
+ } // else if
+
+ else if (ch == KEY_DOWN)
+ {
+ if (selected < (mojobox->textlinecount-1))
+ {
+ WINDOW *win = mojobox->textwin;
+ int maxw, maxh;
+ int y = ++selected - mojobox->textpos;
+ getmaxyx(win, maxh, maxw);
+ if (selected >= mojobox->textpos+maxh)
+ {
+ upkeepBox(&mojobox, ch); // upkeepBox does scrolling
+ y--;
+ } // if
+ else
+ {
+ wattron(win, COLOR_PAIR(MOJOCOLOR_TEXT));
+ mvwhline(win, y-1, 0, ' ', maxw);
+ mvwaddstr(win, y-1, 0, mojobox->textlines[selected-1]);
+ wattroff(win, COLOR_PAIR(MOJOCOLOR_TEXT));
+ } // else
+ wattron(win, COLOR_PAIR(MOJOCOLOR_BUTTONHOVER));
+ mvwhline(win, y, 0, ' ', maxw);
+ mvwaddstr(win, y, 0, mojobox->textlines[selected]);
+ wattroff(win, COLOR_PAIR(MOJOCOLOR_BUTTONHOVER));
+ wrefresh(win);
+ } // if
+ } // else if
+
+ else if ((ch == KEY_NPAGE) || (ch == KEY_NPAGE))
+ {
+ // !!! FIXME: maybe handle this when I'm not so lazy.
+ // !!! FIXME: For now, this if statement is to block
+ // !!! FIXME: upkeepBox() from scrolling and screwing up state.
+ } // else if
+
+ else // let upkeepBox handle other input (button selection, etc).
+ {
+ rc = upkeepBox(&mojobox, ch);
+ if (rc == togglebutton)
+ {
+ int line = 0;
+ rc = -1; // reset so we don't stop processing input.
+ if (toggle_option(NULL, opts, &line, selected+1) == 1)
+ {
+ freeBox(mojobox, false); // rebuild to reflect new options...
+ mojobox = NULL;
+ } // if
+ } // if
+ } // else
+ } while (rc == -1);
+
+ freeBox(mojobox, true);
+
+ for (i = 0; i < bcount; i++)
+ free(buttons[i]);
+
+ free(title);
+
+ if (rc == backbutton)
+ return -1;
+ else if (rc == fwdbutton)
+ return 1;
+
+ return 0; // error? Cancel?
} // MojoGui_ncurses_options
@@ -649,7 +950,9 @@
int *command, boolean can_back,
boolean can_fwd)
{
- return NULL;
+ // !!! FIXME: clearly this isn't right.
+ *command = 1;
+ return entry->xstrdup("/home/icculus/duke3d");
} // MojoGui_ncurses_destination
Modified: trunk/gui_stdio.c
===================================================================
--- trunk/gui_stdio.c 2007-05-20 08:14:11 UTC (rev 294)
+++ trunk/gui_stdio.c 2007-05-20 09:01:30 UTC (rev 295)
@@ -332,7 +332,7 @@
int *command, boolean can_back,
boolean can_fwd)
{
- const char *instdeststr = entry->xstrdup(entry->_("Install destination:"));
+ const char *instdeststr = entry->xstrdup(entry->_("Destination"));
const char *prompt = NULL;
char *retval = NULL;
boolean getout = false;
Modified: trunk/scripts/localization.lua
===================================================================
--- trunk/scripts/localization.lua 2007-05-20 08:14:11 UTC (rev 294)
+++ trunk/scripts/localization.lua 2007-05-20 09:01:30 UTC (rev 295)
@@ -98,10 +98,10 @@
["> "] = {
};
- ["Install options:"] = {
+ ["Options"] = {
};
- ["Install destination:"] = {
+ ["Destination"] = {
};
["Choose install destination by number (hit enter for #1), or enter your own."] = {
More information about the mojosetup-commits
mailing list