чување 289d06d7f45a635bc76c3a776f96d32091fb1dc4
родитељ b4dd32975d80b47d0605bc6ef1fef90c44c0c86b
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sat, 3 Jul 2021 23:26:33 +0200
msgid -> info box; toggle info box focus with F6; when info box is focused, movement keys scroll the info area
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | TODO | | | 8 | ++++---- |
| M | config.def.h | | | 6 | +++++- |
| M | config.h | | | 6 | +++++- |
| M | draw.c | | | 50 | ++++++++++++++++++++++++++++++++++++++------------ |
| M | draw.h | | | 10 | ++++++++-- |
| M | po.c | | | 6 | ++++++ |
| M | poe.1.in | | | 1 | + |
| M | poe.c | | | 276 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
измењених датотека: 8, додавања: 322(+), брисања: 41(-)
diff --git a/TODO b/TODO
@@ -13,11 +13,11 @@
[ ] Yank/paste (entire current msgstr)
- [ ] Multiline msgid display
- [ ] Also msgid_plural
+ [~] Multiline msgid display
+ [x] Also msgid_plural
[ ] Also Plural-Forms
- [ ] (Multiline) comment display; ~key binding: "?"~
- [ ] Toggle msgid/msgstr focus with F6; when msgid is focused,
+ [x] (Multiline) comment display; ~key binding: "?"~
+ [x] Toggle msgid/msgstr focus with F6; when msgid is focused,
arrow keys scroll the msgid area
[/] ~Edit dialog overhaul? Don't display as dialog, but
full-screen so more information can be shown~
diff --git a/config.def.h b/config.def.h
@@ -3,8 +3,12 @@
#define DLG_BG TB_WHITE
#define EDIT_MSGID_FG TB_BLACK | TB_BOLD
#define EDIT_MSGID_BG TB_WHITE
-#define EDIT_MSGSTR_FG TB_YELLOW | TB_BOLD
+#define EDIT_MSGID_FOCUS_FG TB_BLACK
+#define EDIT_MSGID_FOCUS_BG TB_WHITE
+#define EDIT_MSGSTR_FG TB_BLACK | TB_BOLD
#define EDIT_MSGSTR_BG TB_BLACK
+#define EDIT_MSGSTR_FOCUS_FG TB_YELLOW | TB_BOLD
+#define EDIT_MSGSTR_FOCUS_BG TB_BLACK
#define ERROR_FG TB_WHITE | TB_BOLD
#define ERROR_BG TB_RED
#define FLAG_FG TB_YELLOW | TB_BOLD
diff --git a/config.h b/config.h
@@ -3,8 +3,12 @@
#define DLG_BG TB_WHITE
#define EDIT_MSGID_FG TB_BLACK | TB_BOLD
#define EDIT_MSGID_BG TB_WHITE
-#define EDIT_MSGSTR_FG TB_YELLOW | TB_BOLD
+#define EDIT_MSGID_FOCUS_FG TB_BLACK
+#define EDIT_MSGID_FOCUS_BG TB_WHITE
+#define EDIT_MSGSTR_FG TB_BLACK | TB_BOLD
#define EDIT_MSGSTR_BG TB_BLACK
+#define EDIT_MSGSTR_FOCUS_FG TB_YELLOW | TB_BOLD
+#define EDIT_MSGSTR_FOCUS_BG TB_BLACK
#define ERROR_FG TB_WHITE | TB_BOLD
#define ERROR_BG TB_RED
#define FLAG_FG TB_YELLOW | TB_BOLD
diff --git a/draw.c b/draw.c
@@ -245,15 +245,38 @@ draw_editbox(const struct DrawState* state)
strlen(editbox_title)+2, 1, 1, CENTER))
return NULL;
- draw_rect(startx+1, endx-1, starty+1, endy-h/2-1,
- EDIT_MSGID_FG, EDIT_MSGID_BG);
- u32_draw_string(startx+1, starty+1, EDIT_MSGID_FG, EDIT_MSGID_BG,
- state->entries[state->msgid_number-1].msgid, w-2,
- w-2, 1, 1, LEFT);
+ uint16_t fg = state->edit_info_focused ? EDIT_MSGID_FOCUS_FG :
+ EDIT_MSGID_FG;
+ uint16_t bg = state->edit_info_focused ? EDIT_MSGID_FOCUS_BG :
+ EDIT_MSGID_BG;
+
+ draw_rect(startx+1, endx-1, starty+1, endy-h/2-1, fg, bg);
+ for (size_t i = 0; i < (h-3)/2+1 && state->info_first_shown_row + i <
+ state->info_rows_count; i++)
+ {
+ struct BufferLine* curline = &state->info_buffer[
+ state->info_first_shown_row+i];
+ if (!curline || !curline->text)
+ return NULL;
+ if (curline->length > state->info_first_shown_column)
+ u32_draw_string(startx+1, starty+1+i, fg,
+ bg, curline->text +
+ state->info_first_shown_column,
+ w-3, w-3, 1, 1, LEFT);
+ }
+ /*
+ *u32_draw_string(startx+1, starty+1, EDIT_MSGID_FG, EDIT_MSGID_BG,
+ * state->entries[state->msgid_number-1].msgid, w-2,
+ * w-2, 1, 1, LEFT);
+ */
+
- draw_rect(startx+1, endx-1, endy-h/2-1, endy-2,
- EDIT_MSGSTR_FG, EDIT_MSGSTR_BG);
+ fg = state->edit_info_focused ? EDIT_MSGSTR_FG :
+ EDIT_MSGSTR_FOCUS_FG;
+ bg = state->edit_info_focused ? EDIT_MSGSTR_BG :
+ EDIT_MSGSTR_FOCUS_BG;
+ draw_rect(startx+1, endx-1, endy-h/2-1, endy-2, fg, bg);
for (size_t i = 0; i < (h-3)/2+1 && state->input_first_shown_row + i <
state->input_rows_count; i++)
{
@@ -263,15 +286,18 @@ draw_editbox(const struct DrawState* state)
return NULL;
if (curline->length > state->input_first_shown_column)
u32_draw_string(startx+1, endy-h/2-1+i,
- EDIT_MSGSTR_FG, EDIT_MSGSTR_BG, curline->text +
+ fg, bg, curline->text +
state->input_first_shown_column,
w-3, w-3, 1, 1, LEFT);
}
- tb_set_cursor(startx+2+state->input_display_column
- - state->input_first_shown_column,
- endy-h/2-1 + state->input_row -
- state->input_first_shown_row);
+ if (state->edit_info_focused)
+ tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR);
+ else
+ tb_set_cursor(startx+2+state->input_display_column -
+ state->input_first_shown_column, endy-h/2-1 +
+ state->input_row -
+ state->input_first_shown_row);
char sbuf[MAXBUFLINE];
if (entry->msgstr_count > 1)
diff --git a/draw.h b/draw.h
@@ -31,7 +31,7 @@ struct DrawState {
char* error;
char* prompt;
char* filename;
- struct BufferLine* input_buffer;
+ struct BufferLine* input_buffer; /* edit box */
int input_column;
int input_row;
int input_first_shown_column;
@@ -39,6 +39,11 @@ struct DrawState {
int input_rows_count;
int input_display_column;
int saved_column;
+ struct BufferLine* info_buffer; /* information pane above
+ * edit box */
+ int info_first_shown_column;
+ int info_first_shown_row;
+ int info_rows_count;
struct PoEntry* entries;
void (*prompt_callback)(struct DrawState*, struct tb_event*);
int running;
@@ -46,12 +51,13 @@ struct DrawState {
int in_prompt;
int show_help;
int show_edit;
+ int edit_info_focused;
int maxx;
int maxy;
size_t msgid_number;
size_t msgid_count;
size_t msgid_size;
- int msgstr_index; /* with msgstr[] */
+ int msgstr_index; /* with msgstr[] */
size_t first_shown_msgid;
};
diff --git a/po.c b/po.c
@@ -417,6 +417,12 @@ parse_po_line(const char* line, struct PoEntry** entries, size_t* entries_size,
else if (*pline)
return PARSE_ERR_SYNTAX;
}
+ else
+ {
+ *ptoken++ = *pline++;
+ (*col)++;
+ }
+ break;
case '"':
/* skip beginning and end quote */
if (ptoken == token || *(pline+1) == 0)
diff --git a/poe.1.in b/poe.1.in
@@ -94,6 +94,7 @@ _
\fCC-P\fP@Show previous plural form of msgstr
\fCC-N\fP@Show next plural form of msgstr
\fCEscape\fP@Cancel changes and close dialog
+\fCF6\fP@Toggle focus between info box and edit box
\fCC-Z\fP@Toggle fuzzy flag
\fCC-A\fP or \fCHome\fP@Go to start of line
\fCC-E\fP or \fCEnd\fP@Go to end of line
diff --git a/poe.c b/poe.c
@@ -91,6 +91,7 @@ quit_callback(struct DrawState* state, struct tb_event* ev)
}
}
+struct BufferLine* load_info(struct DrawState* state);
struct BufferLine* load_msgstr(struct DrawState* state);
void save_msgstr(struct DrawState* state);
void move_up(struct DrawState* state);
@@ -117,6 +118,141 @@ struct DrawState* insert_line(struct DrawState* state);
struct DrawState* join_lines(struct DrawState* state, size_t first_line);
struct BufferLine*
+load_info(struct DrawState* state)
+{
+ struct PoEntry* current = &state->entries[state->msgid_number-1];
+ size_t msgid_num_lines = u32_lines_in_string(current->msgid);
+ size_t msgid_plural_num_lines = u32_lines_in_string(
+ current->msgid_plural);
+ size_t num_lines = 0;
+ struct BufferLine* newbuf = NULL;
+ struct BufferLine* pnewbuf = NULL;
+
+ if (current->msgid)
+ num_lines += 1 + msgid_num_lines + 1;
+ num_lines += 3; /* Plural-Forms */
+ if (current->msgid_plural)
+ num_lines += 1 + msgid_plural_num_lines + 1;
+ if (current->comments)
+ num_lines += 1 + current->comment_lines + 1;
+ if (current->ref_comments)
+ num_lines += 1 + current->ref_comment_lines + 1;
+ newbuf = calloc(num_lines, sizeof(struct BufferLine));
+ if (!newbuf)
+ return NULL;
+
+ pnewbuf = newbuf;
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ init_bufferline(pnewbuf);
+ uint32_t* newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
+ if (!newtext)
+ return NULL;
+ pnewbuf->text = newtext;
+ pnewbuf++;
+ }
+
+ state->info_rows_count = num_lines;
+
+ pnewbuf = newbuf;
+ size_t newlen = 0;
+ uint32_t* pumsgid = NULL;
+ if (current->msgid)
+ {
+ pumsgid = current->msgid;
+ newlen = u32_u8_strncpy(pnewbuf->text, "msgid:",
+ MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ for (size_t i = 0; i < msgid_num_lines; i++)
+ {
+ size_t len = u32_line_length(pumsgid);
+ newlen = 0;
+ u32_strncpy(pnewbuf->text, pumsgid, MIN(len+1,
+ MAXBUFLINE));
+ newlen = u32_decode_tabs(pnewbuf->text, MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pumsgid += len+(pumsgid[len] ? 2 : 0);
+ pnewbuf++;
+ }
+ pnewbuf->text[0] = 0;
+ pnewbuf->length = 0;
+ pnewbuf++;
+ }
+ /* TODO: Parse first msgid for Plural-Forms */
+ newlen = u32_u8_strncpy(pnewbuf->text, "Plural-Forms:", MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ newlen = u32_u8_strncpy(pnewbuf->text, "<Reserved>", MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ pnewbuf->text[0] = 0;
+ pnewbuf->length = 0;
+ pnewbuf++;
+ if (current->msgid_plural)
+ {
+ newlen = u32_u8_strncpy(pnewbuf->text, "msgid_plural:",
+ MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ pumsgid = current->msgid_plural;
+ for (size_t i = 0; i < msgid_plural_num_lines; i++)
+ {
+ size_t len = u32_line_length(pumsgid);
+ newlen = 0;
+ u32_strncpy(pnewbuf->text, pumsgid, MIN(len+1,
+ MAXBUFLINE));
+ newlen = u32_decode_tabs(pnewbuf->text, MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pumsgid += len+(pumsgid[len] ? 2 : 0);
+ pnewbuf++;
+ }
+ pnewbuf->text[0] = 0;
+ pnewbuf->length = 0;
+ pnewbuf++;
+ }
+ if (current->comments)
+ {
+ newlen = u32_u8_strncpy(pnewbuf->text, "Comments:",
+ MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ for (size_t i = 0; i < current->comment_lines; i++)
+ {
+ uint32_t* comment = current->comments[i];
+ size_t len = u32_strlen(comment);
+ newlen = u32_strncpy(pnewbuf->text, comment,
+ MIN(len+1, MAXBUFLINE));
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ }
+ pnewbuf->text[0] = 0;
+ pnewbuf->length = 0;
+ pnewbuf++;
+ }
+ if (current->ref_comments)
+ {
+ newlen = u32_u8_strncpy(pnewbuf->text, "References:",
+ MAXBUFLINE);
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ for (size_t i = 0; i < current->ref_comment_lines; i++)
+ {
+ char* ref_comment = current->ref_comments[i];
+ size_t len = strlen(ref_comment);
+ newlen = u32_u8_strncpy(pnewbuf->text, ref_comment,
+ MIN(len+1, MAXBUFLINE));
+ pnewbuf->length = newlen;
+ pnewbuf++;
+ }
+ }
+
+ state->info_buffer = newbuf;
+
+ return state->info_buffer;
+}
+
+struct BufferLine*
load_msgstr(struct DrawState* state)
{
int msgstr_index = state->msgstr_index;
@@ -195,6 +331,11 @@ save_msgstr(struct DrawState* state)
}
free(state->input_buffer);
state->input_buffer = NULL;
+ if (state->info_buffer)
+ for (size_t i = 0; i < state->info_rows_count; i++)
+ free_bufferline(state->info_buffer+i);
+ free(state->info_buffer);
+ state->info_buffer = NULL;
u32_encode_tabs(to_save, MAXBUFLINE);
u32_set_msgstr(&state->entries[state->msgid_number-1], to_save,
state->msgstr_index, 0);
@@ -209,11 +350,23 @@ cancel_msgstr(struct DrawState* state)
free_bufferline(state->input_buffer+i);
free(state->input_buffer);
state->input_buffer = NULL;
+ if (state->info_buffer)
+ for (size_t i = 0; i < state->info_rows_count; i++)
+ free_bufferline(state->info_buffer+i);
+ free(state->info_buffer);
+ state->info_buffer = NULL;
}
void
move_up(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ {
+ if (state->info_first_shown_row > 0)
+ state->info_first_shown_row--;
+ return;
+ }
+
if (state->input_row > 0)
state->input_row--;
if (state->input_first_shown_row > state->input_row)
@@ -239,6 +392,14 @@ move_up(struct DrawState* state)
void
move_down(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ {
+ if (state->info_first_shown_row + (EDIT_HEIGHT-3)/2 <
+ state->info_rows_count-1)
+ state->info_first_shown_row++;
+ return;
+ }
+
if (state->input_row < state->input_rows_count-1)
state->input_row++;
if (state->input_first_shown_row + (EDIT_HEIGHT-3)/2 <
@@ -266,6 +427,13 @@ move_down(struct DrawState* state)
void
move_start(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ {
+ state->info_first_shown_row = 0;
+ state->info_first_shown_column = 0;
+ return;
+ }
+
state->input_column = 0;
state->input_display_column = 0;
state->input_first_shown_column = 0;
@@ -313,6 +481,14 @@ move_right(struct DrawState* state)
void
move_end(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ {
+ if (state->info_rows_count > (EDIT_HEIGHT-3)/2)
+ state->info_first_shown_row = state->info_rows_count-1 -
+ (EDIT_HEIGHT-3)/2;
+ state->info_first_shown_column = 0;
+ return;
+ }
size_t len = state->input_buffer[state->input_row].length;
state->input_column = len;
@@ -399,20 +575,26 @@ move_list_page_down(struct DrawState* state)
void
next_plural(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ return;
struct PoEntry* current = &state->entries[state->msgid_number-1];
save_msgstr(state);
if (state->msgstr_index + 1 < current->msgstr_count)
state->msgstr_index++;
load_msgstr(state);
+ load_info(state);
}
void
prev_plural(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ return;
save_msgstr(state);
if (state->msgstr_index > 0)
state->msgstr_index--;
load_msgstr(state);
+ load_info(state);
}
void
@@ -472,6 +654,8 @@ input_length(const struct DrawState* state, const size_t max_index)
void
insert_char(struct DrawState* state, uint32_t ch)
{
+ if (state->edit_info_focused)
+ return;
struct BufferLine* buffer_line = &state->input_buffer[state->input_row];
size_t len = buffer_line->length;
if (state->input_column < MAXBUFLINE-1)
@@ -501,6 +685,8 @@ insert_char(struct DrawState* state, uint32_t ch)
void
erase_to_start(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ return;
size_t i = state->input_column;
struct BufferLine* buffer_line = &state->input_buffer[state->input_row];
size_t len = buffer_line->length;
@@ -519,6 +705,8 @@ erase_to_start(struct DrawState* state)
void
erase_to_end(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ return;
struct BufferLine* buffer_line = &state->input_buffer[state->input_row];
buffer_line->text[state->input_column] = 0;
buffer_line->length = state->input_column;
@@ -528,6 +716,8 @@ erase_to_end(struct DrawState* state)
struct DrawState*
insert_line(struct DrawState* state)
{
+ if (state->edit_info_focused)
+ return state;
state->input_rows_count++;
struct BufferLine* newbuf = realloc(
state->input_buffer, state->input_rows_count *
@@ -625,8 +815,9 @@ handle_editbox_key_event(struct tb_event* ev, struct DrawState* state)
move_right(state);
else if (ev->key == TB_KEY_ARROW_UP)
move_up(state);
- else if (ev->key == TB_KEY_BACKSPACE
- || ev->key == TB_KEY_BACKSPACE2)
+ else if ((ev->key == TB_KEY_BACKSPACE
+ || ev->key == TB_KEY_BACKSPACE2)
+ && !state->edit_info_focused)
{
if (state->input_column > 0)
{
@@ -675,7 +866,7 @@ handle_editbox_key_event(struct tb_event* ev, struct DrawState* state)
erase_to_start(state);
else if (ev->key == TB_KEY_CTRL_Z)
toggle_fuzzy(state);
- else if (ev->key == TB_KEY_DELETE)
+ else if (ev->key == TB_KEY_DELETE && !state->edit_info_focused)
{
if (buffer_line->text[state->input_column])
{
@@ -706,32 +897,65 @@ handle_editbox_key_event(struct tb_event* ev, struct DrawState* state)
cancel_msgstr(state);
tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR);
}
+ else if (ev->key == TB_KEY_F6)
+ state->edit_info_focused = !state->edit_info_focused;
else if (ev->key == TB_KEY_HOME
|| ev->key == TB_KEY_CTRL_A)
move_start(state);
else if (ev->key == TB_KEY_PGDN
|| ev->key == TB_KEY_CTRL_F)
{
- save_msgstr(state);
- move_list_down(state);
- state->msgstr_index = 0;
- load_msgstr(state);
- state->input_row = 0;
- state->input_first_shown_row = 0;
- move_start(state);
- state->error[0] = 0;
+ if (state->edit_info_focused)
+ {
+ if (state->info_first_shown_row + (EDIT_HEIGHT-3)/2 <
+ state->info_rows_count-1)
+ state->info_first_shown_row += (EDIT_HEIGHT-3)/2;
+ /*
+ *else
+ * move_end(state);
+ */
+ }
+ else
+ {
+ save_msgstr(state);
+ move_list_down(state);
+ state->msgstr_index = 0;
+ load_msgstr(state);
+ load_info(state);
+ state->input_row = 0;
+ state->input_first_shown_row = 0;
+ state->input_first_shown_column = 0;
+ state->info_first_shown_row = 0;
+ state->info_first_shown_column = 0;
+ move_start(state);
+ state->error[0] = 0;
+ }
}
else if (ev->key == TB_KEY_PGUP
|| ev->key == TB_KEY_CTRL_B)
{
- save_msgstr(state);
- move_list_up(state);
- state->msgstr_index = 0;
- load_msgstr(state);
- state->input_row = 0;
- state->input_first_shown_row = 0;
- move_start(state);
- state->error[0] = 0;
+ if (state->edit_info_focused)
+ {
+ if (state->info_first_shown_row > (EDIT_HEIGHT-3)/2)
+ state->info_first_shown_row -= (EDIT_HEIGHT-3)/2;
+ else
+ move_start(state);
+ }
+ else
+ {
+ save_msgstr(state);
+ move_list_up(state);
+ state->msgstr_index = 0;
+ load_msgstr(state);
+ load_info(state);
+ state->input_row = 0;
+ state->input_first_shown_row = 0;
+ state->input_first_shown_column = 0;
+ state->info_first_shown_row = 0;
+ state->info_first_shown_column = 0;
+ move_start(state);
+ state->error[0] = 0;
+ }
}
else if (ev->key == TB_KEY_SPACE)
insert_char(state, ' ');
@@ -809,11 +1033,14 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
else
{
state->msgstr_index = 0;
- if (load_msgstr(state))
+ if (load_msgstr(state) && load_info(state))
{
state->show_edit = 1;
state->input_row = 0;
state->input_first_shown_row = 0;
+ state->input_first_shown_column = 0;
+ state->info_first_shown_row = 0;
+ state->info_first_shown_column = 0;
move_start(state);
state->error[0] = 0;
}
@@ -940,15 +1167,22 @@ main(int argc, char** argv)
state.input_buffer = NULL;
state.input_column = 0;
state.input_first_shown_column = 0;
+ state.input_first_shown_row = 0;
+ state.input_rows_count = 0;
state.input_display_column = 0;
state.saved_column = -1;
+ state.info_buffer = NULL;
+ state.info_first_shown_column = 0;
+ state.info_first_shown_row = 0;
+ state.info_rows_count = 0;
state.prompt = prompt;
state.prompt_callback = NULL;
state.running = 1;
state.dirty = 0;
state.in_prompt = 0;
- state.show_edit = 0;
state.show_help = 0;
+ state.show_edit = 0;
+ state.edit_info_focused = 0;
state.msgid_number = state.msgid_count > 0 ? 1 : 0;
state.msgstr_index = 0;
state.first_shown_msgid = state.msgid_number;