чување b39e5e9e8e2aefcb6118893e8cda089c01b2e6c0
родитељ 4124504b05c76685589802362d58ba3095d65c93
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Fri, 9 Jul 2021 13:43:50 +0200
Finished work on u32_draw_string wrt tabs
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | draw.c | | | 270 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
| M | draw.h | | | 4 | ++-- |
| M | poe.c | | | 14 | +++++++------- |
| M | tabs.draft | | | 108 | +++++++++++++++++++++---------------------------------------------------------- |
| M | util.h | | | 1 | + |
измењених датотека: 5, додавања: 195(+), брисања: 202(-)
diff --git a/draw.c b/draw.c
@@ -271,158 +271,200 @@ draw_box(const int startx, const int endx, const int starty, const int endy,
tb_change_cell(x, endy-1, ' ', SHADOW_FG, SHADOW_BG);
}
+/* mc - (max cols) pack text and padding into this many columns
+ * fc - (fill cols) this many columns from the left/right/center will be
+ * filled
+ * p_? - (padding) this many cells will be skipped from ? side
+ * ds - (display start) string starts being displayed from this display column
+ * counted from the start of the string; an "entry point" joining string
+ * index with screen
+ * fill - boolean; 1 = fill fc, 0 = don't fill fc
+ * */
const char*
draw_string(const int x, const int y, const uint16_t fg, const uint16_t bg,
- const char* s, const int max_cols, const int fill_cols,
- const int padding_left, const int padding_right,
- const Alignment align, const int display_starts_at)
+ const char* s, const int mc, const int fc,
+ const int p_l, const int p_r,
+ const Alignment align, const int ds, const int fill)
{
uint32_t* us = calloc(strlen(s)+1, sizeof(uint32_t));
if (!us)
return NULL;
- u8_string_to_unicode(us, s, max_cols);
- u32_draw_string(x, y, fg, bg, us, max_cols, fill_cols,
- padding_left, padding_right, align, display_starts_at);
+ u8_string_to_unicode(us, s, mc);
+ u32_draw_string(x, y, fg, bg, us, mc, fc, p_l, p_r, align, ds, fill);
free(us);
return s;
}
-/* mc - pack text and padding into this many columns
- * fc - this many columns from the left/right/center will be filled
- * p_? - this many cells will be skipped from ? side
- * ds - string starts being displayed from this column (will fit into c) */
+/* mc - (max cols) pack text and padding into this many columns
+ * fc - (fill cols) this many columns from the left/right/center will be
+ * filled
+ * p_? - (padding) this many cells will be skipped from ? side
+ * ds - (display start) string starts being displayed from this display column
+ * counted from the start of the string; an "entry point" joining string
+ * index with screen
+ * fill - boolean; 1 = fill fc, 0 = don't fill fc
+ * */
void
u32_draw_string(const int x, const int y, const uint16_t fg, const uint16_t bg,
const uint32_t* s, const int mc, const int fc,
const int p_l, const int p_r,
- const Alignment align, const int ds)
+ const Alignment align, const int ds, const int fill)
{
- int d = 0; /* distance, in screen columns, from x to visible
- * part of the string, followed by p_l */
-
- int c = 0; /* distance in screen columns from
- * d + p_l to mc - p_r (part of the displayed string
- * containing text, between padding;
- * string fits within this many columns */
-
- int r = 0; /* current rune; goes from 0..c */
-
- int i = 0; /* string index */
-
/*
* <-------- visible part ---------->
* +---------+-------+----------------+---------+
- * |d=0 | |c=0 | |
+ * | | | | |
* |<-- d -->|<-p_l->|<------ c ----->|<- p_r ->|
* | |<-------------- mc -------------->|
* |<------------------ fc -------------------->|
- * x (align == RIGHT here)
+ * x | |
+ * ds ds+c
+ * <.....(sc).....>
+ * (align == RIGHT in this case)
* */
- const uint32_t* ps = s;
- size_t len = u32_strlen(s);
+
+ int d = 0; /* distance, in screen columns, from x to
+ * visible part of the string, followed by
+ * p_l */
+
+ int c = 0; /* distance in screen columns from
+ * d + p_l to d + mc - p_r (part of the
+ * displayed string containing text, between
+ * padding; string fits within this many columns
+ * */
+
+ int sc = 0; /* current screen column; goes from 0..c-1
+ * only increased when actual characters are
+ * written
+ */
+
+ int ssc = 0; /* current string screen column; goes from start
+ * of the string until ds+c */
+
+ const int ts = TAB_SIZE;
+
+ const uint32_t* ps = s; /* pointer to current character in string;
+ * string index: ps-s */
c = mc - p_l - p_r;
+
if (align == LEFT)
- {
d = 0;
- for (r = 0; r < fc; r++) /* r wraps p_? here for filling */
- tb_change_cell(x + d + r, y, ' ', fg, bg);
- }
else if (align == RIGHT)
- {
- d = fc - mc;
- /* r wraps p_? here for filling */
- for (r = 0; r < mc; r++)
- tb_change_cell(x + d + r, y, ' ', fg, bg);
- }
+ d = fc >= mc ? fc-mc : 0;
else if (align == CENTER)
- {
- d = (fc - mc)/2;
- for (r = 0; r < mc; r++)
- tb_change_cell(x + d + r, y, ' ', fg, bg);
- }
+ d = fc >= mc ? (fc - mc)/2 : 0;
+
+ /* fill */
+ if (fill)
+ for (int j = 0; j < fc; j++)
+ tb_change_cell(x+j, y, ' ', fg, bg);
+
+ /* left padding */
+ for (int j = 0; j < p_l; j++)
+ tb_change_cell(x+d+j, y, ' ', fg, bg);
+
+ sc = 0;
- r = 0;
- i = 0;
- while (ps && *ps && r < c)
+ /*
+ * main idea: we go from start of the string to the end and count
+ * displayed characters until we get to ds, then we also output
+ * characters; tabs count as spaces up to multiple of ts, counted from
+ * the start of the string
+ *
+ * exit condition is also sc == c, when we have reached the maximum
+ * number of characters to output
+ * */
+ while (ps && *ps && sc < c)
{
if (*ps == '\t')
{
- if (i < ds)
+ if (ssc < ds)
{
- /* col+TAB_SIZE
- * \t |
- * ------[ :::|: ]
- * | | c+padding_left=c+2
- * | c
- * i
+ /* ssc-(ssc%ts)+ts
+ * \t | = ssc+(ts-(ssc%ts))
+ * ----------|-----[ :|::: ]
+ * | | |
+ * | | ds
+ * ssc-(ssc%ts) |
+ * ssc
* */
- if ()
+ if (ssc - (ssc % ts) + ts >= ds)
{
- for (int j = 0; j < ;
+ for (int j = 0; j < ssc-(ssc%ts)+ts-ds;
j++)
- tb_change_cell(x+padding_left+
- j, y, ' ', fg, bg);
+ tb_change_cell(x+d+p_l+sc+j, y,
+ ' ', fg, bg);
+ sc += (ts - (ssc % ts));
}
- /*
+ /* else, just increase counter
+ *
* \t
* ----------|----[ ::::: ]
- * | | |
- * | | c
- * | col+TAB_SIZE
- * col
+ * | | |
+ * | | ds
+ * | ssc-(ssc%ts)+ts
+ * ssc = ssc + (ts-(ssc%ts))
* */
- col += TAB_SIZE;
+ ssc += (ts - (ssc % ts));
}
- else
+ else /* ssc >= ds */
{
/*
- * col+TAB_SIZE = col+end
- * \t |
+ * ds ssc+(ts-(ssc%ts))
+ * | \t |
* [ ::::::: ]---|-----
- * | |
- * | dlimit
- * col = (col - start) + start
+ * | |
+ * | ds+c
+ * ssc
* */
- int dlimit = max_cols-padding_right;
- if (col + end >= dlimit)
+ if (ssc+(ts-(ssc%ts)) >= ds+c)
{
- int spaces = dlimit - col;
- for (int j = 0; j < spaces; j++)
- tb_change_cell(x+padding_left+
- col+j, y, ' ', fg, bg);
- col += spaces;
+ for (int j = 0; j < ds+c-ssc; j++)
+ tb_change_cell(x+d+p_l+sc+j,
+ y, ' ', fg, bg);
+ sc = c;
+ ssc = ds+c;
}
- /*
+ else /* ssc+(ts-(ssc%ts)) < ds+c */
+ {
+ /*
* \t
* [ :::::::::::|::: ]-----
- * | | | |
- * | | | dlimit
- * | | col+TAB_SIZE
- * | col
- * c
+ * | | | |
+ * | | | ds+c
+ * | | ssc+(ts-(ssc%ts))
+ * | ssc
+ * ds
* */
- else
- {
- for (int j = start; j < end; j++)
- tb_change_cell(x+padding_left+
- (col-start)+j, y, ' ',
- fg, bg);
- col += TAB_SIZE;
+ for (int j = 0; j < ts-(ssc%ts); j++)
+ tb_change_cell(x+d+p_l+sc+j,
+ y, ' ', fg, bg);
+ sc += ts-(ssc%ts);
+ ssc += ts-(ssc%ts);
}
}
}
else
{
- if (col >= c)
- tb_change_cell(x+padding_left+col-c, y, *ps,
- fg, bg);
- col++;
+ if (ssc >= ds)
+ {
+ if (sc < c)
+ tb_change_cell(x+d+p_l+sc, y, *ps,
+ fg, bg);
+ sc++;
+ }
+ ssc++;
}
ps++;
}
+
+ /* right padding */
+ for (int j = 0; j < p_r; j++)
+ tb_change_cell(x+d+p_l+c+j, y, ' ', fg, bg);
+
}
const struct DrawState*
@@ -446,12 +488,13 @@ draw_help(const struct DrawState* state)
draw_box(startx, endx, starty, endy, DLG_FG, DLG_BG);
if (!draw_string(startx, starty, TITLE_FG, TITLE_BG,
- help_title, w-2, strlen(help_title)+2, 1, 1, CENTER, 0))
+ help_title, strlen(help_title)+2, w-2, 1, 1, CENTER,
+ 0, 0))
return NULL;
while (row < LEN(help))
{
if (!draw_string(startx+1, starty+1+row, DLG_FG, DLG_BG,
- help[row], w-2, w-2, 2, 2, LEFT, 0))
+ help[row], w-2, w-2, 2, 2, LEFT, 0, 1))
return NULL;
row++;
}
@@ -486,8 +529,8 @@ draw_editbox(const struct DrawState* state)
draw_box(startx, endx, starty, endy, DLG_FG, DLG_BG);
if (!draw_string(startx+1, starty, TITLE_FG, TITLE_BG,
- editbox_title, w-2,
- strlen(editbox_title)+2, 1, 1, CENTER, 0))
+ editbox_title, strlen(editbox_title)+2, w-2, 1, 1,
+ CENTER, 0, 0))
return NULL;
uint16_t fg = state->edit_info_focused ? EDIT_MSGID_FOCUS_FG :
@@ -511,15 +554,15 @@ draw_editbox(const struct DrawState* state)
curline->bg == 0 ? bg : curline->bg,
curline->text,
w-2, w-2, 1, 1, LEFT,
- state->info_first_shown_column);
+ state->info_first_shown_column, 1);
}
if (state->info_first_shown_row > 0)
u32_draw_string(endx-2, starty+1, fg, bg, (uint32_t*)L"\u2191",
- 1, 1, 0, 0, LEFT, 0);
+ 1, 1, 0, 0, LEFT, 0, 0);
if (state->info_first_shown_row + (h-3)/2 < state->info_rows_count)
u32_draw_string(endx-2, starty+(h-3)/2, fg, bg,
- (uint32_t*)L"\u2193", 1, 1, 0, 0, LEFT, 0);
+ (uint32_t*)L"\u2193", 1, 1, 0, 0, LEFT, 0, 0);
fg = state->edit_info_focused ? EDIT_MSGSTR_FG :
EDIT_MSGSTR_FOCUS_FG;
@@ -540,7 +583,7 @@ draw_editbox(const struct DrawState* state)
u32_draw_string(startx+1, endy-h/2-1+i,
fg, bg, curline->text,
w-2, w-2, 1, 1, LEFT,
- state->input_first_shown_column);
+ state->input_first_shown_column, 1);
}
if (state->edit_info_focused)
@@ -569,11 +612,11 @@ draw_editbox(const struct DrawState* state)
state->input_first_shown_row,
state->input_rows_count);
draw_string(startx+1, endy-2, DLG_FG, DLG_BG,
- sbuf, w-2, strlen(sbuf)+2, 1, 1, LEFT, 0);
+ sbuf, strlen(sbuf)+2, w-2, 1, 1, LEFT, 0, 0);
if (entry->flags != FL_NONE)
if (!draw_string(endx-MAXFLAGSBUF-4-5, endy-2, DLG_FG, DLG_BG,
flags_buf, MAXFLAGSBUF+4-1, MAXFLAGSBUF+4-1, 0,
- 0, LEFT, 0))
+ 0, LEFT, 0, 0))
return NULL;
return state;
}
@@ -599,9 +642,9 @@ draw_search(const struct DrawState* state)
SEARCH_EDIT_BG);
if (len > state->search_input_first_shown_column)
u32_draw_string(startx+1, starty+1,
- SEARCH_EDIT_FG, SEARCH_EDIT_BG, state->search +
- state->search_input_first_shown_column,
- w-3, w-3, 0, 0, LEFT, state->input_first_shown_column);
+ SEARCH_EDIT_FG, SEARCH_EDIT_BG, state->search,
+ w-3, w-3, 0, 0, LEFT, state->input_first_shown_column,
+ 1);
tb_set_cursor(startx+1+state->search_input_display_column -
state->search_input_first_shown_column,
starty+1);
@@ -623,13 +666,13 @@ draw_status(const struct DrawState* state)
{
if (!draw_string(0, state->maxy-1, PROMPT_FG, PROMPT_BG,
state->prompt, state->maxx, state->maxx, 1, 1,
- CENTER, 0))
+ CENTER, 0, 1))
return NULL;
}
else if (state->error && state->error[0])
{
if (!draw_string(0, state->maxy-1, ERROR_FG, ERROR_BG, state->error,
- state->maxx, state->maxx, 1, 1, CENTER, 0))
+ state->maxx, state->maxx, 1, 1, CENTER, 0, 1))
return NULL;
}
else
@@ -645,8 +688,9 @@ draw_status(const struct DrawState* state)
if (pseg == status_segments + LEN(status_segments)-1)
seg_size = state->maxx-1 - current_start;
if (!draw_string(current_start, state->maxy-1, pseg->fg,
- pseg->bg, buf, seg_size, seg_size, 1, 1,
- pseg->alignment, 0))
+ pseg->bg, buf,
+ MIN(seg_size, strlen(buf)+2), seg_size,
+ 1, 1, pseg->alignment, 0, 1))
return NULL;
pseg++;
current_start += seg_size;
@@ -684,7 +728,7 @@ draw_list_visible(const struct DrawState* state)
if (!draw_string(0, cy, sel ? LIST_FLAGS_SEL_FG : LIST_FLAGS_FG,
sel ? LIST_FLAGS_SEL_BG : LIST_FLAGS_BG,
flags_buf, MAXFLAGSBUF-1+2, MAXFLAGSBUF-1+2,
- 2, 0, LEFT, 0))
+ 2, 0, LEFT, 0, 1))
return NULL;
if (current->msgid)
u32_draw_string(MAXFLAGSBUF-1+2, cy, sel ?
@@ -693,7 +737,7 @@ draw_list_visible(const struct DrawState* state)
current->msgid,
state->maxx/2-MAXFLAGSBUF+1-2,
state->maxx/2-MAXFLAGSBUF+1-2, 2, 0,
- LEFT, 0);
+ LEFT, 0, 1);
else if (current == state->entries) /* special */
draw_string(MAXFLAGSBUF-1+2, cy, sel ?
LIST_MSGID_SPECIAL_SEL_FG :
@@ -703,7 +747,7 @@ draw_list_visible(const struct DrawState* state)
first_entry_msgid,
state->maxx/2-MAXFLAGSBUF+1-2,
state->maxx/2-MAXFLAGSBUF+1-2, 2, 0,
- LEFT, 0);
+ LEFT, 0, 1);
/* don't use msgstr_index as then the entire list will shift
* when changing currently displayed plural form msgstr in an
@@ -718,7 +762,7 @@ draw_list_visible(const struct DrawState* state)
*(current->msgstr /*+
state->msgstr_index*/),
state->maxx/2, state->maxx/2, 2, 2,
- LEFT, 0);
+ LEFT, 0, 1);
i++;
cy++;
}
diff --git a/draw.h b/draw.h
@@ -102,11 +102,11 @@ void draw_box(const int startx, const int endx, const int starty,
const char* draw_string(const int x, const int y, const uint16_t fg, const
uint16_t bg, const char* s, const int max_cols, const int
fill_cols, const int padding_left, const int padding_right,
- const Alignment align, const int display_starts_at);
+ const Alignment align, const int ds, const int fill);
void u32_draw_string(const int x, const int y, const uint16_t fg, const uint16_t bg,
const uint32_t* s, const int max_cols, const int fill_cols,
const int padding_left, const int padding_right,
- const Alignment align, const int display_starts_at);
+ const Alignment align, const int ds, const int fill);
const struct DrawState* draw_help(const struct DrawState* state);
const struct DrawState* draw_editbox(const struct DrawState* state);
const struct DrawState* draw_search(const struct DrawState* state);
diff --git a/poe.c b/poe.c
@@ -763,10 +763,10 @@ move_up(struct DrawState* state)
state->input_display_column);
if (state->input_first_shown_column > state->input_display_column)
state->input_first_shown_column = state->input_display_column;
- if (state->input_first_shown_column + EDIT_WIDTH-5 <
+ if (state->input_first_shown_column + EDIT_WIDTH-4 <
state->input_display_column)
state->input_first_shown_column = state->input_display_column -
- EDIT_WIDTH+5;
+ EDIT_WIDTH+4;
state->input_display_column = display_length(state,
state->input_buffer[state->input_row].text,
state->input_column);
@@ -803,10 +803,10 @@ move_down(struct DrawState* state)
state->input_display_column);
if (state->input_first_shown_column > state->input_display_column)
state->input_first_shown_column = state->input_display_column;
- if (state->input_first_shown_column + EDIT_WIDTH-5 <
+ if (state->input_first_shown_column + EDIT_WIDTH-4 <
state->input_display_column)
state->input_first_shown_column = state->input_display_column -
- EDIT_WIDTH+5;
+ EDIT_WIDTH+4;
state->input_display_column = display_length(state,
state->input_buffer[state->input_row].text,
state->input_column);
@@ -878,9 +878,9 @@ move_right(struct DrawState* state)
state->input_column++;
if (state->input_display_column - state->input_first_shown_column
- > EDIT_WIDTH-3)
+ > EDIT_WIDTH-4)
state->input_first_shown_column = state->input_display_column
- - EDIT_WIDTH+3;
+ - EDIT_WIDTH+4;
}
void
@@ -901,7 +901,7 @@ move_end(struct DrawState* state)
state->input_row].text, state->input_column);
state->input_display_column = dlen;
if (dlen > EDIT_WIDTH-3)
- state->input_first_shown_column = dlen - EDIT_WIDTH+3;
+ state->input_first_shown_column = dlen - EDIT_WIDTH+4;
else
state->input_first_shown_column = 0;
}
diff --git a/tabs.draft b/tabs.draft
@@ -1,84 +1,32 @@
- s - string
- x - starting column
- y - starting row
- c - first screen column
- t - index in string containing \t
- max_cols = w - max screen width
- col = d - current screen column
-
- w = padding_left + ... + padding_right
-
-
-01 234567890123456 7
-f\t test_with_tabs\t;
-012[45670123456701234567]123456701234567012345670123456701234567
-f------>test_with_tabs->]
-f [----test_with_tabs--]
-012[45678901234567890123]567890123456789012345678901234567890123456789
- |
- t = 1
-012[45678901234567890123]567890123456789012345678901234567890123456789
- | |<--c+w=24
- c = 4 |
- [01234567890123456789]1234567890123456789012345678901234567890123456789
- |
- w = 20
------------------------|<--c+w=24
-
-int i = 0;
-int d = 0;
-while (i < len && d < c+w)
-{
- if (s[i] == '\t')
- {
- if (d < c)
- {
- if (d+8 >= c)
- for (int j = 0; j < 8-(c-d); j++)
- print(' ');
- d += 8;
- }
- else
- {
- for (int j = 0; j < MIN(c+w-d, 8); j++)
- print(' ');
- d += MIN(c+w-d, 8);
- }
- }
- else
- {
- if (d >= c)
- print(s[i]);
- d++;
- }
-
- i++;
-}
-
- ABC\t WQ
- A
- |B
- ||C
- |||\t
- 0123 45
- c
- |
- 01234567890123456789
- [
- ABC.::::WQ
- [ |
----+----+ |
- | | |
- x x+padding_left
- | |
- | c=4
- c=0
-
-c = 0..n
-draw(x+padding_left+c)
-
-
+ | |
+ |012345678901234567890123456789|123456789
+ |012345670123456701234567012345|701234567
+ ds = 0 |The quick brown fox | jumps.
+ i = 19 | |----|->
+ *ps = '\t'
+
+ | |
+ 0|234567890123456789012345678901|3456789
+ 0|234567012345670123456701234567|1234567
+ T|e quick brown fox |umps.
+ | |->
+ ds = 2 ds = first shown display column
+ i = 20
+ *ps = 'j'
+
+ | |
+ 0123|567890123456789012345678901234|6789
+ 0123|567012345670123456701234567012|4567
+ The | quick brown fox jum|s.
+ | |
+ ds = 5 | |
+ i = 23
+ *ps = 'p'
+
+
+
+
diff --git a/util.h b/util.h
@@ -1,5 +1,6 @@
#include <bits/stdint-uintn.h>
#include <sys/types.h>
+#define ABS(a) ((a < 0) ? (-a) : (a))
#define LEN(x) (sizeof(x) / sizeof(x[0]))
#define MAX(a,b) ((a > b) ? a : b)
#define MIN(a,b) ((a < b) ? a : b)