#include #include #include #include #include #include #include #define DEFAULT_PARAGRAPH_WIDTH 160 static void indent( struct fx_paragraph_format *format, struct fx_tty *tty, unsigned int margin) { unsigned int x = 0; while (x < margin) { fx_tty_puts(tty, 0, " "); x++; } } static unsigned int extract_line( const char **sp, unsigned int line_length, fx_string *out, struct fx_paragraph_format *format) { const char *start = *sp; while (isspace(*start) || *start == '\n') { start++; } if (!*start) { return 0; } const char *end = NULL; unsigned int delta = 0; unsigned int i; for (i = 0; start[i]; i++) { if (start[i] == '\033') { while (start[i] && !isalpha(start[i])) { delta++; i++; } delta++; } if (start[i] == '[') { if (start[i + 1] == '[') { delta++; i++; continue; } while (start[i] && start[i] != ']') { i++; delta++; } delta++; } if (!isspace(start[i]) && start[i] != '\n') { continue; } if ((i - delta) >= line_length) { break; } end = &start[i]; if (start[i] == '\n') { break; } } if (start[i] == '\0' && (i - delta) < line_length) { end = NULL; } unsigned int len; if (end) { len = end - start; } else { len = strlen(start); } fx_string_insert_cstrn(out, start, len, FX_NPOS); *sp = end; return len; } static fx_status print_paragraph_tty( const char *str, struct fx_tty *tty, struct fx_paragraph_format *format) { unsigned int w = 0, h = 0; fx_tty_get_dimensions(tty, &w, &h); if (!w) { w = DEFAULT_PARAGRAPH_WIDTH; } unsigned int left_margin = format->p_left_margin; unsigned int line_length = format->p_line_length; if (format->p_left_margin + format->p_right_margin >= w) { return FX_SUCCESS; } unsigned int page_width = w - format->p_left_margin - format->p_right_margin; if (page_width < line_length || line_length == 0) { line_length = page_width; } if (!(format->p_flags & FX_PARAGRAPH_DONT_INDENT_FIRST_LINE)) { indent(format, tty, left_margin); } fx_string *line = fx_string_create(); bool need_indent = false; while (str) { if (*str == '\n') { if (format->p_flags & FX_PARAGRAPH_DOUBLE_LINE_BREAK) { fx_tty_putc(tty, 0, '\n'); } str++; need_indent = true; while (*str == '\n') { if (format->p_flags & FX_PARAGRAPH_MULTI_LINE_BREAK) { fx_tty_putc(tty, 0, '\n'); } str++; } } fx_string_clear(line); unsigned int this_line = extract_line(&str, line_length, line, format); if (this_line == 0) { break; } if (need_indent) { indent(format, tty, left_margin); } fx_tty_puts(tty, 0, fx_string_ptr(line)); fx_tty_putc(tty, 0, '\n'); need_indent = true; } fx_string_unref(line); return FX_SUCCESS; } static fx_status print_paragraph_file( const char *str, FILE *fp, struct fx_paragraph_format *format) { return FX_SUCCESS; } fx_status fx_print_paragraph( const char *str, struct fx_tty *fp, struct fx_paragraph_format *format) { return print_paragraph_tty(str, fp, format); }