Hotpot-proto/btk/btk-text.c
2022-07-06 22:11:01 -04:00

301 lines
6.6 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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;
}