чување 896305171f8464e8e1f9f02f7c23fa84cf73b3e1
родитељ 1b488738b7455a16a0ac5707dabc7d3eed7b1850
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sun, 4 Jul 2021 21:53:37 +0200
Added .po loaded structures saving
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | TODO | | | 3 | ++- |
| M | draw.c | | | 40 | +++++++++++++++++++++++++++++++++++++--- |
| M | draw.h | | | 2 | ++ |
| M | po.c | | | 356 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
| M | po.h | | | 29 | ++++++++++++++++++----------- |
| M | poe.1.in | | | 9 | +++++++++ |
| M | poe.c | | | 99 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- |
| M | util.h | | | 5 | +++-- |
измењених датотека: 8, додавања: 485(+), брисања: 58(-)
diff --git a/TODO b/TODO
@@ -8,7 +8,8 @@
[x] Reading #, comments
[x] Reading #: comments
- [ ] .po file save
+ [~] .po file save
+ [x] Save all read .po structure
[ ] Edit first msgid's msgstr
[ ] Yank/paste (entire current msgstr)
diff --git a/draw.c b/draw.c
@@ -31,7 +31,8 @@ const char* errors[] = {
[ERR_DLG_OPEN] = "Press Esc to close dialog or q/C-Q to quit",
[ERR_DLG_OPEN_QUIT] = "Press Esc to close dialog",
[ERR_EMPTY_FILE] = "No msgids to edit",
- [ERR_CANT_ALLOC] = "Memory allocation failed - exit advised"
+ [ERR_CANT_ALLOC] = "Memory allocation failed - exit advised",
+ [ERR_CANT_SAVE] = "File is not writeable"
};
const char* flag_strings[] = {
[FL_C_FORMAT] = "c-format",
@@ -67,6 +68,39 @@ free_bufferline(struct BufferLine* bl)
bl->bg = 0;
}
+struct BufferLine*
+split(const uint32_t* s)
+{
+ if (!s)
+ return NULL;
+
+ size_t num_lines = u32_lines_in_string(s);
+ struct BufferLine* newbuf = NULL;
+ struct BufferLine* pnewbuf = NULL;
+ const uint32_t* ps = s;
+
+ 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;
+ size_t len = u32_line_length(ps);
+ pnewbuf->length = u32_strncpy(pnewbuf->text, ps,
+ MIN(len+1, MAXBUFLINE));
+ ps += len + (ps[len] ? 2 : 0);
+ pnewbuf++;
+ }
+
+ return newbuf;
+}
+
void
draw_rect(const int startx, const int endx, const int starty, const int endy,
const uint16_t fg, const uint16_t bg)
@@ -275,8 +309,8 @@ draw_editbox(const struct DrawState* state)
u32_draw_string(endx-2, starty+1, fg, bg, (uint32_t*)L"\u2191",
1, 1, 0, 0, LEFT);
if (state->info_first_shown_row + (h-3)/2 + 2 <= state->info_rows_count)
- u32_draw_string(endx-2, h/2+1, fg, bg, (uint32_t*)L"\u2193",
- 1, 1, 0, 0, LEFT);
+ u32_draw_string(endx-2, starty+(h-3)/2+1, fg, bg,
+ (uint32_t*)L"\u2193", 1, 1, 0, 0, LEFT);
/*
*u32_draw_string(startx+1, starty+1, EDIT_MSGID_FG, EDIT_MSGID_BG,
* state->entries[state->msgid_number-1].msgid, w-2,
diff --git a/draw.h b/draw.h
@@ -51,6 +51,7 @@ struct DrawState {
void (*prompt_callback)(struct DrawState*, struct tb_event*);
int running;
int dirty;
+ int dirty_before_edit;
int in_prompt;
int show_help;
int show_edit;
@@ -76,6 +77,7 @@ extern struct PoEntry entries[];
void init_bufferline(struct BufferLine* bl);
void free_bufferline(struct BufferLine* bl);
+struct BufferLine* split(const uint32_t* s);
void draw_rect(const int startx, const int endx, const int starty,
const int endy, const uint16_t fg, const uint16_t bg);
void draw_box(const int startx, const int endx, const int starty,
diff --git a/po.c b/po.c
@@ -1,7 +1,9 @@
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "po.h"
+#include "draw.h"
#include "util.h"
extern const char* flag_strings[];
@@ -19,16 +21,18 @@ format_flags(char* buffer, const size_t max, const struct PoEntry* entry)
void
init_po_entry(struct PoEntry* entry)
{
- entry->flags = FL_NONE;
- entry->msgid = NULL;
- entry->msgid_plural = NULL;
- entry->plural_forms = NULL;
- entry->msgstr = NULL;
- entry->msgstr_count = 0;
- entry->comments = NULL;
- entry->comment_lines = 0;
- entry->ref_comments = NULL;
- entry->ref_comment_lines = 0;
+ entry->flags = FL_NONE;
+ entry->msgid = NULL;
+ entry->msgid_plural = NULL;
+ entry->plural_forms = NULL;
+ entry->msgstr = NULL;
+ entry->msgstr_count = 0;
+ entry->comments = NULL;
+ entry->comment_lines = 0;
+ entry->trans_comments = NULL;
+ entry->trans_comment_lines = 0;
+ entry->ref_comments = NULL;
+ entry->ref_comment_lines = 0;
}
void
@@ -56,6 +60,15 @@ free_po_entry(struct PoEntry* entry)
free(entry->comments);
}
+ if (entry->trans_comments)
+ {
+ uint32_t** trans_comment = entry->trans_comments;
+ while (trans_comment < entry->trans_comments +
+ entry->trans_comment_lines)
+ free(*trans_comment++);
+ free(entry->trans_comments);
+ }
+
if (entry->ref_comments)
{
char** comment = entry->ref_comments;
@@ -208,7 +221,7 @@ struct PoEntry*
u32_add_comment(struct PoEntry* entry, const uint32_t* comment)
{
uint32_t** comments = NULL;
- uint32_t* new_line = NULL;
+ uint32_t* new_line = NULL;
if (!entry)
return NULL;
@@ -232,6 +245,34 @@ u32_add_comment(struct PoEntry* entry, const uint32_t* comment)
}
struct PoEntry*
+u32_add_trans_comment(struct PoEntry* entry, const uint32_t* trans_comment)
+{
+ uint32_t** trans_comments = NULL;
+ uint32_t* new_line = NULL;
+
+ if (!entry)
+ return NULL;
+
+ entry->trans_comment_lines++;
+ if (!entry->trans_comments)
+ trans_comments = calloc(entry->trans_comment_lines,
+ sizeof(uint32_t*));
+ else
+ trans_comments = realloc(entry->trans_comments,
+ entry->trans_comment_lines * sizeof(uint32_t*));
+ if (!trans_comments)
+ return NULL;
+ entry->trans_comments = trans_comments;
+
+ new_line = calloc(MAXCOMMENTLINE, sizeof(uint32_t));
+ if (!new_line)
+ return NULL;
+ entry->trans_comments[entry->trans_comment_lines-1] = new_line;
+ u32_strncpy(new_line, trans_comment, MAXCOMMENTLINE);
+ return entry;
+}
+
+struct PoEntry*
add_ref_comment(struct PoEntry* entry, const char* comment)
{
char** ref_comments = NULL;
@@ -316,6 +357,8 @@ load_file(struct PoEntry** entries, size_t* entries_size,
(*lineno)++;
}
fclose(input);
+ if (*entries_count > 1)
+ (*entries_count)++;
/* file has < PO_DETECTION_LINES */
if (msgid_counter > 0)
@@ -325,8 +368,277 @@ load_file(struct PoEntry** entries, size_t* entries_size,
}
int
-save_file(const struct PoEntry* entries, const char* filename)
+save_file(const struct PoEntry* entries, const size_t msgid_count,
+ const char* filename)
{
+ const struct PoEntry* current = entries;
+ size_t len = strlen(filename);
+ FILE* output = NULL;
+ char* backup_filename = calloc(len+2, 1);
+ char* tmp_filename = "/tmp/poe.tmp";
+
+ if (!(output = fopen(tmp_filename, "wt")))
+ return SAVE_ERR_CANT_OPEN_FILE;
+ strncpy(backup_filename, filename, len+1);
+ backup_filename[len] = '~';
+ backup_filename[len+1] = 0;
+
+ while (current < entries + msgid_count)
+ {
+ if (current->comment_lines > 0)
+ {
+ char u8_comment[MAXCOMMENTLINE*6];
+ for (size_t c = 0; c < current->comment_lines; c++)
+ {
+ unicode_string_to_u8(u8_comment,
+ *(current->comments + c));
+ fprintf(output, "#%s\n", u8_comment);
+ }
+ }
+ if (current->trans_comment_lines > 0)
+ {
+ char u8_trans_comment[MAXCOMMENTLINE*6];
+ for (size_t tc = 0; tc < current->trans_comment_lines;
+ tc++)
+ {
+ unicode_string_to_u8(u8_trans_comment,
+ *(current->trans_comments + tc));
+ fprintf(output, "#.%s%s\n",
+ u8_trans_comment[0] == 0 ? "" :
+ " ",
+ u8_trans_comment);
+ }
+ }
+ if (current->ref_comment_lines > 0)
+ {
+ for (size_t rc = 0; rc < current->ref_comment_lines;
+ rc++)
+ fprintf(output, "#: %s\n",
+ *(current->ref_comments + rc));
+ }
+ Flags flags = current->flags;
+ if (current->flags != FL_NONE)
+ fprintf(output, "#, ");
+ while (flags != FL_NONE)
+ {
+ if (flags & FL_C_FORMAT)
+ {
+ flags &= ~FL_C_FORMAT;
+ fprintf(output, "%s",
+ flag_strings[FL_C_FORMAT]);
+ }
+ else if (flags & FL_FUZZY)
+ {
+ flags &= ~FL_FUZZY;
+ fprintf(output, "%s",
+ flag_strings[FL_FUZZY]);
+ }
+ if (flags != FL_NONE)
+ fprintf(output, ", ");
+ }
+ if (current->flags != FL_NONE)
+ fprintf(output, "\n");
+
+ if (current->msgid)
+ {
+ char msgid[MAXMSG];
+ unicode_string_to_u8(msgid, current->msgid);
+ size_t num_lines = u32_lines_in_string(current->msgid);
+ if (num_lines > 1)
+ {
+ struct BufferLine* msgid_split = split(
+ current->msgid);
+ struct BufferLine* pmsgid_split = NULL;
+
+ if (!msgid_split)
+ return SAVE_ERR_CANT_ALLOC;
+
+ fprintf(output, "msgid \"\"\n");
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgid_split = msgid_split + i;
+ int last = i == num_lines - 1;
+ char u8_msgid[MAXMSG*6];
+ size_t len = u32_strlen(
+ pmsgid_split->text);
+ unicode_string_to_u8(u8_msgid,
+ pmsgid_split->text);
+ if (!(last && len == 0))
+ fprintf(output, "\"%s%s\"\n",
+ u8_msgid, last ? "" :
+ "\\n");
+ }
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgid_split = msgid_split + i;
+ free_bufferline(pmsgid_split);
+ }
+ free(msgid_split);
+ }
+ else
+ {
+ char u8_msgid[MAXMSG*6];
+ unicode_string_to_u8(u8_msgid, current->msgid);
+ fprintf(output, "msgid \"%s\"\n", u8_msgid);
+ }
+ }
+ else
+ fprintf(output, "msgid \"\"\n");
+
+ if (current->msgid_plural)
+ {
+ char msgid_plural[MAXMSG];
+ unicode_string_to_u8(msgid_plural,
+ current->msgid_plural);
+ size_t num_lines = u32_lines_in_string(
+ current->msgid_plural);
+ if (num_lines > 1)
+ {
+ struct BufferLine* msgid_split = split(
+ current->msgid_plural);
+ struct BufferLine* pmsgid_split = NULL;
+
+ if (!msgid_split)
+ return SAVE_ERR_CANT_ALLOC;
+
+ fprintf(output, "msgid_plural \"\"\n");
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgid_split = msgid_split + i;
+ int last = i == num_lines - 1;
+ char u8_msgid[MAXMSG*6];
+ size_t len = u32_strlen(
+ pmsgid_split->text);
+ unicode_string_to_u8(u8_msgid,
+ pmsgid_split->text);
+ if (!(last && len == 0))
+ fprintf(output, "\"%s%s\"\n",
+ u8_msgid, last ? "" :
+ "\\n");
+ }
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgid_split = msgid_split + i;
+ free_bufferline(pmsgid_split);
+ }
+ free(msgid_split);
+ }
+ else
+ {
+ char u8_msgid[MAXMSG*6];
+ unicode_string_to_u8(u8_msgid,
+ current->msgid_plural);
+ fprintf(output, "msgid_plural \"%s\"\n",
+ u8_msgid);
+ }
+ }
+
+ if (current->msgstr_count == 1)
+ {
+ size_t num_lines = u32_lines_in_string(
+ *current->msgstr);
+ if (num_lines > 1)
+ {
+ struct BufferLine* msgstr_split =
+ split(*current->msgstr);
+ struct BufferLine* pmsgstr_split = NULL;
+
+ if (!msgstr_split)
+ return SAVE_ERR_CANT_ALLOC;
+
+ fprintf(output, "msgstr \"\"\n");
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgstr_split = msgstr_split + i;
+ int last = i == num_lines - 1;
+ char u8_msgstr[MAXMSG*6];
+ size_t len = u32_strlen(
+ pmsgstr_split->text);
+ unicode_string_to_u8(u8_msgstr,
+ pmsgstr_split->text);
+ if (!(last && len == 0))
+ fprintf(output, "\"%s%s\"\n",
+ u8_msgstr,
+ last ? "" : "\\n");
+ }
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgstr_split = msgstr_split + i;
+ free_bufferline(pmsgstr_split);
+ }
+ free(msgstr_split);
+ }
+ else
+ {
+ char u8_msgstr[MAXMSG*6];
+ unicode_string_to_u8(u8_msgstr, *current->msgstr);
+ fprintf(output, "msgstr \"%s\"\n", u8_msgstr);
+ }
+ }
+ else if (current->msgstr_count > 0)
+ {
+ for (size_t m = 0; m < current->msgstr_count; m++)
+ {
+ size_t num_lines = u32_lines_in_string(
+ *current->msgstr);
+ if (num_lines > 1)
+ {
+ struct BufferLine* msgstr_split =
+ split(*(current->msgstr + m));
+ struct BufferLine* pmsgstr_split = NULL;
+
+ if (!msgstr_split)
+ return SAVE_ERR_CANT_ALLOC;
+
+ fprintf(output, "msgstr[%ld] \"\"\n",
+ m);
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgstr_split =
+ msgstr_split + i;
+ int last = i == num_lines - 1;
+ char u8_msgstr[MAXMSG*6];
+ size_t len = u32_strlen(
+ pmsgstr_split->text);
+ unicode_string_to_u8(u8_msgstr,
+ pmsgstr_split->text);
+ if (!(last && len == 0))
+ fprintf(output,
+ "\"%s%s\"\n",
+ u8_msgstr,
+ last ? "" :
+ "\\n");
+ }
+ for (size_t i = 0; i < num_lines; i++)
+ {
+ pmsgstr_split =
+ msgstr_split + i;
+ free_bufferline(pmsgstr_split);
+ }
+ free(msgstr_split);
+ }
+ else
+ {
+ char u8_msgstr[MAXMSG*6];
+ unicode_string_to_u8(u8_msgstr,
+ *(current->msgstr + m));
+ fprintf(output, "msgstr[%ld] \"%s\"\n",
+ m, u8_msgstr);
+ }
+ }
+ }
+ else
+ fprintf(output, "msgstr \"\"\n");
+
+ fprintf(output, "\n");
+ current++;
+ }
+ fclose(output);
+
+ rename(filename, backup_filename);
+ rename(tmp_filename, filename);
+ free(backup_filename);
+
return SAVE_ERR_NONE;
}
@@ -424,7 +736,7 @@ parse_po_line(const char* line, struct PoEntry** entries, size_t* entries_size,
if (*col == 2 && *state & PS_COMMENT)
{
*state &= ~PS_COMMENT;
- *state |= PS_COMMENT_DESC;
+ *state |= PS_COMMENT_TRANS;
pline++;
(*col)++;
if (*pline == ' ')
@@ -485,7 +797,9 @@ parse_po_line(const char* line, struct PoEntry** entries, size_t* entries_size,
break;
case '"':
/* skip beginning and end quote */
- if (ptoken == token || *(pline+1) == 0)
+ if ((ptoken == token || *(pline+1) == 0)
+ && !(*state & (PS_COMMENT |
+ PS_COMMENT_TRANS)))
{
pline++;
(*col)++;
@@ -538,12 +852,18 @@ parse_po_line(const char* line, struct PoEntry** entries, size_t* entries_size,
}
else if (*state & PS_MSGSTR_ARRAY)
set_msgstr(*current_entry, token, *msgstr_index, 1);
- else if (*state & PS_COMMENT_DESC)
+ else if (*state & PS_COMMENT)
{
uint32_t u32_token[MAXCOMMENTLINE];
u8_string_to_unicode(u32_token, token);
u32_add_comment(*current_entry, u32_token);
}
+ else if (*state & PS_COMMENT_TRANS)
+ {
+ uint32_t u32_token[MAXCOMMENTLINE];
+ u8_string_to_unicode(u32_token, token);
+ u32_add_trans_comment(*current_entry, u32_token);
+ }
else if (*state & PS_COMMENT_FLAG)
{
ptoken = token;
@@ -574,9 +894,13 @@ parse_po_line(const char* line, struct PoEntry** entries, size_t* entries_size,
add_ref_comment(*current_entry, token);
*token = 0;
}
+ else if (*state & PS_COMMENT)
+ u32_add_comment(*current_entry, (uint32_t*)L"");
+ else if (*state & PS_COMMENT_TRANS)
+ u32_add_trans_comment(*current_entry, (uint32_t*)L"");
/* one-line states */
- *state &= ~(PS_COMMENT | PS_COMMENT_DESC | PS_COMMENT_FLAG |
+ *state &= ~(PS_COMMENT | PS_COMMENT_TRANS | PS_COMMENT_FLAG |
PS_COMMENT_REF);
return PARSE_ERR_NONE;
diff --git a/po.h b/po.h
@@ -29,19 +29,21 @@ enum {
};
enum {
- SAVE_ERR_NONE = 0
+ SAVE_ERR_NONE = 0,
+ SAVE_ERR_CANT_ALLOC = 1,
+ SAVE_ERR_CANT_OPEN_FILE = 2
};
typedef enum {
- PS_NONE = 0,
- PS_COMMENT = 1,
- PS_COMMENT_DESC = 1 << 1,
- PS_COMMENT_FLAG = 1 << 2,
- PS_COMMENT_REF = 1 << 3,
- PS_MSGID = 1 << 4,
- PS_MSGID_PLURAL = 1 << 5,
- PS_MSGSTR = 1 << 6,
- PS_MSGSTR_ARRAY = 1 << 7
+ PS_NONE = 0,
+ PS_COMMENT = 1,
+ PS_COMMENT_TRANS = 1 << 1,
+ PS_COMMENT_FLAG = 1 << 2,
+ PS_COMMENT_REF = 1 << 3,
+ PS_MSGID = 1 << 4,
+ PS_MSGID_PLURAL = 1 << 5,
+ PS_MSGSTR = 1 << 6,
+ PS_MSGSTR_ARRAY = 1 << 7
} ParseState;
typedef enum {
@@ -59,6 +61,8 @@ struct PoEntry {
int msgstr_count;
uint32_t** comments;
size_t comment_lines;
+ uint32_t** trans_comments;
+ size_t trans_comment_lines;
char** ref_comments;
size_t ref_comment_lines;
};
@@ -84,11 +88,14 @@ struct PoEntry* u32_set_plural_forms(struct PoEntry* entry,
struct PoEntry* u32_set_msgstr(struct PoEntry* entry, const uint32_t* msgstr,
int msgstr_index, int append);
struct PoEntry* u32_add_comment(struct PoEntry* entry, const uint32_t* comment);
+struct PoEntry* u32_add_trans_comment(struct PoEntry* entry,
+ const uint32_t* trans_comment);
struct PoEntry* add_ref_comment(struct PoEntry* entry, const char* comment);
int load_file(struct PoEntry** entries, size_t* entries_size,
size_t* entries_count, const char* filename, long* lineno,
long* col);
-int save_file(const struct PoEntry* entries, const char* filename);
+int save_file(const struct PoEntry* entries, const size_t msgid_count,
+ const char* filename);
int parse_po_line(const char* line, struct PoEntry** entries,
size_t* entries_size, size_t* entries_count,
struct PoEntry** current_entry, ParseState* state, long* col,
diff --git a/poe.1.in b/poe.1.in
@@ -108,6 +108,10 @@ _
.
.sp 1
.
+.LP
+When the info box is focused, arrow keys, C-B/C-F (PgUp/PgDn) and C-A/C-E
+(Home/End) keys scroll the info box.
+.
.SH "KNOWN LIMITATIONS"
.
.IP \(bu 4
@@ -128,6 +132,11 @@ for more details.
Only one file can be edited at a time, and no additional files can be loaded at
runtime. This is a design decision.
.
+.IP \(bu
+The directory \fC/tmp\fP must be writeable by the user in order to write the
+changes to the file. This is due to creating backups in order to avoid the
+potential data loss under specific circumstances (loss of power during write).
+.
.SH BUGS
.
.LP
diff --git a/poe.c b/poe.c
@@ -84,7 +84,24 @@ quit_callback(struct DrawState* state, struct tb_event* ev)
{
if (state)
{
- // if (ev->ch == 'y')...
+ if (ev->ch == 'y')
+ {
+ int result = save_file(state->entries,
+ state->msgid_count, state->filename);
+ switch (result)
+ {
+ case SAVE_ERR_CANT_ALLOC:
+ strcpy(state->error,
+ errors[ERR_CANT_ALLOC]);
+ break;
+ case SAVE_ERR_CANT_OPEN_FILE:
+ strcpy(state->error,
+ errors[ERR_CANT_SAVE]);
+ break;
+ default:
+ state->error[0] = 0;
+ }
+ }
state->dirty = 0;
state->prompt_callback = NULL;
state->running = 0;
@@ -141,6 +158,8 @@ load_info(struct DrawState* state)
}
if (current->comments)
num_lines += current->comment_lines + 1;
+ if (current->trans_comments)
+ num_lines += current->trans_comment_lines + 1;
if (current->ref_comments)
num_lines += current->ref_comment_lines + 1;
newbuf = calloc(num_lines, sizeof(struct BufferLine));
@@ -187,11 +206,6 @@ load_info(struct DrawState* state)
pumsgid += len+(pumsgid[len] ? 2 : 0);
pnewbuf++;
}
- /*
- *pnewbuf->text[0] = 0;
- *pnewbuf->length = 0;
- *pnewbuf++;
- */
}
if (current->msgid_plural)
{
@@ -217,11 +231,6 @@ load_info(struct DrawState* state)
pumsgid += len+(pumsgid[len] ? 2 : 0);
pnewbuf++;
}
- /*
- *pnewbuf->text[0] = 0;
- *pnewbuf->length = 0;
- *pnewbuf++;
- */
if (first->plural_forms)
{
newlen = u32_u8_strncpy(pnewbuf->text, "Plural forms:",
@@ -238,11 +247,6 @@ load_info(struct DrawState* state)
if (newlen > state->info_rows_maxlen)
state->info_rows_maxlen = newlen;
pnewbuf++;
- /*
- *pnewbuf->text[0] = 0;
- *pnewbuf->length = 0;
- *pnewbuf++;
- */
}
}
if (current->comments)
@@ -266,11 +270,28 @@ load_info(struct DrawState* state)
state->info_rows_maxlen = newlen;
pnewbuf++;
}
- /*
- *pnewbuf->text[0] = 0;
- *pnewbuf->length = 0;
- *pnewbuf++;
- */
+ }
+ if (current->trans_comments)
+ {
+ newlen = u32_u8_strncpy(pnewbuf->text, "Translation comments:",
+ MAXBUFLINE);
+ pnewbuf->length = newlen;
+ if (newlen > state->info_rows_maxlen)
+ state->info_rows_maxlen = newlen;
+ pnewbuf->fg = EDIT_MSGID_HEADING_FG;
+ pnewbuf->bg = EDIT_MSGID_HEADING_BG;
+ pnewbuf++;
+ for (size_t i = 0; i < current->trans_comment_lines; i++)
+ {
+ uint32_t* trans_comment = current->trans_comments[i];
+ size_t len = u32_strlen(trans_comment);
+ newlen = u32_strncpy(pnewbuf->text, trans_comment,
+ MIN(len+1, MAXBUFLINE));
+ pnewbuf->length = newlen;
+ if (newlen > state->info_rows_maxlen)
+ state->info_rows_maxlen = newlen;
+ pnewbuf++;
+ }
}
if (current->ref_comments)
{
@@ -387,7 +408,7 @@ save_msgstr(struct DrawState* state)
u32_encode_tabs(to_save, MAXBUFLINE);
u32_set_msgstr(&state->entries[state->msgid_number-1], to_save,
state->msgstr_index, 0);
- state->dirty = 1;
+ //state->dirty = 1;
}
void
@@ -403,6 +424,7 @@ cancel_msgstr(struct DrawState* state)
free_bufferline(state->info_buffer+i);
free(state->info_buffer);
state->info_buffer = NULL;
+ state->dirty = state->dirty_before_edit;
}
void
@@ -743,6 +765,7 @@ insert_char(struct DrawState* state, uint32_t ch)
> EDIT_WIDTH-5)
state->input_first_shown_column = state->input_display_column
- EDIT_WIDTH+5;
+ state->dirty = 1;
}
void
@@ -763,6 +786,7 @@ erase_to_start(struct DrawState* state)
buffer_line->text[len-state->input_column] = 0;
buffer_line->length = len-state->input_column;
move_start(state);
+ state->dirty = 1;
}
void
@@ -774,6 +798,7 @@ erase_to_end(struct DrawState* state)
buffer_line->text[state->input_column] = 0;
buffer_line->length = state->input_column;
move_end(state);
+ state->dirty = 1;
}
struct DrawState*
@@ -816,6 +841,7 @@ insert_line(struct DrawState* state)
state->input_first_shown_row = state->input_row -
(EDIT_HEIGHT-3)/2;
move_start(state);
+ state->dirty = 1;
return state;
}
@@ -851,6 +877,7 @@ join_lines(struct DrawState* state, size_t first_line)
if (!newbuf)
return NULL;
state->input_buffer = newbuf;
+ state->dirty = 1;
return state;
}
@@ -941,6 +968,7 @@ handle_editbox_key_event(struct tb_event* ev, struct DrawState* state)
}
buffer_line->text[i] = 0;
buffer_line->length--;
+ state->dirty = 1;
}
else if (state->input_row < state->input_rows_count-1)
if (!join_lines(state, state->input_row))
@@ -981,6 +1009,7 @@ handle_editbox_key_event(struct tb_event* ev, struct DrawState* state)
else
{
save_msgstr(state);
+ state->dirty_before_edit = state->dirty;
move_list_down(state);
state->msgstr_index = 0;
load_msgstr(state);
@@ -1083,6 +1112,23 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
move_list_page_up(state);
else if (ev->key == TB_KEY_CTRL_F || ev->key == TB_KEY_PGDN)
move_list_page_down(state);
+ else if (ev->key == TB_KEY_CTRL_S || ev->ch == 'w')
+ {
+ int result = save_file(state->entries, state->msgid_count,
+ state->filename);
+ switch (result)
+ {
+ case SAVE_ERR_CANT_ALLOC:
+ strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ break;
+ case SAVE_ERR_CANT_OPEN_FILE:
+ strcpy(state->error, errors[ERR_CANT_SAVE]);
+ break;
+ default:
+ state->error[0] = 0;
+ }
+ state->dirty = 0;
+ }
else if (ev->key == TB_KEY_CTRL_Z
|| (ev->ch == 'f' && !state->show_edit))
toggle_fuzzy(state);
@@ -1098,6 +1144,7 @@ handle_key_event(struct tb_event* ev, struct DrawState* state)
state->msgstr_index = 0;
if (load_msgstr(state) && load_info(state))
{
+ state->dirty_before_edit = state->dirty;
state->show_edit = 1;
state->input_row = 0;
state->input_first_shown_row = 0;
@@ -1160,6 +1207,7 @@ main(int argc, char** argv)
if (!(input = fopen(filename, "rt")))
return print_error(ENOENT, "No such file `%s'", filename);
+ fclose(input);
long lineno = 1;
long col = 1;
@@ -1180,8 +1228,8 @@ main(int argc, char** argv)
case LOAD_ERR_P_INVAL:
return print_error(result, "Invalid value");
case LOAD_ERR_P_SYNTAX:
- return print_error(result, "%s:%ld: Syntax error",
- filename, lineno);
+ return print_error(result, "%s:%ld:%ld: Syntax error",
+ filename, lineno, col);
case LOAD_ERR_NONE:
break;
default:
@@ -1268,8 +1316,9 @@ main(int argc, char** argv)
nanosleep(&sleep_spec, NULL);
}
}
- fclose(input);
tb_shutdown();
+ if (state.error && state.error[0])
+ return print_error(1, state.error);
return 0;
}
diff --git a/util.h b/util.h
@@ -10,10 +10,11 @@ enum {
ERR_DLG_OPEN,
ERR_DLG_OPEN_QUIT,
ERR_EMPTY_FILE,
- ERR_CANT_ALLOC
+ ERR_CANT_ALLOC,
+ ERR_CANT_SAVE
};
-#define MAXBUFLINE 1024
+#define MAXBUFLINE 4096
#define MAXMSG 1024
#define MAXPATH 1024
#define MAXFLAGSBUF 3+1