/** * Get some input at the cursor location. * * The buffer is assumed to have been initialized to a default string. * Note that this string is often "empty" (see below). * * The default buffer is displayed in yellow until cleared, which happens * on the first keypress, unless that keypress is Return. * * Normal chars clear the default and append the char. * Backspace clears the default or deletes the final char. * Return accepts the current buffer contents and returns true. * Escape clears the buffer and the window and returns false. * * Note that 'len' refers to the size of the buffer. The maximum length * of the input is 'len-1'. * * 'keypress_h' is a pointer to a function to handle keypresses, altering * the input buffer, cursor position and suchlike as required. See * 'askfor_aux_keypress' (the default handler if you supply NULL for * 'keypress_h') for an example. */ bool askfor_aux(char *buf, size_t len, bool (*keypress_h)(char *, size_t, size_t *, size_t *, struct keypress, bool)) { int y, x; size_t k = 0; /* Cursor position */ size_t nul = 0; /* Position of the null byte in the string */ struct keypress ch = KEYPRESS_NULL; bool done = false; bool firsttime = true; if (keypress_h == NULL) keypress_h = askfor_aux_keypress; /* Locate the cursor */ Term_locate(&x, &y); /* Paranoia */ if ((x < 0) || (x >= 80)) x = 0; /* Restrict the length */ if (x + len > 80) len = 80 - x; /* Truncate the default entry */ buf[len-1] = '\0'; /* Get the position of the null byte */ nul = strlen(buf); /* Display the default answer */ Term_erase(x, y, (int)len); Term_putstr(x, y, -1, COLOUR_YELLOW, buf); /* Process input */ while (!done) { /* Place cursor */ Term_gotoxy(x + k, y); /* Get a key */ ch = inkey(); /* Let the keypress handler deal with the keypress */ done = keypress_h(buf, len, &k, &nul, ch, firsttime); /* Update the entry */ Term_erase(x, y, (int)len); Term_putstr(x, y, -1, COLOUR_WHITE, buf); /* Not the first time round anymore */ firsttime = false; } /* Done */ return (ch.code != ESCAPE); }
/* * Display glyph and colours */ static void display_glyphs(int col, int row, int height, int width, byte a, wchar_t c) { int i; int x, y; /* Clear the display lines */ for (i = 0; i < height; i++) Term_erase(col, row + i, width); /* Prompt */ prt("Choose colour:", row + height / 2, col); Term_locate(&x, &y); for (i = 0; i < MAX_COLORS; i++) big_pad(x + i, y, i, c); /* Place the cursor */ Term_gotoxy(x + a, y); }
/* * Hack -- display recent messages in sub-windows * * XXX XXX XXX Adjust for width and split messages */ void fix_message(void) { s32b j, i; s32b w, h; s32b x, y; /* Scan windows */ for (j = 0; j < 8; j++) { term *old = Term; /* No window */ if (!angband_term[j]) continue; /* No relevant flags */ if (!flag_exists(&window_flag[j], FLAG_PW_MESSAGE)) continue; /* Activate */ Term_activate(angband_term[j]); /* Get size */ Term_get_size(&w, &h); /* Dump messages */ for (i = 0; i < h; i++) { /* Dump the message on the appropriate line */ display_message(0, (h - 1) - i, strlen(message_str((s16b)i)), message_color((s16b)i), message_str((s16b)i)); /* Cursor */ Term_locate(&x, &y); /* Clear to end of line */ Term_erase(x, y, 255); } /* Fresh */ Term_fresh(); /* Restore */ Term_activate(old); } }
/* * Print some (colored) text to the screen at the current cursor position, * automatically "wrapping" existing text (at spaces) when necessary to * avoid placing any text into the last column, and clearing every line * before placing any text in that line. Also, allow "newline" to force * a "wrap" to the next line. Advance the cursor as needed so sequential * calls to this function will work correctly. * * Once this function has been called, the cursor should not be moved * until all the related "text_out()" calls to the window are complete. * * This function will correctly handle any width up to the maximum legal * value of 256, though it works best for a standard 80 character width. */ void text_out_to_screen(byte a, const char *str) { int x, y; int wid, h; int wrap; const wchar_t *s; wchar_t buf[1024]; /* Obtain the size */ (void)Term_get_size(&wid, &h); /* Obtain the cursor */ (void)Term_locate(&x, &y); /* Copy to a rewriteable string */ Term_mbstowcs(buf, str, 1024); /* Use special wrapping boundary? */ if ((text_out_wrap > 0) && (text_out_wrap < wid)) wrap = text_out_wrap; else wrap = wid; /* Process the string */ for (s = buf; *s; s++) { wchar_t ch; /* Force wrap */ if (*s == L'\n') { /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); continue; } /* Clean up the char */ ch = (iswprint(*s) ? *s : L' '); /* Wrap words as needed */ if ((x >= wrap - 1) && (ch != L' ')) { int i, n = 0; byte av[256]; wchar_t cv[256]; /* Wrap word */ if (x < wrap) { /* Scan existing text */ for (i = wrap - 2; i >= 0; i--) { /* Grab existing attr/char */ Term_what(i, y, &av[i], &cv[i]); /* Break on space */ if (cv[i] == L' ') break; /* Track current word */ n = i; } } /* Special case */ if (n == 0) n = wrap; /* Clear line */ Term_erase(n, y, 255); /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); /* Wrap the word (if any) */ for (i = n; i < wrap - 1; i++) { /* Dump */ Term_addch(av[i], cv[i]); /* Advance (no wrap) */ if (++x > wrap) x = wrap; } } /* Dump */ Term_addch(a, ch); /* Advance */ if (++x > wrap) x = wrap; } }
/* * Memorize a message, Log it, Search it, and Display it in pieces */ static void borg_note_aux(cptr what) { int j, n, i, k; int w, h, x, y; term *old = Term; /* Memorize it */ message_add(what, MSG_GENERIC); /* Log the message */ if (borg_fff) froff(borg_fff, "%s\n", what); /* Mega-Hack -- Check against the search string */ if (borg_match[0] && strstr(what, borg_match)) { /* Tell the user why you quit */ borg_oops("Search string was matched"); } /* Scan windows */ for (j = 0; j < 8; j++) { if (!angband_term[j]) continue; /* Check flag */ if (!(window_flag[j] & PW_BORG_1)) continue; /* Activate */ Term_activate(angband_term[j]); /* Access size */ Term_get_size(&w, &h); /* Access cursor */ Term_locate(&x, &y); /* Erase current line */ clear_row(y); /* Total length */ n = strlen(what); /* Too long */ if (n > w - 2) { char buf[1024]; /* Split */ while (n > w - 2) { /* Default */ k = w - 2; /* Find a split point */ for (i = w / 2; i < w - 2; i++) { /* Pre-emptive split point */ if (isspace(what[i])) k = i; } /* Copy over the split message */ for (i = 0; i < k; i++) { /* Copy */ buf[i] = what[i]; } /* Indicate split */ buf[i++] = '\\'; /* Terminate */ buf[i] = '\0'; /* Show message */ roff(buf); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ clear_row(y); /* Advance */ what += k; /* Reduce */ n -= k; } /* Show message tail */ roff(what); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ clear_row(y); } /* Normal */ else { /* Show message */ roff(what); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ clear_row(y); } /* Flush output */ Term_fresh(); /* Use correct window */ Term_activate(old); } }
/* * Print some (colored) text to the screen at the current cursor position, * automatically "wrapping" existing text (at spaces) when necessary to * avoid placing any text into the last column, and clearing every line * before placing any text in that line. Also, allow "newline" to force * a "wrap" to the next line. Advance the cursor as needed so sequential * calls to this function will work correctly. * * Once this function has been called, the cursor should not be moved * until all the related "text_out()" calls to the window are complete. * * This function will correctly handle any width up to the maximum legal * value of 256, though it works best for a standard 80 character width. */ void text_out_to_screen(byte a, const char *str) { int x, y; int wid, h; int wrap; const char *s; char buf[1024]; /* We use either ascii or system-specific encoding */ int encoding = (OPT(xchars_to_file)) ? SYSTEM_SPECIFIC : ASCII; /* Obtain the size */ (void)Term_get_size(&wid, &h); /* Obtain the cursor */ (void)Term_locate(&x, &y); /* Copy to a rewriteable string */ my_strcpy(buf, str, 1024); /* Translate it to 7-bit ASCII or system-specific format */ xstr_trans(buf, encoding); /* Use special wrapping boundary? */ if ((text_out_wrap > 0) && (text_out_wrap < wid)) wrap = text_out_wrap; else wrap = wid; /* Process the string */ for (s = buf; *s; s++) { char ch; /* Force wrap */ if (*s == '\n') { /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); continue; } /* Clean up the char */ ch = (my_isprint((unsigned char)*s) ? *s : ' '); /* Wrap words as needed */ if ((x >= wrap - 1) && (ch != ' ')) { int i, n = 0; byte av[256]; char cv[256]; /* Wrap word */ if (x < wrap) { /* Scan existing text */ for (i = wrap - 2; i >= 0; i--) { /* Grab existing attr/char */ Term_what(i, y, &av[i], &cv[i]); /* Break on space */ if (cv[i] == ' ') break; /* Track current word */ n = i; } } /* Special case */ if (n == 0) n = wrap; /* Clear line */ Term_erase(n, y, 255); /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); /* Wrap the word (if any) */ for (i = n; i < wrap - 1; i++) { /* Dump */ Term_addch(av[i], cv[i]); /* Advance (no wrap) */ if (++x > wrap) x = wrap; } } /* Dump */ Term_addch(a, ch); /* Advance */ if (++x > wrap) x = wrap; } }
/* * Get some input at the cursor location. * Assume the buffer is initialized to a default string. * Note that this string is often "empty" (see below). * The default buffer is displayed in yellow until cleared. * Pressing RETURN right away accepts the default entry. * Normal chars clear the default and append the char. * Backspace clears the default or deletes the final char. * ESCAPE clears the buffer and the window and returns FALSE. * RETURN accepts the current buffer contents and returns TRUE. * * Note that 'len' refers to the size of the buffer. The maximum length * of the input is 'len-1'. */ bool askfor_aux(char *buf, int len) { int y, x; int i = 0; int k = 0; bool done = FALSE; /* Locate the cursor */ (void)Term_locate(&x, &y); /* Paranoia -- check len */ if (len < 1) len = 1; /* Paranoia -- check column */ if ((x < 0) || (x >= 80)) x = 0; /* Restrict the length */ if (x + len > 80) len = 80 - x; /* Paranoia -- Clip the default entry */ buf[len - 1] = '\0'; /* Display the default answer */ Term_erase(x, y, len); put_fstr(x, y, CLR_YELLOW "%s", buf); /* Process input */ while (!done) { /* Get a key */ i = inkey(); /* Analyze the key */ switch (i) { case ESCAPE: k = 0; done = TRUE; break; case '\n': case '\r': k = strlen(buf); done = TRUE; break; case 0x7F: case '\010': if (k > 0) k--; break; default: if ((k < len - 1) && (isprint(i))) { buf[k++] = i; } else { bell("Illegal edit key!"); } break; } /* Terminate */ buf[k] = '\0'; /* Update the entry */ Term_erase(x, y, len); put_fstr(x, y, "%s", buf); } /* Aborted */ if (i == ESCAPE) return (FALSE); /* Success */ return (TRUE); }
/* * Print some (colored) text to the screen at the current cursor position, * automatically "wrapping" existing text (at spaces) when necessary to * avoid placing any text into the last column, and clearing every line * before placing any text in that line. Also, allow "newline" to force * a "wrap" to the next line. Advance the cursor as needed so sequential * calls to this function will work correctly. * * Once this function has been called, the cursor should not be moved * until all the related "roff()" calls to the window are complete. * * This function will correctly handle any width up to the maximum legal * value of 256, though it works best for a standard 80 character width. */ void roff(cptr str, ...) { int x, y; int w, h; cptr s; byte a = TERM_WHITE; byte da = a; va_list vp; char buf[1024]; /* Begin the Varargs Stuff */ va_start(vp, str); /* Format the args, save the length */ (void)vstrnfmt(buf, 1024, str, &vp); /* End the Varargs Stuff */ va_end(vp); /* Obtain the size */ (void)Term_get_size(&w, &h); /* Obtain the cursor */ (void)Term_locate(&x, &y); /* Process the string */ for (s = buf; *s; s++) { char ch; /* Force wrap */ if (*s == '\n') { /* Wrap */ x = 0; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); continue; } /* Does this character match the escape code? */ if (*s == '$') { /* Scan the next character */ s++; /* Is it a colour specifier? */ if ((*s >= 'A') && (*s <= 'P')) { /* * Save the new colour * * Hack - this depends on ASCII symbols */ a = *s - 'A'; /* Hack -- fake monochrome */ if (!use_color) a = TERM_WHITE; continue; } /* Default colour change? */ else if (*s == 'Q') { /* Save current colour as 'default' */ da = a; continue; } /* Go back to default colour */ else if (*s == 'R') { a = da; continue; } /* * Hack XXX XXX - otherwise, ignore the dollar sign * * This makes "$$" turn into just "$". */ /* Stop if now reach null */ else if (*s == 0) break; } /* Clean up the char */ ch = (isprint(*s) ? *s : ' '); /* Wrap words as needed */ if ((x >= w - 1) && (ch != ' ')) { int i, n = 0; byte av[256]; char cv[256]; /* Wrap word */ if (x < w) { /* Scan existing text */ for (i = w - 2; i >= 0; i--) { /* Grab existing attr/char */ (void)Term_what(i, y, &av[i], &cv[i]); /* Break on space */ if (cv[i] == ' ') break; /* Track current word */ n = i; } } /* Special case */ if (n == 0) n = w; /* Clear line */ Term_erase(n, y, 255); /* Wrap */ x = 0; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); /* Wrap the word (if any) */ for (i = n; i < w - 1; i++) { /* Dump */ Term_addch(av[i], cv[i]); /* Advance (no wrap) */ if (++x > w) x = w; } } /* Dump */ Term_addch(a, ch); /* Advance */ if (++x > w) x = w; } }