/** * Hack -- load a screen dump from a file * * ToDo: Add support for loading/saving screen-dumps with graphics * and pseudo-graphics. Allow the player to specify the filename * of the dump. */ void do_cmd_load_screen(void) { int i, y, x; int a = 0; wchar_t c = L' '; bool okay = TRUE; ang_file *fp; char buf[1024]; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); fp = file_open(buf, MODE_READ, FTYPE_TEXT); if (!fp) return; /* Save screen */ screen_save(); /* Clear the screen */ Term_clear(); /* Load the screen */ for (y = 0; okay && (y < 24); y++) { /* Get a line of data */ if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; /* Show each row */ for (x = 0; x < 79; x++) { text_mbstowcs(&c, &buf[x], 1); /* Put the attr/char */ Term_draw(x, y, COLOUR_WHITE, c); } } /* Get the blank line */ if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; /* Dump the screen */ for (y = 0; okay && (y < 24); y++) { /* Get a line of data */ if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Look up the attr */ for (i = 0; i < BASIC_COLORS; i++) /* Use attr matches */ if (hack[i] == buf[x]) a = i; /* Put the attr/char */ Term_draw(x, y, a, c); } } /* Close it */ file_close(fp); /* Message */ msg("Screen dump loaded."); event_signal(EVENT_MESSAGE_FLUSH); /* Load screen */ screen_load(); }
/** * 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 */ text_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; int 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; } }
/** * Parses the provided line. * * This runs the first parser hook registered with `p` that matches `line`. */ enum parser_error parser_parse(struct parser *p, const char *line) { char *cline; char *tok; struct parser_hook *h; struct parser_spec *s; struct parser_value *v; char *sp = NULL; assert(p); assert(line); parser_freeold(p); p->lineno++; p->colno = 1; p->fhead = NULL; p->ftail = NULL; /* Ignore empty lines and comments. */ while (*line && (isspace(*line))) line++; if (!*line || *line == '#') return PARSE_ERROR_NONE; cline = string_make(line); tok = strtok(cline, ":"); if (!tok) { mem_free(cline); p->error = PARSE_ERROR_MISSING_FIELD; return PARSE_ERROR_MISSING_FIELD; } h = findhook(p, tok); if (!h) { my_strcpy(p->errmsg, tok, sizeof(p->errmsg)); p->error = PARSE_ERROR_UNDEFINED_DIRECTIVE; mem_free(cline); return PARSE_ERROR_UNDEFINED_DIRECTIVE; } /* There's a little bit of trickiness here to account for optional * types. The optional flag has a bit assigned to it in the spec's type * tag; we compute a temporary type for the spec with that flag removed * and use that instead. */ for (s = h->fhead; s; s = s->next) { int t = s->type & ~PARSE_T_OPT; p->colno++; /* These types are tokenized on ':'; strings are not tokenized * at all (i.e., they consume the remainder of the line) */ if (t == PARSE_T_INT || t == PARSE_T_SYM || t == PARSE_T_RAND || t == PARSE_T_UINT) { tok = strtok(sp, ":"); sp = NULL; } else if (t == PARSE_T_CHAR) { tok = strtok(sp, ""); if (tok) sp = tok + 2; } else { tok = strtok(sp, ""); sp = NULL; } if (!tok) { if (!(s->type & PARSE_T_OPT)) { my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_MISSING_FIELD; mem_free(cline); return PARSE_ERROR_MISSING_FIELD; } break; } /* Allocate a value node. */ v = mem_alloc(sizeof *v); v->spec.next = NULL; v->spec.type = s->type; v->spec.name = s->name; /* Parse out its value. */ if (t == PARSE_T_INT) { char *z = NULL; v->u.ival = strtol(tok, &z, 0); if (z == tok) { mem_free(v); mem_free(cline); my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_NOT_NUMBER; return PARSE_ERROR_NOT_NUMBER; } } else if (t == PARSE_T_UINT) { char *z = NULL; v->u.uval = strtoul(tok, &z, 0); if (z == tok || *tok == '-') { mem_free(v); mem_free(cline); my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_NOT_NUMBER; return PARSE_ERROR_NOT_NUMBER; } } else if (t == PARSE_T_CHAR) { text_mbstowcs(&v->u.cval, tok, 1); } else if (t == PARSE_T_SYM || t == PARSE_T_STR) { v->u.sval = string_make(tok); } else if (t == PARSE_T_RAND) { if (!parse_random(tok, &v->u.rval)) { mem_free(v); mem_free(cline); my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_NOT_RANDOM; return PARSE_ERROR_NOT_RANDOM; } } /* Link it into the value list. */ if (!p->fhead) p->fhead = v; else p->ftail->spec.next = &v->spec; p->ftail = v; } mem_free(cline); p->error = h->func(p); return p->error; }