#include #include #include #include "btk-text.h" /* mode for difference between backspace and del */ /* mode == 0 : backspace; mode == 1 : del */ int btk_text_del_char(char *dest, int pos, int mode) { int dest_n = strlen(dest); if (mode && !(dest_n - pos)) return 0; if (!mode && !pos) return 0; for (int i = pos - 1 + mode; i < dest_n; i++) dest[i] = dest [i + 1]; return 1; } int btk_text_insert_char(char *dest, char src, int pos, int max_w) { int dest_n = strlen(dest); if (dest_n >= max_w - 1) return 0; for (int i = dest_n; i >= pos; i--) dest[i + 1] = dest[i]; dest[pos] = src; return 1; } /***************************************************************************************/ btk_pos_t btk_text_caret_1dto2d(btk_par_t *par, int caret) { int c = caret; btk_pos_t pos = {0, 0}; if (caret <= 0) return pos; /* add previous rows qtt */ for (int i = 0; i < par->rows_n; i++) { if (c >= par->rows_w[i]) { c -= par->rows_w[i]; } else { pos.y = i; break; } } /* compensation for indentation at the beginning of row*/ if (*(par->rows_shadow + pos.y * par->rows_max_w) == 's') while (*(par->rows_shadow + pos.y * par->rows_max_w + pos.x) == 's') pos.x++; /* add current row qtt */ for (int i = 0; i < c; i++) { pos.x++; while (*(par->rows_shadow + pos.y * par->rows_max_w + pos.x) == 's') pos.x++; } return pos; } int btk_text_caret_2dto1d(btk_par_t *par, btk_pos_t pos) { int caret = 0; for (int i = 0; i < pos.y; i++) caret += par->rows_w[i]; for (int i = 0; i < pos.x; i++) if (*(par->rows_shadow + pos.y * par->rows_max_w + i) != 's') caret++; return caret; } void btk_text_destroy_par(btk_par_t *par) { if (!par) return; free(par->rows); free(par->rows_shadow); free(par->rows_spot); free(par->rows_w); free(par); } btk_par_t* btk_text_get_par(char *text, unsigned int rows_max_w) { if (!text || !rows_max_w) { return NULL; } int text_n = strlen(text); int buffer_n = 1; btk_par_t *par = malloc(sizeof(btk_par_t)); par->rows_n = 0; par->rows_max_w = rows_max_w; par->rows = malloc(buffer_n * rows_max_w); par->rows_shadow = malloc(buffer_n * rows_max_w); par->rows_spot = malloc(buffer_n * sizeof(int)); par->rows_w = malloc(buffer_n * sizeof(int)); par->rows_w[0] = 0; int pos = 0; int a = 0, b = 0; int first = 1; int indent = 0; int cl = 0, cr = 0; for (int i = 0;; i++) { /* set base row indentation level */ if (!pos) { b = indent >= rows_max_w ? rows_max_w : indent; for (int j = 0; j < b; j++, pos++) { par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; } } par->rows_w[par->rows_n]++; switch(text[i]) { case '\0': par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 'e'; pos++; cr = 1; goto row_end; case '\n': par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 'n'; pos++; cr = 1; goto row_end; case '\t': par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 't'; a = btk_tab_size - pos % (btk_tab_size); b = pos + a >= rows_max_w - 1 ? rows_max_w - 1 : pos + a; pos++; for (int j = pos; j < b; j++, pos++) { par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; } if (first) indent += btk_tab_size; if (b == rows_max_w - 1) goto row_end; break; case '>': if (!first) goto char_input; cl = 1; par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = '>'; pos++; par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; pos++; par->rows[pos + par->rows_n * rows_max_w] = '>'; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; pos++; par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; pos++; indent += 4; first = 0; break; case '-': if (!first) goto char_input; par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = '-'; pos++; par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; pos++; par->rows[pos + par->rows_n * rows_max_w] = '-'; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; pos++; par->rows[pos + par->rows_n * rows_max_w] = ' '; par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; pos++; indent += 4; first = 0; break; case '#': cl = first ? 2 : cl; goto char_input; case '!': cl = first ? 4 : cl; goto char_input; default: char_input: par->rows[pos + par->rows_n * rows_max_w] = text[i]; par->rows_shadow[pos + par->rows_n * rows_max_w] = '_'; pos++; first = 0; break; } if (pos >= rows_max_w - 1 || i == text_n) { row_end: par->rows[pos + par->rows_n * rows_max_w] = '\0'; par->rows_shadow[pos + par->rows_n * rows_max_w] = '\0'; par->rows_spot[par->rows_n] = cl; par->rows_n++; pos = 0; if (cr) { cr = 0; cl = 0; indent = 0; first = 1; } par->rows_w[par->rows_n] = 0; if (text[i] == '\0') break; } if (par->rows_n >= buffer_n - 1) { buffer_n += 1; par->rows = realloc(par->rows, buffer_n * rows_max_w); par->rows_shadow = realloc(par->rows_shadow, buffer_n * rows_max_w); par->rows_spot = realloc(par->rows_spot, buffer_n * sizeof(int)); par->rows_w = realloc(par->rows_w, buffer_n * sizeof(int)); } } /* printf("%i rows :\n", par->rows_n); for (int i = 0; i < par->rows_n; i++) printf("row %i\n", par->rows_w[i]); printf("\n"); */ return par; } int btk_text_guard_1d_caret(char *text, int caret) { int new_caret = caret; int text_n = strlen(text); if (new_caret < 0) new_caret = 0; if (new_caret > text_n) new_caret = text_n; return new_caret; } btk_pos_t btk_text_guard_2d_caret(btk_par_t *par, btk_pos_t pos) { btk_pos_t new_pos = pos; if (new_pos.y <= 0) new_pos.y = 0; if (new_pos.y >= par->rows_n) new_pos.y = par->rows_n - 1; if (new_pos.x < 0) new_pos.x = 0; if (new_pos.x > strlen(par->rows + new_pos.y * par->rows_max_w) - 1) new_pos.x = strlen(par->rows + new_pos.y * par->rows_max_w) - 1; /*if (new_pos.x > par->rows_w[new_pos.y] - 1) new_pos.x = par->rows_w[new_pos.y] - 1;*/ while (*(par->rows_shadow + pos.y * par->rows_max_w + new_pos.x) == 's') new_pos.x++; return new_pos; }