void textui_textblock_place(textblock *tb, region orig_area, const char *header) { const char *text = textblock_text(tb); const byte *attrs = textblock_attrs(tb); /* xxx on resize this should be recalculated */ region area = region_calculate(orig_area); size_t *line_starts = NULL, *line_lengths = NULL; size_t n_lines; n_lines = textblock_calculate_lines(tb, &line_starts, &line_lengths, area.width); area.page_rows--; if (n_lines > (size_t) area.page_rows) n_lines = area.page_rows; c_prt(TERM_L_BLUE, header, area.row, area.col); area.row++; display_area(text, attrs, line_starts, line_lengths, n_lines, area, 0); mem_free(line_starts); mem_free(line_lengths); }
void textblock_dump(textblock *tb, char_attr_line **line, int *current_line, int indent, int wrap) { const char *text = textblock_text(tb); const byte *attrs = textblock_attrs(tb); size_t *line_starts = NULL, *line_lengths = NULL; size_t i, j, n_lines; char_attr_line *lline = *line; n_lines = textblock_calculate_lines(tb, &line_starts, &line_lengths, wrap - indent); for (i = 0; i < n_lines; i++) { for (j = 0; j < line_lengths[i]; j++) { dump_put_str(attrs[line_starts[i] + j], format("%c",text[line_starts[i] + j]), j + indent); } (*current_line)++; dump_ptr = (char_attr *) &lline[*current_line]; } if (!n_lines) (*current_line)--; }
/** * Output a textblock to file. */ void textblock_to_file(textblock *tb, ang_file *f, int indent, int wrap_at) { size_t *line_starts = NULL; size_t *line_lengths = NULL; size_t n_lines, i; int width = wrap_at - indent; assert(width > 0); n_lines = textblock_calculate_lines(tb, &line_starts, &line_lengths, width); for (i = 0; i < n_lines; i++) { file_putf(f, "%*c%.*s\n", indent, ' ', line_lengths[i], tb->text + line_starts[i]); } }
void textui_textblock_show(textblock *tb, region orig_area, const char *header) { const char *text = textblock_text(tb); const byte *attrs = textblock_attrs(tb); /* xxx on resize this should be recalculated */ region area = region_calculate(orig_area); size_t *line_starts = NULL, *line_lengths = NULL; size_t n_lines; n_lines = textblock_calculate_lines(tb, &line_starts, &line_lengths, area.width); screen_save(); /* make room for the header & footer */ area.page_rows -= 3; c_prt(TERM_L_BLUE, header, area.row, area.col); area.row++; if (n_lines > (size_t) area.page_rows) { int start_line = 0; c_prt(TERM_WHITE, "", area.row + area.page_rows, area.col); c_prt(TERM_L_BLUE, "(Up/down or ESCAPE to exit.)", area.row + area.page_rows + 1, area.col); /* Pager mode */ while (1) { struct keypress ch; display_area(text, attrs, line_starts, line_lengths, n_lines, area, start_line); ch = inkey(); if (ch.code == ARROW_UP) start_line--; else if (ch.code== ESCAPE || ch.code == 'q') break; else if (ch.code == ARROW_DOWN) start_line++; else if (ch.code == ' ') start_line += area.page_rows; if (start_line < 0) start_line = 0; if (start_line + (size_t) area.page_rows > n_lines) start_line = n_lines - area.page_rows; } } else { display_area(text, attrs, line_starts, line_lengths, n_lines, area, 0); c_prt(TERM_WHITE, "", area.row + n_lines, area.col); c_prt(TERM_L_BLUE, "(Press any key to continue.)", area.row + n_lines + 1, area.col); inkey(); } mem_free(line_starts); mem_free(line_lengths); screen_load(); return; }
int edit_text(char *buffer, int buflen) { int len = strlen(buffer); bool done = FALSE; int cursor = 0; while (!done) { int x, y; struct keypress ke; region area = { 1, HIST_INSTRUCT_ROW + 1, 71, 5 }; textblock *tb = textblock_new(); size_t *line_starts = NULL, *line_lengths = NULL; size_t n_lines; /* Display on screen */ clear_from(HIST_INSTRUCT_ROW); textblock_append(tb, buffer); textblock_append(tb, "\n"); /* XXX This shouldn't be necessary */ textui_textblock_place(tb, area, NULL); n_lines = textblock_calculate_lines(tb, &line_starts, &line_lengths, area.width); /* Set cursor to current editing position */ get_screen_loc(cursor, &x, &y, n_lines, line_starts, line_lengths); Term_gotoxy(1 + x, 19 + y); ke = inkey(); switch (ke.code) { case ESCAPE: return -1; case KC_ENTER: done = TRUE; break; case ARROW_LEFT: if (cursor > 0) cursor--; break; case ARROW_RIGHT: if (cursor < len) cursor++; break; case ARROW_DOWN: { int add = line_lengths[y] + 1; if (cursor + add < len) cursor += add; break; } case ARROW_UP: if (y > 0) { int up = line_lengths[y - 1] + 1; if (cursor - up >= 0) cursor -= up; } break; case KC_END: cursor = MAX(0, len); break; case KC_HOME: cursor = 0; break; case KC_BACKSPACE: case KC_DELETE: { /* Refuse to backspace into oblivion */ if ((ke.code == KC_BACKSPACE && cursor == 0) || (ke.code == KC_DELETE && cursor >= len)) break; /* Move the string from k to nul along to the left by 1 */ if (ke.code == KC_BACKSPACE) memmove(&buffer[cursor - 1], &buffer[cursor], len - cursor); else memmove(&buffer[cursor], &buffer[cursor + 1], len - cursor - 1); /* Decrement */ if (ke.code == KC_BACKSPACE) cursor--; len--; /* Terminate */ buffer[len] = '\0'; break; } default: { bool atnull = (buffer[cursor] == 0); if (!isprint(ke.code)) break; if (atnull) { /* Make sure we have enough room for a new character */ if ((cursor + 1) >= buflen) break; } else { /* Make sure we have enough room to add a new character */ if ((cursor + 1) >= buflen) break; /* Move the rest of the buffer along to make room */ memmove(&buffer[cursor + 1], &buffer[cursor], len - cursor); } /* Insert the character */ buffer[cursor++] = (char)ke.code; len++; /* Terminate */ buffer[len] = '\0'; break; } } textblock_free(tb); } return 0; }