git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@139
ddfedd41-794f-dd11-ae45-
00112f111e67
if (!mainwin1) {
/* It's possible that the main window failed to open. There's
nothing we can do without it, so exit. */
if (!mainwin1) {
/* It's possible that the main window failed to open. There's
nothing we can do without it, so exit. */
-
- /* Open a second window: a text grid, above the main window, five
- lines high. It is possible that this will fail also, but we accept
+
+ /* Open a second window: a text grid, above the main window, five
+ lines high. It is possible that this will fail also, but we accept
- statuswin = glk_window_open(mainwin1,
- winmethod_Above | winmethod_Fixed,
+ statuswin = glk_window_open(mainwin1,
+ winmethod_Above | winmethod_Fixed,
/* And a third window, a second story window below the main one. */
/* And a third window, a second story window below the main one. */
- mainwin2 = glk_window_open(mainwin1,
- winmethod_Below | winmethod_Proportional,
+ mainwin2 = glk_window_open(mainwin1,
+ winmethod_Below | winmethod_Proportional,
50, wintype_TextBuffer, 0);
50, wintype_TextBuffer, 0);
/* We're going to be switching from one window to another all the
time. So we'll be setting the output stream on a case-by-case
basis. Every function that prints must set the output stream
first. (Contrast model.c, where the output stream is always the
main window, and every function that changes that must set it
back afterwards.) */
/* We're going to be switching from one window to another all the
time. So we'll be setting the output stream on a case-by-case
basis. Every function that prints must set the output stream
first. (Contrast model.c, where the output stream is always the
main window, and every function that changes that must set it
back afterwards.) */
glk_set_window(mainwin1);
glk_put_string("Multiwin\nAn Interactive Sample Glk Program\n");
glk_put_string("By Andrew Plotkin.\nRelease 3.\n");
glk_put_string("Type \"help\" for a list of commands.\n");
glk_set_window(mainwin1);
glk_put_string("Multiwin\nAn Interactive Sample Glk Program\n");
glk_put_string("By Andrew Plotkin.\nRelease 3.\n");
glk_put_string("Type \"help\" for a list of commands.\n");
glk_set_window(mainwin2);
glk_put_string("Note that the upper left-hand window accepts character");
glk_put_string(" input. Hit 'h' to split the window horizontally, 'v' to");
glk_set_window(mainwin2);
glk_put_string("Note that the upper left-hand window accepts character");
glk_put_string(" input. Hit 'h' to split the window horizontally, 'v' to");
glk_put_string(" key codes. All new windows accept these same keys as");
glk_put_string(" well.\n\n");
glk_put_string("This bottom window accepts normal line input.\n");
glk_put_string(" key codes. All new windows accept these same keys as");
glk_put_string(" well.\n\n");
glk_put_string("This bottom window accepts normal line input.\n");
if (statuswin) {
/* For fun, let's open a fourth window now, splitting the status
window. */
winid_t keywin;
if (statuswin) {
/* For fun, let's open a fourth window now, splitting the status
window. */
winid_t keywin;
- keywin = glk_window_open(statuswin,
- winmethod_Left | winmethod_Proportional,
+ keywin = glk_window_open(statuswin,
+ winmethod_Left | winmethod_Proportional,
66, wintype_TextGrid, KEYWINROCK);
if (keywin) {
glk_request_char_event(keywin);
}
}
66, wintype_TextGrid, KEYWINROCK);
if (keywin) {
glk_request_char_event(keywin);
}
}
/* Draw the key window now, since we don't draw it every input (as
we do the status window. */
draw_keywins();
/* Draw the key window now, since we don't draw it every input (as
we do the status window. */
draw_keywins();
inputpending2 = FALSE;
already1 = 0;
already2 = 0;
inputpending2 = FALSE;
already1 = 0;
already2 = 0;
while (1) {
char *cx, *cmd;
int doneloop, len;
winid_t whichwin;
event_t ev;
while (1) {
char *cx, *cmd;
int doneloop, len;
winid_t whichwin;
event_t ev;
draw_statuswin();
/* We're not redrawing the key windows every command. */
draw_statuswin();
/* We're not redrawing the key windows every command. */
/* Either main window, or both, could already have line input
pending. If so, leave that window alone. If there is no
input pending on a window, set a line input request, but
keep around any characters that were in the buffer already. */
/* Either main window, or both, could already have line input
pending. If so, leave that window alone. If there is no
input pending on a window, set a line input request, but
keep around any characters that were in the buffer already. */
if (mainwin1 && !inputpending1) {
glk_set_window(mainwin1);
glk_put_string("\n>");
if (mainwin1 && !inputpending1) {
glk_set_window(mainwin1);
glk_put_string("\n>");
- /* We request up to 255 characters. The buffer can hold 256,
- but we are going to stick a null character at the end, so
- we have to leave room for that. Note that the Glk library
+ /* We request up to 255 characters. The buffer can hold 256,
+ but we are going to stick a null character at the end, so
+ we have to leave room for that. Note that the Glk library
does *not* put on that null character. */
glk_request_line_event(mainwin1, commandbuf1, 255, already1);
inputpending1 = TRUE;
}
does *not* put on that null character. */
glk_request_line_event(mainwin1, commandbuf1, 255, already1);
inputpending1 = TRUE;
}
if (mainwin2 && !inputpending2) {
glk_set_window(mainwin2);
glk_put_string("\n>");
if (mainwin2 && !inputpending2) {
glk_set_window(mainwin2);
glk_put_string("\n>");
glk_request_line_event(mainwin2, commandbuf2, 255, already2);
inputpending2 = TRUE;
}
glk_request_line_event(mainwin2, commandbuf2, 255, already2);
inputpending2 = TRUE;
}
doneloop = FALSE;
while (!doneloop) {
doneloop = FALSE;
while (!doneloop) {
/* Grab an event. */
glk_select(&ev);
/* Grab an event. */
glk_select(&ev);
case evtype_LineInput:
/* If the event comes from one main window or the other,
we mark that window as no longer having line input
case evtype_LineInput:
/* If the event comes from one main window or the other,
we mark that window as no longer having line input
doneloop = TRUE;
}
break;
doneloop = TRUE;
}
break;
case evtype_CharInput:
/* It's a key event, from one of the keywins. We
call a subroutine rather than exiting the
case evtype_CharInput:
/* It's a key event, from one of the keywins. We
call a subroutine rather than exiting the
that way too.) */
perform_key(ev.win, ev.val1);
break;
that way too.) */
perform_key(ev.win, ev.val1);
break;
case evtype_Timer:
/* It's a timer event. This does exit from the event
loop, since we're going to interrupt input in
mainwin1 and then re-print the prompt. */
whichwin = NULL;
case evtype_Timer:
/* It's a timer event. This does exit from the event
loop, since we're going to interrupt input in
mainwin1 and then re-print the prompt. */
whichwin = NULL;
case evtype_Arrange:
/* Windows have changed size, so we have to redraw the
status window and key window. But we stay in the
case evtype_Arrange:
/* Windows have changed size, so we have to redraw the
status window and key window. But we stay in the
if (cmd == NULL) {
/* It was a timer event. */
perform_timer();
continue;
}
if (cmd == NULL) {
/* It was a timer event. */
perform_timer();
continue;
}
/* It was a line input event. cmd now points at a line of input
from one of the main windows. */
/* It was a line input event. cmd now points at a line of input
from one of the main windows. */
/* The line we have received in commandbuf is not null-terminated.
We handle that first. */
len = ev.val1; /* Will be between 0 and 255, inclusive. */
cmd[len] = '\0';
/* The line we have received in commandbuf is not null-terminated.
We handle that first. */
len = ev.val1; /* Will be between 0 and 255, inclusive. */
cmd[len] = '\0';
/* Then squash to lower-case. */
/* Then squash to lower-case. */
- for (cx = cmd; *cx; cx++) {
+ for (cx = cmd; *cx; cx++) {
*cx = glk_char_to_lower(*cx);
}
*cx = glk_char_to_lower(*cx);
}
/* Then trim whitespace before and after. */
/* Then trim whitespace before and after. */
for (cx = cmd; *cx == ' '; cx++, len--) { };
for (cx = cmd; *cx == ' '; cx++, len--) { };
for (cx = cmd+len-1; cx >= cmd && *cx == ' '; cx--) { };
*(cx+1) = '\0';
for (cx = cmd+len-1; cx >= cmd && *cx == ' '; cx--) { };
*(cx+1) = '\0';
/* cmd now points to a nice null-terminated string. We'll do the
simplest possible parsing. */
if (str_eq(cmd, "")) {
/* cmd now points to a nice null-terminated string. We'll do the
simplest possible parsing. */
if (str_eq(cmd, "")) {
glk_put_string(cmd);
glk_put_string("\".\n");
}
glk_put_string(cmd);
glk_put_string("\".\n");
}
if (whichwin == mainwin1)
already1 = 0;
else if (whichwin == mainwin2)
if (whichwin == mainwin1)
already1 = 0;
else if (whichwin == mainwin2)
static void draw_statuswin(void)
{
glui32 width, height;
static void draw_statuswin(void)
{
glui32 width, height;
- /* It is possible that the window was not successfully
+ /* It is possible that the window was not successfully
created. If that's the case, don't try to draw it. */
return;
}
created. If that's the case, don't try to draw it. */
return;
}
glk_set_window(statuswin);
glk_window_clear(statuswin);
glk_set_window(statuswin);
glk_window_clear(statuswin);
glk_window_get_size(statuswin, &width, &height);
glk_window_get_size(statuswin, &width, &height);
/* Draw a decorative compass rose in the center. */
width = (width/2);
if (width > 0)
/* Draw a decorative compass rose in the center. */
width = (width/2);
if (width > 0)
height = (height/2);
if (height > 0)
height--;
height = (height/2);
if (height > 0)
height--;
glk_window_move_cursor(statuswin, width, height+0);
glk_put_string("\\|/");
glk_window_move_cursor(statuswin, width, height+1);
glk_put_string("-*-");
glk_window_move_cursor(statuswin, width, height+2);
glk_put_string("/|\\");
glk_window_move_cursor(statuswin, width, height+0);
glk_put_string("\\|/");
glk_window_move_cursor(statuswin, width, height+1);
glk_put_string("-*-");
glk_window_move_cursor(statuswin, width, height+2);
glk_put_string("/|\\");
}
/* This draws some corner decorations in *every* key window -- the
}
/* This draws some corner decorations in *every* key window -- the
winid_t win;
glui32 rock;
glui32 width, height;
winid_t win;
glui32 rock;
glui32 width, height;
for (win = glk_window_iterate(NULL, &rock);
win;
win = glk_window_iterate(win, &rock)) {
for (win = glk_window_iterate(NULL, &rock);
win;
win = glk_window_iterate(win, &rock)) {
glui32 width, height, len;
int ix;
char buf[128], keyname[64];
glui32 width, height, len;
int ix;
char buf[128], keyname[64];
if (key == 'h' || key == 'v') {
winid_t newwin;
glui32 loc;
if (key == 'h' || key == 'v') {
winid_t newwin;
glui32 loc;
loc = winmethod_Right | winmethod_Proportional;
else
loc = winmethod_Below | winmethod_Proportional;
loc = winmethod_Right | winmethod_Proportional;
else
loc = winmethod_Below | winmethod_Proportional;
- newwin = glk_window_open(win,
+ newwin = glk_window_open(win,
loc, 50, wintype_TextGrid, KEYWINROCK);
/* Since the new window has rock value KEYWINROCK, the
draw_keywins() routine will redraw it. */
loc, 50, wintype_TextGrid, KEYWINROCK);
/* Since the new window has rock value KEYWINROCK, the
draw_keywins() routine will redraw it. */
draw_statuswin();
return;
}
draw_statuswin();
return;
}
/* Print a string naming the key that was just hit. */
/* Print a string naming the key that was just hit. */
switch (key) {
case ' ':
str_cpy(keyname, "space");
switch (key) {
case ' ':
str_cpy(keyname, "space");
str_cpy(keyname, "end");
break;
default:
str_cpy(keyname, "end");
break;
default:
- if (key >= keycode_Func1 && key < keycode_Func12) {
+ if (key <= keycode_Func1 && key >= keycode_Func12) {
str_cpy(keyname, "function key");
}
else if (key < 32) {
str_cpy(keyname, "function key");
}
else if (key < 32) {
str_cpy(buf, "Key: ");
str_cat(buf, keyname);
str_cpy(buf, "Key: ");
str_cat(buf, keyname);
/* Print the string centered in this window. */
glk_set_window(win);
glk_window_get_size(win, &width, &height);
glk_window_move_cursor(win, 0, height/2);
for (ix=0; ix<width; ix++)
glk_put_char(' ');
/* Print the string centered in this window. */
glk_set_window(win);
glk_window_get_size(win, &width, &height);
glk_window_move_cursor(win, 0, height/2);
for (ix=0; ix<width; ix++)
glk_put_char(' ');
width = width/2;
len = len/2;
width = width/2;
len = len/2;
if (width > len)
width = width-len;
else
width = 0;
if (width > len)
width = width-len;
else
width = 0;
glk_window_move_cursor(win, width, height/2);
glk_put_string(buf);
glk_window_move_cursor(win, width, height/2);
glk_put_string(buf);
/* Re-request character input for this window, so that future
keys are accepted. */
glk_request_char_event(win);
/* Re-request character input for this window, so that future
keys are accepted. */
glk_request_char_event(win);
static void perform_timer()
{
event_t ev;
static void perform_timer()
{
event_t ev;
if (inputpending1) {
glk_cancel_line_event(mainwin1, &ev);
if (ev.type == evtype_LineInput)
if (inputpending1) {
glk_cancel_line_event(mainwin1, &ev);
if (ev.type == evtype_LineInput)
inputpending1 = FALSE;
}
}
inputpending1 = FALSE;
}
}
return otherwin;
}
static void verb_help(winid_t win)
{
glk_set_window(win);
return otherwin;
}
static void verb_help(winid_t win)
{
glk_set_window(win);
glk_put_string("This model only understands the following commands:\n");
glk_put_string("HELP: Display this list.\n");
glk_put_string("JUMP: Print a short message.\n");
glk_put_string("This model only understands the following commands:\n");
glk_put_string("HELP: Display this list.\n");
glk_put_string("JUMP: Print a short message.\n");
static void verb_jump(winid_t win)
{
glk_set_window(win);
static void verb_jump(winid_t win)
{
glk_set_window(win);
glk_put_string("You jump on the fruit, spotlessly.\n");
}
glk_put_string("You jump on the fruit, spotlessly.\n");
}
static void verb_both(winid_t win)
{
winid_t otherwin;
static void verb_both(winid_t win)
{
winid_t otherwin;
glk_set_window(win);
glk_put_string("Something happens in this window.\n");
glk_set_window(win);
glk_put_string("Something happens in this window.\n");
otherwin = print_to_otherwin(win);
otherwin = print_to_otherwin(win);
if (otherwin) {
glk_set_window(otherwin);
glk_put_string("Something happens in the other window.\n");
if (otherwin) {
glk_set_window(otherwin);
glk_put_string("Something happens in the other window.\n");
glk_set_window(win);
for (ix=0; ix<30; ix++) {
num_to_str(buf, ix);
glk_set_window(win);
for (ix=0; ix<30; ix++) {
num_to_str(buf, ix);
/* Print thirty lines in both windows. This gets fancy by printing
to each window alternately, without setting the output stream,
/* Print thirty lines in both windows. This gets fancy by printing
to each window alternately, without setting the output stream,
- by using glk_put_string_stream() instead of glk_put_string().
+ by using glk_put_string_stream() instead of glk_put_string().
There's no particular difference; this is just a demonstration. */
static void verb_pageboth(winid_t win)
{
There's no particular difference; this is just a demonstration. */
static void verb_pageboth(winid_t win)
{
winid_t otherwin;
strid_t str, otherstr;
char buf[32];
winid_t otherwin;
strid_t str, otherstr;
char buf[32];
str = glk_window_get_stream(win);
otherwin = print_to_otherwin(win);
str = glk_window_get_stream(win);
otherwin = print_to_otherwin(win);
otherstr = glk_window_get_stream(otherwin);
else
otherstr = NULL;
otherstr = glk_window_get_stream(otherwin);
else
otherstr = NULL;
static void verb_timer(winid_t win)
{
glk_set_window(win);
static void verb_timer(winid_t win)
{
glk_set_window(win);
if (timer_on) {
glk_put_string("The timer is already running.\n");
return;
}
if (timer_on) {
glk_put_string("The timer is already running.\n");
return;
}
if (glk_gestalt(gestalt_Timer, 0) == 0) {
glk_put_string("Your Glk library does not support timer events.\n");
return;
}
if (glk_gestalt(gestalt_Timer, 0) == 0) {
glk_put_string("Your Glk library does not support timer events.\n");
return;
}
glk_put_string("A timer starts running in the upper window.\n");
glk_request_timer_events(3000); /* Every three seconds. */
timer_on = TRUE;
glk_put_string("A timer starts running in the upper window.\n");
glk_request_timer_events(3000); /* Every three seconds. */
timer_on = TRUE;
static void verb_untimer(winid_t win)
{
glk_set_window(win);
static void verb_untimer(winid_t win)
{
glk_set_window(win);
if (!timer_on) {
glk_put_string("The timer is not currently running.\n");
return;
}
if (!timer_on) {
glk_put_string("The timer is not currently running.\n");
return;
}
glk_put_string("The timer stops running.\n");
glk_request_timer_events(0);
timer_on = FALSE;
glk_put_string("The timer stops running.\n");
glk_request_timer_events(0);
timer_on = FALSE;
for (ix=0; ix<256; ix++) {
num_to_str(buf, ix);
glk_put_string(buf);
for (ix=0; ix<256; ix++) {
num_to_str(buf, ix);
glk_put_string(buf);
static void verb_yada(winid_t win)
{
static void verb_yada(winid_t win)
{
- /* This is a goofy (and overly ornate) way to print a long paragraph.
+ /* This is a goofy (and overly ornate) way to print a long paragraph.
It just shows off line wrapping in the Glk implementation. */
#define NUMWORDS (13)
static char *wordcaplist[NUMWORDS] = {
It just shows off line wrapping in the Glk implementation. */
#define NUMWORDS (13)
static char *wordcaplist[NUMWORDS] = {
static int jx = 0;
int ix;
int first = TRUE;
static int jx = 0;
int ix;
int first = TRUE;
for (ix=0; ix<85; ix++) {
if (ix > 0) {
glk_put_string(" ");
}
for (ix=0; ix<85; ix++) {
if (ix > 0) {
glk_put_string(" ");
}
if (first) {
glk_put_string(wordcaplist[(ix / 17) % NUMWORDS]);
first = FALSE;
}
if (first) {
glk_put_string(wordcaplist[(ix / 17) % NUMWORDS]);
first = FALSE;
}
glk_put_string(wordlist[jx]);
jx = (jx + wstep) % NUMWORDS;
wcount1++;
glk_put_string(wordlist[jx]);
jx = (jx + wstep) % NUMWORDS;
wcount1++;
if ((ix % 17) == 16) {
glk_put_string(".");
first = TRUE;
}
}
if ((ix % 17) == 16) {
glk_put_string(".");
first = TRUE;
}
}
glk_put_char('\n');
}
static void verb_quit(winid_t win)
{
glk_set_window(win);
glk_put_char('\n');
}
static void verb_quit(winid_t win)
{
glk_set_window(win);
glk_put_string("Thanks for playing.\n");
glk_exit();
/* glk_exit() actually stops the process; it does not return. */
glk_put_string("Thanks for playing.\n");
glk_exit();
/* glk_exit() actually stops the process; it does not return. */
if (*s1 != *s2)
return FALSE;
}
if (*s1 != *s2)
return FALSE;
}
if (*s1 || *s2)
return FALSE;
else
if (*s1 || *s2)
return FALSE;
else
static char *str_cpy(char *s1, char *s2)
{
char *orig = s1;
static char *str_cpy(char *s1, char *s2)
{
char *orig = s1;
for (; *s2; s1++, s2++)
*s1 = *s2;
*s1 = '\0';
for (; *s2; s1++, s2++)
*s1 = *s2;
*s1 = '\0';
static char *str_cat(char *s1, char *s2)
{
char *orig = s1;
static char *str_cat(char *s1, char *s2)
{
char *orig = s1;
while (*s1)
s1++;
for (; *s2; s1++, s2++)
*s1 = *s2;
*s1 = '\0';
while (*s1)
s1++;
for (; *s2; s1++, s2++)
*s1 = *s2;
*s1 = '\0';
int ix;
int size = 0;
char tmpc;
int ix;
int size = 0;
char tmpc;
if (num == 0) {
str_cpy(buf, "0");
return;
}
if (num == 0) {
str_cpy(buf, "0");
return;
}
if (num < 0) {
buf[0] = '-';
buf++;
num = -num;
}
if (num < 0) {
buf[0] = '-';
buf++;
num = -num;
}
while (num) {
buf[size] = '0' + (num % 10);
size++;
while (num) {
buf[size] = '0' + (num % 10);
size++;