poe

Уређивач .po фајлова
git clone https://git.sr.ht/~strahinja/poe
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување b5e9596130f4a5b2eb5b0c64e176f04d04691419
родитељ d1019afbfcd2a3efc2dcf18a03d1d285d28f0d72
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Thu, 12 Feb 2026 23:15:17 +0100

WIP continue converting, optimizing and fixing old code

Diffstat:
Mpo.c | 924++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mpo.h | 26++++++++++++++++++++------
Mpoe.c | 16++++++++--------
Mpoe.h | 2+-
измењених датотека: 4, додавања: 493(+), брисања: 475(-)

diff --git a/po.c b/po.c @@ -22,6 +22,7 @@ extern const char* flag_strings[]; // TODO: Check ifdef PLURAL_ ... +extern int cp(const char* from, const char* to); extern int print_error(const int code, const char* msg, ...); extern void redraw_status(struct DrawState* state); @@ -41,26 +42,26 @@ format_flags(char* buffer, const size_t max, const struct PoEntry* entry, void init_po_entry(struct PoEntry* entry) { - entry->flags = FL_NONE; - entry->obsolete = 0; - entry->warning = 0; - entry->msgid = NULL; - entry->msgid_size = 0; - entry->msgid_len = 0; - entry->msgid_plural = NULL; - entry->msgid_plural_size = 0; - entry->msgid_plural_len = 0; - entry->plural_forms = NULL; - entry->msgstr = NULL; - entry->msgstr_count = 0; - entry->msgstr_size = NULL; - entry->msgstr_len = NULL; - 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; + entry->flags = FL_NONE; + entry->obsolete = 0; + entry->warning = 0; + entry->msgid = NULL; + entry->msgid_size = 0; + entry->msgid_len = 0; + entry->msgid_plural = NULL; + entry->msgid_plural_size = 0; + entry->msgid_plural_len = 0; + entry->plural_forms = NULL; + entry->msgstr = NULL; + entry->msgstr_count = 0; + entry->msgstr_size = NULL; + entry->msgstr_len = NULL; + entry->comments = NULL; + entry->comment_lines = 0; + entry->extr_comments = NULL; + entry->extr_comment_lines = 0; + entry->ref_comments = NULL; + entry->ref_comment_lines = 0; } void @@ -90,13 +91,13 @@ free_po_entry(struct PoEntry* entry) free(entry->comments); } - if (entry->trans_comments) + if (entry->extr_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); + uint32_t** extr_comment = entry->extr_comments; + while (extr_comment + < entry->extr_comments + entry->extr_comment_lines) + free(*extr_comment++); + free(entry->extr_comments); } if (entry->ref_comments) @@ -157,6 +158,7 @@ set_msgstr(struct PoEntry* entry, const char* msgstr, int msgstr_index, { uint32_t umsgstr[MAXMSGLINE]; assert(entry != NULL); + umsgstr[0] = 0; if (msgstr) u8_string_to_unicode(umsgstr, msgstr, MAXMSGLINE); return u32_set_msgstr(entry, umsgstr, msgstr_index, append, state); @@ -290,42 +292,42 @@ u32_set_msgstr(struct PoEntry* entry, const uint32_t* msgstr, int msgstr_index, } if (!newmsgstr || !newmsgstr_size || !newmsgstr_len) { - free(newmsgstr); + /*free(newmsgstr); free(newmsgstr_len); - free(newmsgstr_size); + free(newmsgstr_size);*/ return NULL; } - *(newmsgstr + msgstr_index) = NULL; + newmsgstr[msgstr_index] = NULL; entry->msgstr = newmsgstr; entry->msgstr_size = newmsgstr_size; entry->msgstr_len = newmsgstr_len; } - if (!*(entry->msgstr + msgstr_index)) + if (!entry->msgstr[msgstr_index]) { - *(entry->msgstr_size + msgstr_index) = MSGDELTA; - *(entry->msgstr_len + msgstr_index) = 0; - *(entry->msgstr + msgstr_index) - = calloc(*(entry->msgstr_size + msgstr_index), + entry->msgstr_size[msgstr_index] = MSGDELTA; + entry->msgstr_len[msgstr_index] = 0; + entry->msgstr[msgstr_index] + = calloc(entry->msgstr_size[msgstr_index], sizeof(uint32_t)); } - else if (*(entry->msgstr_len + msgstr_index) + msgstr_len - >= *(entry->msgstr_size + msgstr_index)) + else if (entry->msgstr_len[msgstr_index] + msgstr_len + >= entry->msgstr_size[msgstr_index]) { - *(entry->msgstr_size + msgstr_index) += MSGDELTA; - *(entry->msgstr + msgstr_index) - = realloc(*(entry->msgstr + msgstr_index), - *(entry->msgstr_size + msgstr_index) + entry->msgstr_size[msgstr_index] += MSGDELTA; + entry->msgstr[msgstr_index] + = realloc(entry->msgstr[msgstr_index], + entry->msgstr_size[msgstr_index] * sizeof(uint32_t)); } - *(entry->msgstr_len + msgstr_index) += msgstr_len; - if (!*(entry->msgstr + msgstr_index)) + entry->msgstr_len[msgstr_index] += msgstr_len; + if (!entry->msgstr[msgstr_index]) return NULL; if (append) - u32_strncat(*(entry->msgstr + msgstr_index), msgstr, - *(entry->msgstr_size + msgstr_index)); + u32_strncat(entry->msgstr[msgstr_index], msgstr, + entry->msgstr_size[msgstr_index]); else - u32_strncpy(*(entry->msgstr + msgstr_index), msgstr, - *(entry->msgstr_size + msgstr_index)); + u32_strncpy(entry->msgstr[msgstr_index], msgstr, + entry->msgstr_size[msgstr_index]); return entry; } @@ -359,32 +361,32 @@ u32_add_comment(struct PoEntry* entry, const uint32_t* comment) } struct PoEntry* -u32_add_trans_comment(struct PoEntry* entry, const uint32_t* trans_comment) +u32_add_extr_comment(struct PoEntry* entry, const uint32_t* extr_comment) { - uint32_t** trans_comments = NULL; - uint32_t* new_line = NULL; - size_t len = 0; + uint32_t** extr_comments = NULL; + uint32_t* new_line = NULL; + size_t len = 0; if (!entry) return NULL; - entry->trans_comment_lines++; - if (!entry->trans_comments) - trans_comments - = calloc(entry->trans_comment_lines, sizeof(uint32_t*)); + entry->extr_comment_lines++; + if (!entry->extr_comments) + extr_comments + = calloc(entry->extr_comment_lines, sizeof(uint32_t*)); else - trans_comments = realloc(entry->trans_comments, - entry->trans_comment_lines * sizeof(uint32_t*)); - if (!trans_comments) + extr_comments = realloc(entry->extr_comments, + entry->extr_comment_lines * sizeof(uint32_t*)); + if (!extr_comments) return NULL; - entry->trans_comments = trans_comments; + entry->extr_comments = extr_comments; - len = u32_strlen(trans_comment) + 1; + len = u32_strlen(extr_comment) + 1; new_line = calloc(len, sizeof(uint32_t)); if (!new_line) return NULL; - entry->trans_comments[entry->trans_comment_lines - 1] = new_line; - u32_strncpy(new_line, trans_comment, len); + entry->extr_comments[entry->extr_comment_lines - 1] = new_line; + u32_strncpy(new_line, extr_comment, len); return entry; } @@ -485,8 +487,9 @@ load_file(struct DrawState* dstate, long* lineno, long* col) if (nulbyte && (nulbyte != eol)) possible_nulbyte = 1; - parse_po_line(input_line, dstate, &entry, &pstate, col, - &msgstr_index); + if (parse_po_line(input_line, dstate, &entry, &pstate, col, + &msgstr_index)) + return 1; if (entry && entry->msgid_plural) has_plural_msgid = 1; @@ -498,7 +501,6 @@ load_file(struct DrawState* dstate, long* lineno, long* col) msgid_counter = -1; else if (msgid_counter != -1) msgid_counter--; - if (msgid_counter == 0) { dstate->error = ERR_NOTPO_FILE; @@ -571,82 +573,77 @@ load_file_alloc_error: } int +save_comment(FILE* output, struct DrawState* state, + const struct PoEntry* current) +{ + char* u8_comment = NULL; + char* temp = NULL; + size_t c, len, size; + + assert((output != NULL) && (state != NULL) && (current != NULL)); + for (c = 0; c < current->comment_lines; c++) + { + len = u32_strlen(current->comments[c]); + size = len * UTF8REPMAX + 1; + temp = realloc(u8_comment, size); + if (!temp) + { + state->error = ERR_CANT_ALLOC; + return 1; + } + u8_comment = temp; + unicode_string_to_u8(u8_comment, current->comments[c], len); + fprintf(output, "#%s%s\n", current->obsolete ? "~ " : "", + u8_comment); + } + free(u8_comment); + return 0; +} + +int save_file(struct DrawState* state) { FILE* output = NULL; const struct PoEntry* current = NULL; struct stat st; - char* real_filename = NULL; - char* backup_filename = NULL; - ssize_t rfn_len = 0; - Flags flags; - int saved_errno; int result = 0; + int saved_errno; assert(state != NULL); + + state->action = ACT_WRITING; + redraw_status(state); + errno = 0; + current = state->entries; - if (!(real_filename = calloc(MAXPATH, 1))) - return SAVE_ERR_CANT_ALLOC; if (!create_backups) goto save_skip_backup_copy; if (!backup_fail && !state->backup_possible) goto save_skip_backup_copy; - if (!(backup_filename = calloc(MAXPATH, 1))) - { - free(real_filename); - return SAVE_ERR_CANT_ALLOC; - } - if (lstat(state->filename, &st) != -1) + if ((unlink(state->backup_filename) < 0) && (errno != ENOENT)) { - if (S_ISLNK(st.st_mode)) - { - rfn_len = readlink(state->filename, real_filename, - MAXPATH); - if (rfn_len == -1) - { - result = SAVE_ERR_CANT_READLINK; - goto save_loop_entries_done; - } - real_filename[rfn_len] = 0; - if (stat(real_filename, &st) == -1) - { - result = SAVE_ERR_CANT_STAT_FILE; - goto save_loop_entries_done; - } - } - STRLCPY(state->filename, backup_filename, MAXPATH); - STRLCAT(backup_suffix, backup_filename, MAXPATH); - if (rename(rfn_len > 0 ? real_filename : state->filename, - backup_filename) - == -1) - { - result = SAVE_ERR_CANT_MOVE_FILE; - goto save_loop_entries_done; - } - } - else - { - result = SAVE_ERR_CANT_STAT_FILE; - goto save_loop_entries_done; + state->error = ERR_ERRNO_SET; + result = 1; + goto save_file_cleanup; } - if (rfn_len > 0) + + if (cp(state->rfn_len > 0 ? state->real_filename : state->filename, + state->backup_filename)) { - if (unlink(state->filename) == -1) + if (backup_fail) { - result = SAVE_ERR_CANT_UNLINK; - goto save_loop_entries_done; - } - if (symlink(real_filename, state->filename) == -1) - { - result = SAVE_ERR_CANT_SYMLINK; - goto save_loop_entries_done; + state->error = ERR_ERRNO_SET; + result = 1; + goto save_file_cleanup; } + else + errno = 0; /* ignore errors */ } - chmod(rfn_len > 0 ? real_filename : state->filename, st.st_mode); save_skip_backup_copy: - if (!(output = fopen(rfn_len > 0 ? real_filename : state->filename, + if (!(output = fopen(state->rfn_len > 0 ? state->real_filename + : state->filename, "wt"))) { state->error = ERR_ERRNO_SET; @@ -654,82 +651,108 @@ save_skip_backup_copy: goto save_file_cleanup; } -save_loop_entries_start: - if (current >= state->entries + state->real_msgid_count) - goto save_loop_entries_done; + if (!create_backups) + goto save_skip_backup_symlink; - if (current->obsolete) - goto save_flags; + if (lstat(state->rfn_len > 0 ? state->real_filename : state->filename, + &st) + < 0) + { + state->error = ERR_ERRNO_SET; + result = 1; + goto save_file_cleanup; + } + + if (!backup_fail && !state->backup_possible) + goto save_skip_backup_symlink; -save_comments: - if (current->comment_lines > 0) + if (state->rfn_len > 0) { - char* u8_comment = NULL; - for (size_t c = 0; c < current->comment_lines; c++) + if (unlink(state->filename) == -1) { - size_t len = u32_strlen(*(current->comments + c)); - size_t size = len * UTF8REPMAX + 1; - if (!u8_comment) - { - u8_comment = malloc(size); - memset(u8_comment, 0, size); - } - else - u8_comment = realloc(u8_comment, size); - if (!u8_comment) - { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; - } - unicode_string_to_u8(u8_comment, - *(current->comments + c), len); - fprintf(output, "#%s%s\n", current->obsolete ? "~" : "", - u8_comment); + state->error = ERR_ERRNO_SET; + result = 1; + goto save_file_cleanup; } - free(u8_comment); - } - if (current->trans_comment_lines > 0) - { - char* u8_trans_comment = NULL; - for (size_t tc = 0; tc < current->trans_comment_lines; tc++) + if (symlink(state->orig_real_filename, state->filename) == -1) { - size_t len - = u32_strlen(*(current->trans_comments + tc)); - size_t size = len * UTF8REPMAX + 1; - - if (!u8_trans_comment) - { - u8_trans_comment = malloc(size); - memset(u8_trans_comment, 0, size); - } - else - u8_trans_comment - = realloc(u8_trans_comment, size); - if (!u8_trans_comment) - { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; - } - unicode_string_to_u8(u8_trans_comment, - *(current->trans_comments + tc), len); - fprintf(output, "#.%s%s\n", - u8_trans_comment[0] == 0 ? "" : " ", - u8_trans_comment); + state->error = ERR_ERRNO_SET; + result = 1; + goto save_file_cleanup; } - free(u8_trans_comment); } + chmod(state->rfn_len > 0 ? state->real_filename : state->filename, + st.st_mode); + +save_skip_backup_symlink: + /*if (state->rows_count == 1 && state->buffer[0].length == 0) + goto save_file_cleanup;*/ + + ; + +save_loop_entries_start: + if (current >= state->entries + state->real_msgid_count) + goto save_loop_entries_done; + + if (!current->obsolete && current->comment_lines > 0) + if (save_comment(output, state, current)) + return 1; + if (current->extr_comment_lines > 0) + if (save_extr_comment(output, state, current)) + return 1; if (current->ref_comment_lines > 0) + if (save_ref_comment(output, state, current)) + return 1; + if (save_flags(output, state, current)) + return 1; + if (current->obsolete && current->comment_lines > 0) + if (save_comment(output, state, current)) + return 1; + + if (current->obsolete) { - for (size_t rc = 0; rc < current->ref_comment_lines; rc++) - fprintf(output, "#: %s\n", - *(current->ref_comments + rc)); + if (current < state->entries + state->real_msgid_count - 1) + fprintf(output, "\n"); + current++; + goto save_loop_entries_start; } - if (current->obsolete) - goto save_obsolete_check; -save_flags: + save_msgid(output, state, current); + if (current->msgid_plural) + if (save_msgid_plural(output, state, current)) + return 1; + + if (save_msgstrs(output, state, current)) + return 1; + + if (current < state->entries + state->real_msgid_count - 1) + fprintf(output, "\n"); + current++; + goto save_loop_entries_start; + + /*save_file_alloc_error: + if (output) + fclose(output); + return 1;*/ + +save_loop_entries_done: +save_file_cleanup: + saved_errno = errno; + if (output) + fclose(output); + state->action = ACT_IDLE; + errno = saved_errno; + return result; +} + +int +save_flags(FILE* output, struct DrawState* state, const struct PoEntry* current) +{ + Flags flags; + + assert((output != NULL) && (state != NULL) && (current != NULL)); flags = current->flags; - if (current->flags != FL_NONE) + if (flags != FL_NONE) fprintf(output, "#, "); while (flags != FL_NONE) { @@ -756,336 +779,297 @@ save_flags: } if (current->flags != FL_NONE) fprintf(output, "\n"); - if (current->obsolete) - goto save_comments; + return 0; +} -save_obsolete_check: - if (current->obsolete) +int +save_msgid(FILE* output, struct DrawState* state, const struct PoEntry* current) +{ + const uint32_t* pumsgid = NULL; + const uint32_t* old_pumsgid = NULL; + char* u8_msgid = NULL; + size_t len = 0; + size_t num_lines; + size_t size; + + assert((output != NULL) && (state != NULL) && (current != NULL)); + if (!current->msgid) { - if (current < state->entries + state->real_msgid_count - 1) - fprintf(output, "\n"); - current++; - goto save_loop_entries_start; + fprintf(output, "msgid \"\"\n"); + return 0; } + num_lines = u32_lines_in_string(current->msgid, 1, wrap_width); - if (current->msgid) + if ((num_lines > 1) + && (u32_strlen(current->msgid) > SAVE_MULTILINE_TRESHOLD)) { - size_t num_lines - = u32_lines_in_string(current->msgid, 1, wrap_width); - - if ((num_lines > 1) - && (u32_strlen(current->msgid) - > SAVE_MULTILINE_TRESHOLD)) + pumsgid = current->msgid; + fprintf(output, "msgid \"\"\n"); + while (*pumsgid) { - const uint32_t* pumsgid = current->msgid; - - fprintf(output, "msgid \"\"\n"); - - while (*pumsgid) - { - size_t len = 0; - size_t size; - char* u8_msgid = NULL; - const uint32_t* old_pumsgid = pumsgid; + u8_msgid = NULL; + old_pumsgid = pumsgid; + len = 0; - len = u32_next_line(current->msgid, &pumsgid, 1, - wrap_width); - if (len == 0) - continue; + len = u32_next_line(current->msgid, &pumsgid, 1, + wrap_width); + if (len == 0) + continue; - size = len * UTF8REPMAX + 1; - - u8_msgid = malloc(size); - if (!u8_msgid) - { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; - } - - memset(u8_msgid, 0, size); - - unicode_string_to_u8(u8_msgid, old_pumsgid, len); - fprintf(output, "\"%s\"\n", u8_msgid); - free(u8_msgid); - } - } - else - { - size_t size; - char* u8_msgid = NULL; + size = len * UTF8REPMAX + 1; - size = current->msgid_size * UTF8REPMAX + 1; u8_msgid = malloc(size); if (!u8_msgid) { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; + state->error = ERR_CANT_ALLOC; + return 1; } memset(u8_msgid, 0, size); - unicode_string_to_u8(u8_msgid, current->msgid, - current->msgid_size); - fprintf(output, "msgid \"%s\"\n", u8_msgid); + unicode_string_to_u8(u8_msgid, old_pumsgid, len); + fprintf(output, "\"%s\"\n", u8_msgid); free(u8_msgid); } } else - fprintf(output, "msgid \"\"\n"); - - if (current->msgid_plural) { - size_t num_lines = u32_lines_in_string(current->msgid_plural, 1, - wrap_width); - - if ((num_lines > 1) - && (u32_strlen(current->msgid_plural) - > SAVE_MULTILINE_TRESHOLD)) + size = current->msgid_size * UTF8REPMAX + 1; + u8_msgid = malloc(size); + if (!u8_msgid) { - const uint32_t* pumsgid = current->msgid_plural; - - fprintf(output, "msgid_plural \"\"\n"); + state->error = ERR_CANT_ALLOC; + return 1; + } - while (*pumsgid) - { - size_t len = 0; - char* u8_msgid = NULL; - const uint32_t* old_pumsgid = pumsgid; - size_t size; - - len = u32_next_line(current->msgid_plural, - &pumsgid, 1, wrap_width); - if (len == 0) - continue; - - size = len * UTF8REPMAX + 1; - u8_msgid = malloc(size); - if (!u8_msgid) - { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; - } + memset(u8_msgid, 0, size); - memset(u8_msgid, 0, size); + unicode_string_to_u8(u8_msgid, current->msgid, + current->msgid_size); + fprintf(output, "msgid \"%s\"\n", u8_msgid); + free(u8_msgid); + } + return 0; +} - unicode_string_to_u8(u8_msgid, old_pumsgid, len); - fprintf(output, "\"%s\"\n", u8_msgid); - free(u8_msgid); - } - } - else +int +save_msgid_plural(FILE* output, struct DrawState* state, + const struct PoEntry* current) +{ + const uint32_t* old_pumsgid = NULL; + const uint32_t* pumsgid = NULL; + char* u8_msgid = NULL; + size_t len = 0; + size_t msgid_plural_len, num_lines, size; + + assert((output != NULL) && (state != NULL) && (current != NULL)); + num_lines = u32_lines_in_string(current->msgid_plural, 1, wrap_width); + if ((num_lines > 1) + && (u32_strlen(current->msgid_plural) > SAVE_MULTILINE_TRESHOLD)) + { + pumsgid = current->msgid_plural; + fprintf(output, "msgid_plural \"\"\n"); + while (*pumsgid) { - char* u8_msgid = NULL; - size_t size; - size_t msgid_plural_len; - - size = current->msgid_plural_size * UTF8REPMAX + 1; + len = 0; + u8_msgid = NULL; + old_pumsgid = pumsgid; + len = u32_next_line(current->msgid_plural, &pumsgid, 1, + wrap_width); + if (len == 0) + continue; + + size = len * UTF8REPMAX + 1; u8_msgid = malloc(size); if (!u8_msgid) { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; + state->error = ERR_CANT_ALLOC; + return 1; } - memset(u8_msgid, 9, size); + memset(u8_msgid, 0, size); - msgid_plural_len = u32_strlen(current->msgid_plural); - unicode_string_to_u8(u8_msgid, current->msgid_plural, - msgid_plural_len); - fprintf(output, "msgid_plural \"%s\"\n", u8_msgid); + unicode_string_to_u8(u8_msgid, old_pumsgid, len); + fprintf(output, "\"%s\"\n", u8_msgid); free(u8_msgid); } } + else + { + size = current->msgid_plural_size * UTF8REPMAX + 1; + u8_msgid = malloc(size); + if (!u8_msgid) + { + state->error = ERR_CANT_ALLOC; + return 1; + } + + memset(u8_msgid, 9, size); + + msgid_plural_len = u32_strlen(current->msgid_plural); + unicode_string_to_u8(u8_msgid, current->msgid_plural, + msgid_plural_len); + fprintf(output, "msgid_plural \"%s\"\n", u8_msgid); + free(u8_msgid); + } + return 0; +} +int +save_msgstrs(FILE* output, struct DrawState* state, + const struct PoEntry* current) +{ + const uint32_t* pumsgstr = NULL; + const uint32_t* old_pumsgstr = NULL; + char now[MAXDATEBUF]; + char* u8_msgstr = NULL; + struct tm* now_tm = NULL; + time_t t; + ssize_t m, num_lines; + size_t len, size, msgstr_len; + int i; + int seen_generator = 0; + int seen_plural_forms = 0; + int first_entry; + + assert((output != NULL) && (state != NULL) && (current != NULL)); + first_entry = (current == state->entries) && !current->msgid; + if (!current->msgstr_count) + { + if (current->msgid_plural) + for (i = 0; i < state->nplurals; i++) + fprintf(output, "msgstr[%d] \"\"\n", i); + else + fprintf(output, "msgstr \"\"\n"); + return 0; + } if (current->msgstr_count == 1) { - ssize_t num_lines - = u32_lines_in_string(*current->msgstr, 1, wrap_width); - int first_entry - = (current == state->entries) && !current->msgid; - + t = time(NULL); + now_tm = localtime(&t); + strftime(now, MAXDATEBUF, "%F %H:%M%z", now_tm); + } + for (m = 0; m < current->msgstr_count; m++) + { + num_lines = u32_lines_in_string(current->msgstr[m], 1, + wrap_width); if ((num_lines > 1) - && (first_entry - || (u32_strlen(*current->msgstr) - > (size_t)SAVE_MULTILINE_TRESHOLD))) + && (u32_strlen(current->msgstr[m]) + > SAVE_MULTILINE_TRESHOLD)) { - const uint32_t* pumsgstr = *current->msgstr; - int seen_generator = 0; - int seen_plural_forms = 0; - char now[MAXDATEBUF]; - time_t t = time(NULL); - struct tm* now_tm = localtime(&t); - - strftime(now, MAXDATEBUF, "%F %H:%M%z", now_tm); - fprintf(output, "msgstr \"\"\n"); + pumsgstr = current->msgstr[m]; + if (current->msgstr_count == 1) + fprintf(output, "msgstr \"\"\n"); + else + fprintf(output, "msgstr[%ld] \"\"\n", m); - while (*pumsgstr) + save_msgstrs_pumsgstr_loop: + len = 0; + old_pumsgstr = pumsgstr; + len = u32_next_line(current->msgstr[m], &pumsgstr, 1, + wrap_width); + if (len == 0) + goto save_msgstrs_pumsgstr_done; + size = len * UTF8REPMAX + 1; + u8_msgstr = malloc(size); + if (!u8_msgstr) { - size_t len = 0; - size_t size; - char* u8_msgstr = NULL; - const uint32_t* old_pumsgstr = pumsgstr; - - len = u32_next_line(*current->msgstr, &pumsgstr, - 1, - ((first_entry && wrap_first_msgstr) - || !first_entry) - ? wrap_width - : 0); - - if (len == 0) - continue; - - size = len * UTF8REPMAX + 1; - u8_msgstr = malloc(size); - if (!u8_msgstr) - { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; - } + state->error = ERR_CANT_ALLOC; + return 1; + } + memset(u8_msgstr, 0, size); - memset(u8_msgstr, 0, size); - - unicode_string_to_u8(u8_msgstr, old_pumsgstr, - len); - if (first_entry - && starts_with(u8_msgstr, - "PO-Revision-Date: ")) - fprintf(output, - "\"PO-Revision-Date: %s\\n\"\n", - now); - else if (first_entry - && starts_with(u8_msgstr, - "X-Generator: ")) - { - seen_generator = 1; - fprintf(output, - "\"X-Generator: poe %s\\n\"\n", - VERSION); - } - else if (first_entry && plural_string - && starts_with(u8_msgstr, - "Plural-Forms: ")) - { - seen_plural_forms = 1; - fprintf(output, - "\"Plural-Forms: %s\\n\"\n", - plural_string); - } - else - fprintf(output, "\"%s\"\n", u8_msgstr); - free(u8_msgstr); + unicode_string_to_u8(u8_msgstr, old_pumsgstr, len); + if (first_entry + && starts_with(u8_msgstr, "X-Generator: ")) + { + seen_generator = 1; + fprintf(output, "\"X-Generator: poe %s\\n\"\n", + VERSION); } - if (first_entry && plural_string && !seen_plural_forms) + else if (first_entry && plural_string + && starts_with(u8_msgstr, "Plural-Forms: ")) + { + seen_plural_forms = 1; fprintf(output, "\"Plural-Forms: %s\\n\"\n", plural_string); + } + else + fprintf(output, "\"%s\"\n", u8_msgstr); + free(u8_msgstr); + if (*pumsgstr) + goto save_msgstrs_pumsgstr_loop; + + save_msgstrs_pumsgstr_done: if (first_entry && !seen_generator) fprintf(output, "\"X-Generator: poe %s\\n\"\n", VERSION); + if (first_entry && plural_string && !seen_plural_forms) + fprintf(output, "\"Plural-Forms: %s\\n\"\n", + plural_string); } - else if (current->msgid_plural - && (!*current->msgstr || !**current->msgstr)) - for (int i = 0; i < state->nplurals; i++) - fprintf(output, "msgstr[%d] \"\"\n", i); else { - size_t size = MAXMSGLINE * UTF8REPMAX + 1; - char u8_msgstr[size]; - size_t msgstr_len; - - msgstr_len = u32_strlen(*current->msgstr); - unicode_string_to_u8(u8_msgstr, *current->msgstr, - msgstr_len); - fprintf(output, "msgstr \"%s\"\n", u8_msgstr); - } - } - else if (current->msgstr_count > 0) - { - for (ssize_t m = 0; m < current->msgstr_count; m++) - { - ssize_t num_lines - = u32_lines_in_string(*current->msgstr, 1, - wrap_width); - - if ((num_lines > 1) - && (u32_strlen(*(current->msgstr + m)) - > SAVE_MULTILINE_TRESHOLD)) + size = MAXMSGLINE * UTF8REPMAX + 1; + u8_msgstr = malloc(size); + if (!u8_msgstr) { - const uint32_t* pumsgstr - = *(current->msgstr + m); - - fprintf(output, "msgstr[%ld] \"\"\n", m); - - while (*pumsgstr) - { - size_t len = 0; - size_t size; - char* u8_msgstr = NULL; - const uint32_t* old_pumsgstr = pumsgstr; - - len = u32_next_line(*(current->msgstr - + m), - &pumsgstr, 1, wrap_width); - if (len == 0) - continue; - - size = len * UTF8REPMAX + 1; - u8_msgstr = malloc(size); - if (!u8_msgstr) - { - result = SAVE_ERR_CANT_ALLOC; - goto save_file_alloc_error; - } - - memset(u8_msgstr, 0, size); - - unicode_string_to_u8(u8_msgstr, - old_pumsgstr, len); - fprintf(output, "\"%s\"\n", u8_msgstr); - free(u8_msgstr); - } + state->error = ERR_CANT_ALLOC; + return 1; } + msgstr_len = u32_strlen(current->msgstr[m]); + unicode_string_to_u8(u8_msgstr, current->msgstr[m], + msgstr_len); + if (current->msgstr_count == 1) + fprintf(output, "msgstr \"%s\"\n", u8_msgstr); else - { - size_t size = MAXMSGLINE * UTF8REPMAX + 1; - char u8_msgstr[size]; - size_t msgstr_len; - msgstr_len = u32_strlen(*(current->msgstr + m)); - unicode_string_to_u8(u8_msgstr, - *(current->msgstr + m), msgstr_len); fprintf(output, "msgstr[%ld] \"%s\"\n", m, u8_msgstr); - } + free(u8_msgstr); } } - else - { - if (current->msgid_plural) - for (int i = 0; i < state->nplurals; i++) - fprintf(output, "msgstr[%d] \"\"\n", i); - else - fprintf(output, "msgstr \"\"\n"); - } + return 0; +} - if (current < state->entries + state->real_msgid_count - 1) - fprintf(output, "\n"); - current++; - goto save_loop_entries_start; -save_file_alloc_error: - if (output) - fclose(output); - return 1; +int +save_ref_comment(FILE* output, struct DrawState* state, + const struct PoEntry* current) +{ + size_t rc; + assert((output != NULL) && (state != NULL) && (current != NULL)); + for (rc = 0; rc < current->ref_comment_lines; rc++) + fprintf(output, "#: %s\n", current->ref_comments[rc]); + return 0; +} -save_loop_entries_done: -save_file_cleanup: - saved_errno = errno; - if (output) - fclose(output); - free(backup_filename); - free(real_filename); - state->action = ACT_IDLE; - errno = saved_errno; - return result; +int +save_extr_comment(FILE* output, struct DrawState* state, + const struct PoEntry* current) +{ + char* u8_extr_comment = NULL; + char* temp = NULL; + size_t tc, len, size; + + assert((output != NULL) && (state != NULL) && (current != NULL)); + for (tc = 0; tc < current->extr_comment_lines; tc++) + { + len = u32_strlen(current->extr_comments[tc]); + size = len * UTF8REPMAX + 1; + + temp = realloc(u8_extr_comment, size); + if (!temp) + { + state->error = ERR_CANT_ALLOC; + return 1; + } + u8_extr_comment = temp; + unicode_string_to_u8(u8_extr_comment, + current->extr_comments[tc], len); + fprintf(output, "#.%s%s\n", u8_extr_comment[0] == 0 ? "" : " ", + u8_extr_comment); + } + free(u8_extr_comment); + return 0; } #define INC_COL() \ @@ -1116,17 +1100,17 @@ parse_po_line(const char* line, struct DrawState* dstate, *token = 0; ptoken = token; - if (starts_with(line, "msgid_plural")) + if (starts_with(line, "msgid_plural ")) { - len = strlen("msgid_plural"); + len = strlen("msgid_plural "); *pstate &= ~PS_MSGID; *pstate |= PS_MSGID_PLURAL; pline += len; *col += len; } - else if (starts_with(line, "msgid")) + else if (starts_with(line, "msgid ")) { - len = strlen("msgid"); + len = strlen("msgid "); *pstate |= PS_MSGID; pline += len; *col += len; @@ -1158,9 +1142,9 @@ parse_po_line(const char* line, struct DrawState* dstate, goto parse_po_cleanup; } } - else if (starts_with(line, "msgstr")) + else if (starts_with(line, "msgstr ")) { - len = strlen("msgstr"); + len = strlen("msgstr "); *pstate &= ~PS_MSGID; *pstate &= ~PS_MSGID_PLURAL; *pstate |= PS_MSGSTR; @@ -1227,6 +1211,11 @@ parse_po_line(const char* line, struct DrawState* dstate, *pstate |= PS_COMMENT_EXTR; pline++; INC_COL(); + while (*pline == ' ' || *pline == '\t') + { + pline++; + INC_COL(); + } } else { @@ -1241,6 +1230,11 @@ parse_po_line(const char* line, struct DrawState* dstate, *pstate |= PS_COMMENT_FLAG; pline++; INC_COL(); + while (*pline == ' ' || *pline == '\t') + { + pline++; + INC_COL(); + } } else { @@ -1255,6 +1249,11 @@ parse_po_line(const char* line, struct DrawState* dstate, *pstate |= PS_COMMENT_REFN; pline++; INC_COL(); + while (*pline == ' ' || *pline == '\t') + { + pline++; + INC_COL(); + } } else { @@ -1269,6 +1268,11 @@ parse_po_line(const char* line, struct DrawState* dstate, *pstate |= PS_COMMENT_OBSO; pline++; INC_COL(); + while (*pline == ' ' || *pline == '\t') + { + pline++; + INC_COL(); + } } else { @@ -1279,7 +1283,7 @@ parse_po_line(const char* line, struct DrawState* dstate, case '\\': if (*pstate & PS_COMMENT) { - pline++; + *ptoken++ = *pline++; INC_COL(); } else if ((*pstate & PS_STRING) && *(pstate + 1)) @@ -1292,7 +1296,7 @@ parse_po_line(const char* line, struct DrawState* dstate, case '"': if (*pstate & PS_COMMENT) { - pline++; + *ptoken++ = *pline++; INC_COL(); } else if (*pstate & PS_STRING) @@ -1404,7 +1408,7 @@ parse_po_line(const char* line, struct DrawState* dstate, if (!u32_token) goto parse_po_line_alloc_error; u8_string_to_unicode(u32_token, token, len); - u32_add_trans_comment(*current_entry, u32_token); + u32_add_extr_comment(*current_entry, u32_token); free(u32_token); } else if (*pstate & PS_COMMENT_FLAG) @@ -1466,7 +1470,7 @@ parse_po_line(const char* line, struct DrawState* dstate, else if (*pstate & PS_COMMENT_TRAN) u32_add_comment(*current_entry, (uint32_t*)L""); else if (*pstate & PS_COMMENT_EXTR) - u32_add_trans_comment(*current_entry, (uint32_t*)L""); + u32_add_extr_comment(*current_entry, (uint32_t*)L""); /* one-line states */ *pstate &= ~PS_COMMENT; diff --git a/po.h b/po.h @@ -48,8 +48,8 @@ typedef enum { PS_NONE = 0, PS_COMMENT_TRAN = 1, /* "translator-comments" : # */ PS_COMMENT_EXTR = 1 << 1, /* "extracted-comments" : #. */ - PS_COMMENT_FLAG = 1 << 2, /* "flag" : #, */ - PS_COMMENT_REFN = 1 << 3, /* "reference" : #: */ + PS_COMMENT_REFN = 1 << 2, /* "reference" : #: */ + PS_COMMENT_FLAG = 1 << 3, /* "flag" : #, */ PS_COMMENT_OBSO = 1 << 4, /* obsolete (undocumented) : #~ */ PS_MSGID = 1 << 5, PS_MSGID_PLURAL = 1 << 6, @@ -95,8 +95,8 @@ struct PoEntry { size_t* msgstr_len; uint32_t** comments; size_t comment_lines; - uint32_t** trans_comments; - size_t trans_comment_lines; + uint32_t** extr_comments; + size_t extr_comment_lines; char** ref_comments; size_t ref_comment_lines; }; @@ -122,11 +122,25 @@ 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 DrawState* state); 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* u32_add_extr_comment(struct PoEntry* entry, + const uint32_t* extr_comment); struct PoEntry* add_ref_comment(struct PoEntry* entry, const char* comment); int load_file(struct DrawState* state, long* lineno, long* col); +int save_comment(FILE* output, struct DrawState* state, + const struct PoEntry* current); int save_file(struct DrawState* state); +int save_flags(FILE* output, struct DrawState* state, + const struct PoEntry* current); +int save_msgid(FILE* output, struct DrawState* state, + const struct PoEntry* current); +int save_msgid_plural(FILE* output, struct DrawState* state, + const struct PoEntry* current); +int save_msgstrs(FILE* output, struct DrawState* state, + const struct PoEntry* current); +int save_ref_comment(FILE* output, struct DrawState* state, + const struct PoEntry* current); +int save_extr_comment(FILE* output, struct DrawState* state, + const struct PoEntry* current); int parse_po_line(const char* line, struct DrawState* dstate, struct PoEntry** current_entry, ParseState* pstate, long* col, int* msgstr_index); diff --git a/poe.c b/poe.c @@ -57,7 +57,7 @@ cancel_callback(struct DrawState* state, struct tb_event* ev) #define MAXCOPYBUF 8192 -static int +int cp(const char* from, const char* to) { struct stat st; @@ -533,8 +533,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->extr_comments) + num_lines += current->extr_comment_lines + 1; if (current->ref_comments) num_lines += current->ref_comment_lines + 1; newbuf = calloc(num_lines, sizeof(struct BufferLine)); @@ -647,7 +647,7 @@ load_info(struct DrawState* state) pnewbuf++; } } - if (current->trans_comments) + if (current->extr_comments) { newlen = u32_u8_strncpy(pnewbuf->text, "Translation comments:", MAXBUFLINE); @@ -657,11 +657,11 @@ load_info(struct DrawState* state) pnewbuf->fg = colors[C_EDIT_MSGID_HEADING].fg; pnewbuf->bg = colors[C_EDIT_MSGID_HEADING].bg; pnewbuf++; - for (size_t i = 0; i < current->trans_comment_lines; i++) + for (size_t i = 0; i < current->extr_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, + uint32_t* extr_comment = current->extr_comments[i]; + size_t len = u32_strlen(extr_comment); + newlen = u32_strncpy(pnewbuf->text, extr_comment, MIN(len + 1, MAXBUFLINE)); pnewbuf->length = newlen; if (newlen > state->info_rows_maxlen) diff --git a/poe.h b/poe.h @@ -7,7 +7,7 @@ static int cancel_close(struct DrawState* state); static int cancel_msgstr(struct DrawState* state); static int cancel_search(struct DrawState* state); static int copy_msgid_to_input(struct DrawState* state); -static int cp(const char* from, const char* to); +int cp(const char* from, const char* to); //static int create_file(struct DrawState* state); static char* dirname(char* dir, char* path, const ssize_t dir_size); static int edit_page_down(struct DrawState* state);