UI: automatically indent lines in dialogues
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "main.h"
|
||||
#include "../app.h"
|
||||
#include "alert.h"
|
||||
#include "connection.h"
|
||||
#include "file_list.h"
|
||||
#include "query.h"
|
||||
@@ -41,6 +42,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
/* init alert */
|
||||
w_alert_init(app);
|
||||
w_alert("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.");
|
||||
|
||||
init_query_args(q_args, app->params);
|
||||
q_args->buf = malloc(INBUFSIZE);
|
||||
|
||||
+3
-3
@@ -28,19 +28,19 @@ const char *u_utf8_wind_n(const char *s, int n) {
|
||||
|
||||
int32_t u_utf8_convert_to_wide(const char *utf8_str,
|
||||
wchar_t **restrict wide_str,
|
||||
size_t *restrict len) {
|
||||
size_t *restrict o_len) {
|
||||
// Step 1: Convert UTF-8 (MBCS) to wchar_t (wide)
|
||||
size_t wide_len =
|
||||
u_utf8_code_points_count(utf8_str); // Get required length (-1 on error)
|
||||
if (wide_len == (size_t)-1) {
|
||||
*len = 0;
|
||||
*o_len = 0;
|
||||
perror("mbstowcs failed");
|
||||
return 1;
|
||||
}
|
||||
*wide_str =
|
||||
malloc((wide_len + 1) * sizeof(wchar_t)); // +1 for null terminator
|
||||
mbstowcs(*wide_str, utf8_str, wide_len + 1); // Perform conversion
|
||||
*len = wide_len;
|
||||
*o_len = wide_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
const char *u_utf8_wind_n(const char *s, int n);
|
||||
size_t u_utf8_code_points_count(const char *s);
|
||||
int32_t u_utf8_convert_to_wide(const char *utf8_str, wchar_t **restrict wide_str,
|
||||
size_t *restrict len);
|
||||
size_t *restrict o_len);
|
||||
int32_t u_utf8_curs_printw(WINDOW *win, int32_t *y, int32_t *x, const char* utf8_str, int max_len, bool multiline);
|
||||
|
||||
#endif
|
||||
+12
-4
@@ -1,11 +1,14 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/* Copyright (c) 2026 Oleksandr Zhylin */
|
||||
#include <ncursesw/ncurses.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <wchar.h>
|
||||
#include <widget.h>
|
||||
#include <widget_core.h>
|
||||
|
||||
@@ -237,7 +240,11 @@ int32_t w_dialogue_draw(w_dialogue_t *d) {
|
||||
/* analyze text content */
|
||||
int32_t line_count = 0;
|
||||
int32_t line_max_len = 0;
|
||||
line_max_len = w_get_max_line_len(d->text, &line_count);
|
||||
wchar_t *main_text_wide = malloc(sizeof(wchar_t) * strlen(d->text));
|
||||
size_t mwt_len;
|
||||
u_utf8_convert_to_wide(d->text, &main_text_wide, &mwt_len);
|
||||
line_count = w_text_divide_by_lines(
|
||||
main_text_wide, mwt_len, d->p_coordinates->max_x * 0.77, &line_max_len);
|
||||
y += line_count;
|
||||
y += 2; /* margin for text */
|
||||
|
||||
@@ -246,8 +253,8 @@ int32_t w_dialogue_draw(w_dialogue_t *d) {
|
||||
DETECT_GROUP_SIZE(d->g_action, line_max_len, y, x);
|
||||
x += line_max_len;
|
||||
|
||||
x += 1; /* when uses box */
|
||||
y += 1; /* when uses box */
|
||||
x += 2; /* when uses box */
|
||||
y += 2; /* when uses box */
|
||||
|
||||
d->w.sz.x = x;
|
||||
d->w.sz.y = y;
|
||||
@@ -283,7 +290,8 @@ int32_t w_dialogue_draw(w_dialogue_t *d) {
|
||||
/* text */
|
||||
wattroff(d->win, A_BOLD);
|
||||
/* mvwhline(d->win, d->w.sz.y - 3, 1, 0, d->w.sz.x - 2); */
|
||||
w_print_multiline_text(d->win, d->text, d->w.sz.x, 2, 1, PMT_ALIGN_CENTER);
|
||||
w_print_multiline_text_wide(d->win, main_text_wide, mwt_len, line_max_len,
|
||||
d->w.sz.x, 2, 0, PMT_ALIGN_CENTER);
|
||||
wattroff(d->win, A_REVERSE);
|
||||
|
||||
if (d->g_content != NULL) {
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
#include "widget_core.h"
|
||||
#include "../main.h"
|
||||
#include <ncursesw/ncurses.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <utils.h>
|
||||
#include <wchar.h>
|
||||
|
||||
extern int32_t m_id;
|
||||
|
||||
@@ -59,6 +61,49 @@ int32_t w_get_max_line_len(const char *text, int32_t *line_count) {
|
||||
}
|
||||
}
|
||||
|
||||
/* returns number of lines */
|
||||
int32_t w_text_divide_by_lines(wchar_t *restrict text, size_t src_len,
|
||||
int max_x, int *max_len) {
|
||||
int cl_pos = 0;
|
||||
int last_space = -1; /* space position in the current line */
|
||||
int lines_num = 1;
|
||||
|
||||
for (int i = 0; text[i] != '\0'; i++, cl_pos++) {
|
||||
switch (text[i]) {
|
||||
case ' ': /* space symbol */
|
||||
last_space = i;
|
||||
break;
|
||||
case '\n':
|
||||
if (cl_pos > *max_len) {
|
||||
*max_len = cl_pos;
|
||||
}
|
||||
last_space = -1;
|
||||
cl_pos = 0;
|
||||
lines_num++;
|
||||
break;
|
||||
default:
|
||||
if (cl_pos > max_x) {
|
||||
if (last_space > 0) {
|
||||
int line_size = last_space - (i - cl_pos);
|
||||
if (line_size > *max_len) {
|
||||
*max_len = line_size;
|
||||
}
|
||||
text[last_space] = '\n';
|
||||
i = last_space;
|
||||
last_space = -1;
|
||||
cl_pos = 0;
|
||||
lines_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cl_pos--;
|
||||
if (cl_pos > *max_len) { /* for the last line */
|
||||
*max_len = cl_pos;
|
||||
}
|
||||
return lines_num;
|
||||
}
|
||||
|
||||
/* #define PRINT_TEXT(win, l_buf, text, i, c_line_len, win_width, line_v_pos, \
|
||||
attrs) \
|
||||
strncpy(l_buf, text + i - c_line_len, c_line_len); \
|
||||
@@ -72,7 +117,7 @@ int32_t w_get_max_line_len(const char *text, int32_t *line_count) {
|
||||
}
|
||||
*/
|
||||
|
||||
void PRINT_TEXT(WINDOW *win, char *l_buf, char *text, int32_t i,
|
||||
void line_print(WINDOW *win, char *l_buf, char *text, int32_t i,
|
||||
int32_t c_line_len, int32_t win_width, int32_t line_v_pos,
|
||||
int32_t attrs, int32_t x, int32_t max_line_len) {
|
||||
int32_t utf8len = 0;
|
||||
@@ -90,9 +135,27 @@ void PRINT_TEXT(WINDOW *win, char *l_buf, char *text, int32_t i,
|
||||
}
|
||||
}
|
||||
|
||||
void wline_print(WINDOW *win, wchar_t *w_text, int32_t i, int32_t c_line_len,
|
||||
int32_t win_width, int32_t y, int32_t attrs, int32_t x,
|
||||
int32_t max_line_len) {
|
||||
wchar_t l_buf[DIALOGUE_TEXT];
|
||||
int32_t b_len = c_line_len * sizeof(wchar_t);
|
||||
memcpy(l_buf, w_text + i - c_line_len, b_len);
|
||||
l_buf[c_line_len] = '\0';
|
||||
if ((attrs & PMT_ALIGN_CENTER) == PMT_ALIGN_CENTER) {
|
||||
int32_t _x = x + (win_width - c_line_len) / 2;
|
||||
mvwaddnwstr(win, y, _x, l_buf, c_line_len);
|
||||
} else if (attrs & PMT_POS_CENTER) {
|
||||
int32_t _x = x + (win_width - max_line_len) / 2;
|
||||
mvwaddnwstr(win, y, _x, l_buf, c_line_len);
|
||||
} else {
|
||||
mvwaddnwstr(win, y, x, l_buf, c_line_len);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t w_print_multiline_text(WINDOW *win, const char *_text,
|
||||
const int32_t win_width, const int32_t y,
|
||||
const int32_t x, const int16_t attrs) {
|
||||
const int32_t win_width, const int32_t y,
|
||||
const int32_t x, const int16_t attrs) {
|
||||
|
||||
int16_t line_v_pos = y;
|
||||
int32_t c_line_len = 0;
|
||||
@@ -126,17 +189,64 @@ int32_t w_print_multiline_text(WINDOW *win, const char *_text,
|
||||
|
||||
for (; text[i]; i++, c_line_len++) {
|
||||
if (text[i] == '\n') {
|
||||
PRINT_TEXT(win, l_buf, text, i, c_line_len, win_width, line_v_pos, attrs,
|
||||
line_print(win, l_buf, text, i, c_line_len, win_width, line_v_pos, attrs,
|
||||
x, m_line_len);
|
||||
c_line_len = -1;
|
||||
line_v_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
PRINT_TEXT(win, l_buf, text, i, c_line_len, win_width, line_v_pos, attrs, x,
|
||||
line_print(win, l_buf, text, i, c_line_len, win_width, line_v_pos, attrs, x,
|
||||
m_line_len);
|
||||
|
||||
free(text);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t w_print_multiline_text_wide(WINDOW *win, const wchar_t *_text,
|
||||
size_t text_len, int32_t max_line_size,
|
||||
const int32_t win_width, const int32_t y,
|
||||
const int32_t x, const int16_t attrs) {
|
||||
|
||||
int16_t line_v_pos = y;
|
||||
int32_t c_line_len = 0;
|
||||
int32_t i = 0;
|
||||
int text_bytes_size = sizeof(wchar_t) * (text_len + 1);
|
||||
wchar_t *text = malloc(text_bytes_size);
|
||||
mempcpy(text, _text, text_bytes_size);
|
||||
|
||||
int l_size = 0;
|
||||
for (int m = 0; text[m] != '\0'; m++) {
|
||||
if (text[m] != '\n') {
|
||||
if (l_size >= win_width) {
|
||||
int j = m;
|
||||
while (text[j] != ' ') {
|
||||
j--;
|
||||
}
|
||||
text[j] = '\n';
|
||||
l_size = 0;
|
||||
} else {
|
||||
l_size++;
|
||||
}
|
||||
} else {
|
||||
l_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (; text[i]; i++, c_line_len++) {
|
||||
if (text[i] == '\n') {
|
||||
wline_print(win, text, i, c_line_len, win_width, line_v_pos, attrs, x,
|
||||
max_line_size);
|
||||
c_line_len = -1;
|
||||
line_v_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
wline_print(win, text, i, c_line_len, win_width, line_v_pos, attrs, x,
|
||||
max_line_size);
|
||||
|
||||
free(text);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -59,8 +59,8 @@ enum w_cbrp_code {
|
||||
|
||||
/* widget callback response data */
|
||||
typedef struct {
|
||||
enum w_cbrp_code code;
|
||||
struct w_val_t val;
|
||||
enum w_cbrp_code code;
|
||||
struct w_val_t val;
|
||||
} w_cbrp_data;
|
||||
|
||||
typedef struct {
|
||||
@@ -103,10 +103,16 @@ enum w_pmt_attrs {
|
||||
PMT_ALIGN_CENTER = 03,
|
||||
};
|
||||
|
||||
void w_init(w_t *w, w_t *w_parent, WINDOW **win, char *title);
|
||||
int32_t w_get_max_line_len(const char *text, int32_t *line_count);
|
||||
int32_t w_print_multiline_text(WINDOW *win, const char *text,
|
||||
const int32_t win_width, const int32_t y,
|
||||
const int32_t x, const int16_t attrs);
|
||||
void w_init(w_t *w, w_t *w_parent, WINDOW **win, char *title);
|
||||
int32_t w_get_max_line_len(const char *text, int32_t *line_count);
|
||||
int32_t w_print_multiline_text(WINDOW *win, const char *text,
|
||||
const int32_t win_width, const int32_t y,
|
||||
const int32_t x, const int16_t attrs);
|
||||
int32_t w_print_multiline_text_wide(WINDOW *win, const wchar_t *_text,
|
||||
size_t text_len, int32_t max_line_size, const int32_t win_width,
|
||||
const int32_t y, const int32_t x,
|
||||
const int16_t attrs);
|
||||
int32_t w_text_divide_by_lines(wchar_t *restrict text, size_t src_len,
|
||||
int max_x, int *max_len);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user