301 lines
6.6 KiB
C
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;
|
||
|
}
|