home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)topl.c 3.1 90/09/21
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* NetHack may be freely redistributed. See license for details. */
-
- #include "hack.h"
- #include "termcap.h"
- #include "wintty.h"
- #include <ctype.h>
-
- STATIC_DCL void FDECL(redotoplin, (const char*));
- STATIC_DCL void FDECL(topl_putsym, (CHAR_P));
- STATIC_DCL void NDECL(remember_topl);
- static void FDECL(removetopl, (int));
-
- #ifdef OVLB
-
- int
- tty_doprev_message()
- {
- register struct WinDesc *cw = wins[WIN_MESSAGE];
-
- if(cw->data[cw->maxcol])
- redotoplin(cw->data[cw->maxcol]);
- else if(cw->maxcol == cw->maxrow)
- redotoplin(toplines);
- cw->maxcol--;
- if(cw->maxcol < 0) cw->maxcol = cw->rows-1;
- if(!cw->data[cw->maxcol])
- cw->maxcol = cw->maxrow;
- return 0;
- }
-
- #endif /* OVLB */
- #ifdef OVL1
-
- STATIC_OVL void
- redotoplin(str)
- const char *str;
- {
- int otoplin = ttyDisplay->toplin;
- home();
- if(*str & 0x80) {
- /* kludge for the / command, the only time we ever want a */
- /* graphics character on the top line */
- g_putch(*str++);
- ttyDisplay->curx++;
- }
- end_glyphout(); /* in case message printed during graphics output */
- putsyms(str);
- cl_end();
- ttyDisplay->toplin = 1;
- if(ttyDisplay->cury && otoplin != 3)
- more();
- }
-
- STATIC_OVL void
- remember_topl()
- {
- register struct WinDesc *cw = wins[WIN_MESSAGE];
-
- cw->data[cw->maxrow] = (char*) alloc(strlen(toplines)+1);
- Strcpy(cw->data[cw->maxrow], toplines);
- cw->maxcol = cw->maxrow = (cw->maxrow+1) % cw->rows;
- if(cw->data[cw->maxrow]) {
- free((genericptr_t)cw->data[cw->maxrow]);
- cw->data[cw->maxrow] = 0;
- }
- }
-
- void
- addtopl(s)
- const char *s;
- {
- register struct WinDesc *cw = wins[WIN_MESSAGE];
-
- tty_curs(BASE_WINDOW,cw->curx+1,cw->cury);
- if(cw->curx + (int)strlen(s) >= CO) topl_putsym('\n');
- putsyms(s);
- cl_end();
- ttyDisplay->toplin = 1;
- }
-
- #endif /* OVL1 */
- #ifdef OVL2
-
- void
- more()
- {
- struct WinDesc *cw = wins[WIN_MESSAGE];
-
- /* avoid recursion -- only happens from interrupts */
- if(ttyDisplay->inmore++)
- return;
-
- if(ttyDisplay->toplin) {
- tty_curs(BASE_WINDOW, cw->curx+1, cw->cury);
- if(cw->curx >= CO - 8) topl_putsym('\n');
- }
-
- if(flags.standout)
- standoutbeg();
- putsyms(defmorestr);
- if(flags.standout)
- standoutend();
-
- xwaitforspace("\033");
-
- if(morc == '\033')
- cw->flags |= WIN_STOP;
-
- if(ttyDisplay->toplin && cw->cury) {
- docorner(1, cw->cury+1);
- cw->curx = cw->cury = 0;
- home();
- } else if(morc == '\033') {
- cw->curx = cw->cury = 0;
- home();
- cl_end();
- }
- ttyDisplay->toplin = 0;
- ttyDisplay->inmore = 0;
- }
-
- void
- update_topl(bp)
- register const char *bp;
- {
- register char *tl, *otl;
- register int n0;
- int notdied = 1;
- struct WinDesc *cw = wins[WIN_MESSAGE];
-
- /* If there is room on the line, print message on same line */
- /* But messages like "You die..." deserve their own line */
- n0 = strlen(bp);
- if(ttyDisplay->toplin == 1 && cw->cury == 0 &&
- n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */
- (notdied = strncmp(bp, "You die", 7))) {
- Strcat(toplines, " ");
- Strcat(toplines, bp);
- cw->curx += 2;
- if(!(cw->flags & WIN_STOP))
- addtopl(bp);
- return;
- } else if(!(cw->flags & WIN_STOP)) {
- if(ttyDisplay->toplin == 1) more();
- else if(cw->cury) { /* for when flags.toplin == 2 && cury > 1 */
- docorner(1, cw->cury+1); /* reset cury = 0 if redraw screen */
- cw->curx = cw->cury = 0;/* from home--cls() & docorner(1,n) */
- }
- }
- remember_topl();
- Strcpy(toplines, bp);
- for(tl = toplines; n0 >= CO; ){
- otl = tl;
- for(tl+=CO-1; tl != otl && !isspace(*tl); --tl) ;
- if(tl == otl) {
- /* Eek! A huge token. Try splitting after it. */
- tl = index(otl, ' ');
- if (!tl) break; /* No choice but to spit it out whole. */
- }
- *tl++ = '\n';
- n0 = strlen(tl);
- }
- if(!notdied) cw->flags &= ~WIN_STOP;
- if(!(cw->flags & WIN_STOP)) redotoplin(toplines);
- }
-
- STATIC_OVL
- void
- topl_putsym(c)
- char c;
- {
- register struct WinDesc *cw = wins[WIN_MESSAGE];
-
- if(cw == (struct WinDesc *) 0) panic("Putsym window MESSAGE nonexistant");
-
- switch(c) {
- case '\b':
- if(ttyDisplay->curx == 0 && ttyDisplay->cury > 0)
- tty_curs(BASE_WINDOW, CO, (int)ttyDisplay->cury-1);
- backsp();
- ttyDisplay->curx--;
- cw->curx = ttyDisplay->curx;
- return;
- case '\n':
- cl_end();
- ttyDisplay->curx = 0;
- ttyDisplay->cury++;
- cw->cury = ttyDisplay->cury;
- break;
- default:
- if(ttyDisplay->curx == CO-1)
- topl_putsym('\n'); /* 1 <= curx <= CO; avoid CO */
- ttyDisplay->curx++;
- }
- cw->curx = ttyDisplay->curx;
- if(cw->curx == 0) cl_end();
- (void) putchar(c);
- }
-
- void
- putsyms(str)
- const char *str;
- {
- while(*str)
- topl_putsym(*str++);
- }
-
- static void
- removetopl(n)
- register int n;
- {
- /* assume addtopl() has been done, so ttyDisplay->toplin is already set */
- while (n-- > 0) putsyms("\b \b");
- }
-
- extern char erase_char; /* from xxxtty.c; don't need kill_char */
-
- char
- tty_yn_function(query,resp, def)
- const char *query,*resp;
- char def;
- /*
- * Generic yes/no function. 'def' is the default (returned by space or
- * return; 'esc' returns 'q', or 'n', or the default, depending on
- * what's in the string. The 'query' string is printed before the user
- * is asked about the string.
- * If resp is NULL, any single character is accepted and returned.
- */
- {
- register char q;
- char rtmp[40];
- boolean digit_ok, allow_num;
- struct WinDesc *cw = wins[WIN_MESSAGE];
- boolean doprev = 0;
- char prompt[QBUFSZ];
-
- if(ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP)) more();
- cw->flags &= ~WIN_STOP;
- ttyDisplay->toplin = 3; /* special prompt state */
- ttyDisplay->inread++;
- if(resp) {
- allow_num = (index(resp, '#') != 0);
- if(def)
- Sprintf(prompt, "%s [%s] (%c) ", query, resp, def);
- else
- Sprintf(prompt, "%s [%s] ", query, resp);
- pline("%s", prompt);
- } else {
- pline("%s ", query);
- q = readchar();
- goto clean_up;
- }
-
- do { /* loop until we get valid input */
- q = lowc(readchar());
- if (q == '\020') { /* ctrl-P */
- if(!doprev) (void) tty_doprev_message(); /* need two initially */
- (void) tty_doprev_message();
- q = (char)0;
- doprev = 1;
- continue;
- } else if(doprev) {
- tty_clear_nhwindow(WIN_MESSAGE);
- cw->maxcol = cw->maxrow;
- doprev = 0;
- addtopl(prompt);
- continue;
- }
- digit_ok = allow_num && digit(q);
- if (q == '\033') {
- if (index(resp, 'q'))
- q = 'q';
- else if (index(resp, 'n'))
- q = 'n';
- else
- q = def;
- break;
- } else if (index(quitchars, q)) {
- q = def;
- break;
- }
- if (!index(resp, q) && !digit_ok) {
- tty_nhbell();
- q = (char)0;
- } else if (q == '#' || digit_ok) {
- char z, digit_string[2];
- int n_len = 0;
- long value = 0;
- addtopl("#"), n_len++;
- digit_string[1] = '\0';
- if (q != '#') {
- digit_string[0] = q;
- addtopl(digit_string), n_len++;
- value = q - '0';
- q = '#';
- }
- do { /* loop until we get a non-digit */
- z = lowc(readchar());
- if (digit(z)) {
- value = (10 * value) + (z - '0');
- if (value < 0) break; /* overflow: try again */
- digit_string[0] = z;
- addtopl(digit_string), n_len++;
- } else if (z == 'y' || index(quitchars, z)) {
- if (z == '\033') value = -1; /* abort */
- z = '\n'; /* break */
- } else if (z == erase_char || z == '\b') {
- if (n_len <= 1) { value = -1; break; }
- else { value /= 10; removetopl(1), n_len--; }
- } else {
- value = -1; /* abort */
- tty_nhbell();
- break;
- }
- } while (z != '\n');
- if (value > 0) yn_number = value;
- else if (value == 0) q = 'n'; /* 0 => "no" */
- else { /* remove number from top line, then try again */
- removetopl(n_len), n_len = 0;
- q = '\0';
- }
- }
- } while(!q);
-
- if (q != '#') {
- Sprintf(rtmp, "%c", q);
- addtopl(rtmp);
- }
- clean_up:
- ttyDisplay->inread--;
- ttyDisplay->toplin = 2;
- if(wins[WIN_MESSAGE]->cury)
- tty_clear_nhwindow(WIN_MESSAGE);
-
- return q;
- }
-
- #endif /* OVL2 */
-
- /*topl.c*/
-