static void textblock_vappend_c(textblock *tb, byte attr, const char *fmt, va_list vp) { while (1) { va_list args; size_t len; size_t remaining = tb->size - tb->strlen; char *fmt_start = tb->text + tb->strlen; VA_COPY(args, vp); len = vstrnfmt(fmt_start, remaining, fmt, args); va_end(args); if (len < remaining - 1) { byte *attr_start = tb->attrs + (tb->strlen * sizeof *tb->attrs); memset(attr_start, attr, len * sizeof *tb->attrs); tb->strlen += len; break; } tb->size = TEXTBLOCK_LEN_INCR(tb->size); tb->text = mem_realloc(tb->text, tb->size); tb->attrs = mem_realloc(tb->attrs, tb->size * sizeof *tb->attrs); } }
/* * Get a string from the user * * The "prompt" should take the form "Prompt: " * * Note that the initial contents of the string is used as * the default response, so be sure to "clear" it if needed. * * We clear the input, and return FALSE, on "ESCAPE". */ bool get_string(char *buf, int len, cptr str, ...) { bool res; va_list vp; char prompt[1024]; /* Begin the Varargs Stuff */ va_start(vp, str); /* Format the args, save the length */ (void)vstrnfmt(prompt, 1024, str, &vp); /* End the Varargs Stuff */ va_end(vp); /* Paranoia XXX XXX XXX */ message_flush(); /* Display prompt */ prtf(0, 0, prompt); /* Ask the user for a string */ res = askfor_aux(buf, len); /* Clear prompt */ clear_msg(); /* Result */ return (res); }
/* * Center a format string in the buffer. * * The first parameter on the stack must be the width * to center in. * * The second must be the string to center with. * This is treated as a format string - so may contain * other commands etc... */ void center_string(char *buf, uint max, cptr fmt, va_list *vp) { int i, j; cptr str; char tmp[1024]; int size; /* Unused parameter */ (void)fmt; /* Get the size of the string to center in */ size = va_arg(*vp, int); /* Get the string to center with. */ str = va_arg(*vp, cptr); /* Expand the string */ vstrnfmt(tmp, 1024, str, vp); /* Total length */ i = strlen(tmp); /* Necessary border */ j = (size - i) / 2; /* Mega-Hack center the (format) string in the buffer */ strnfmt(buf, max, "%*s%s%*s", j, "", tmp, size - i - j, ""); }
/** * Append a formatted line of text to the end of file 'f'. * * file_vputf() is the va_list version. It returns TRUE if the write was * successful and FALSE otherwise. */ bool file_vputf(ang_file *f, const char *fmt, va_list vp) { char buf[1024]; if (!f) return FALSE; (void)vstrnfmt(buf, sizeof(buf), fmt, vp); return file_put(f, buf); }
void msgt(unsigned int type, const char *fmt, ...) { va_list vp; char buf[1024]; va_start(vp, fmt); vstrnfmt(buf, sizeof(buf), fmt, vp); va_end(vp); sound(type); msg_print_aux(type, buf); }
/* * Append a formatted line of text to the end of file 'f'. */ bool file_putf(ang_file *f, const char *fmt, ...) { char buf[1024]; va_list vp; va_start(vp, fmt); (void)vstrnfmt(buf, sizeof(buf), fmt, vp); va_end(vp); return file_put(f, buf); }
/* Note: Angband uses proprietary format strings, like %^s that string_vprintf() won't handle. So, let's hope 1024 is enough for every message! (It should be ...) */ void msg_format(cptr fmt, ...) { va_list vp; char buf[1024]; va_start(vp, fmt); (void)vstrnfmt(buf, 1024, fmt, vp); va_end(vp); cmsg_print(TERM_WHITE, buf); }
void cmsg_format(byte color, cptr fmt, ...) { va_list vp; char buf[1024]; va_start(vp, fmt); (void)vstrnfmt(buf, 1024, fmt, vp); va_end(vp); cmsg_print(color, buf); }
/* * Output text to the screen or to a file depending on the * selected hook. Takes strings with "embedded formatting", * such that something within {red}{/} will be printed in red. * * Note that such formatting will be treated as a "breakpoint" * for the printing, so if used within words may lead to part of the * word being moved to the next line. */ void text_out_e(const char *fmt, ...) { char buf[1024]; char smallbuf[1024]; va_list vp; const char *start, *next, *text, *tag; size_t textlen, taglen = 0; /* Begin the Varargs Stuff */ va_start(vp, fmt); /* Do the va_arg fmt to the buffer */ (void)vstrnfmt(buf, sizeof(buf), fmt, vp); /* End the Varargs Stuff */ va_end(vp); start = buf; while (next_section(start, 0, &text, &textlen, &tag, &taglen, &next)) { int a = -1; memcpy(smallbuf, text, textlen); smallbuf[textlen] = 0; if (tag) { char tagbuffer[11]; /* Colour names are less than 11 characters long. */ assert(taglen < 11); memcpy(tagbuffer, tag, taglen); tagbuffer[taglen] = '\0'; a = color_text_to_attr(tagbuffer); } if (a == -1) a = TERM_WHITE; /* Output now */ text_out_hook(a, smallbuf); start = next; } }
/* * Output text to the screen (in color) or to a file depending on the * selected hook. */ void text_out_c(byte a, const char *fmt, ...) { char buf[1024]; va_list vp; /* Begin the Varargs Stuff */ va_start(vp, fmt); /* Do the va_arg fmt to the buffer */ (void)vstrnfmt(buf, sizeof(buf), fmt, vp); /* End the Varargs Stuff */ va_end(vp); /* Output now */ text_out_hook(a, buf); }
/* * Format and translate a string, then print it out to file. */ bool x_file_putf(ang_file *f, const char *fmt, ...) { va_list vp; char buf[1024]; /* Begin the Varargs Stuff */ va_start(vp, fmt); /* Format the args, save the length */ (void)vstrnfmt(buf, sizeof(buf), fmt, vp); /* End the Varargs Stuff */ va_end(vp); return file_put(f, buf); }
bool get_check(cptr prompt, ...) { va_list vp; char buf[1024]; /* Begin the Varargs Stuff */ va_start(vp, prompt); /* Format the args, save the length */ (void)vstrnfmt(buf, 1024, prompt, &vp); /* End the Varargs Stuff */ va_end(vp); return get_check_base(FALSE, FALSE, buf); }
/* * Use a format string with spoil_out(). */ static void spoil_out(cptr fmt, ...) { if (fmt) { char buf[1024]; va_list vp; va_start(vp, fmt); vstrnfmt(buf, sizeof(buf), fmt, vp); va_end(vp); spoil_out_aux(buf); } else { spoil_out_aux(fmt); } }
/* * Like the above roff(), print lines. * However, print them to a file like fprintf(). * * froff() is smarter than fprintf() though. * It will also understand the '%v' format control sequence. */ void froff(FILE *fff, cptr str, ...) { 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); /* Output it to the file */ fprintf(fff, "%s", buf); }
/* * Display a formatted message, using "vstrnfmt()" and "msg("%s", )". */ void msg(const char *fmt, ...) { va_list vp; char buf[1024]; /* Begin the Varargs Stuff */ va_start(vp, fmt); /* Format the args, save the length */ (void)vstrnfmt(buf, sizeof(buf), fmt, vp); /* End the Varargs Stuff */ va_end(vp); /* Display */ msg_print_aux(MSG_GENERIC, buf); }
/* Abort the borg, give a text with formatting */ void borg_oops(cptr fmt, ...) { va_list vp; char buf[1024]; /* Begin the Varargs Stuff */ va_start(vp, fmt); /* Format the args, save the length */ (void)vstrnfmt(buf, 1024, fmt, &vp); /* End the Varargs Stuff */ va_end(vp); /* Display */ borg_oops_aux(buf); }
/* * Put a string with formatting information at a given location. * Clear the line before we start printing. */ void prtf(int col, int row, cptr str, ...) { 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); /* Display */ put_cstr(col, row, buf, TRUE); }
/** * Add a new line to the panel */ static void panel_line(struct panel *p, byte attr, const char *label, const char *fmt, ...) { va_list vp; struct panel_line *pl; /* Get the next panel line */ assert(p); assert(p->len != p->max); pl = &p->lines[p->len++]; /* Set the basics */ pl->attr = attr; pl->label = label; /* Set the value */ va_start(vp, fmt); vstrnfmt(pl->value, sizeof pl->value, fmt, vp); va_end(vp); }
/** * Format and translate a string, then print it out to file. */ void x_fprintf(ang_file *f, int encoding, const char *fmt, ...) { va_list vp; char buf[1024]; /* Begin the Varargs Stuff */ va_start(vp, fmt); /* Format the args, save the length */ (void)vstrnfmt(buf, sizeof(buf), fmt, vp); /* End the Varargs Stuff */ va_end(vp); /* Translate */ xstr_trans(buf, encoding); file_put(f, buf); }
/* * 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; } }