Project

General

Profile

Feature #1903 ยป 1903_S3_3&Main.patch

Dean Brown, 08/29/2026 06:26 AM

View differences:

utility/registry_ini.c
#include <fc_config.h>
#endif
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
......
#define MAX_LEN_SECPATH 1024
#define MAX_LINE_LEN 75
/* Set to FALSE for old-style savefiles. */
#define SAVE_TABLES TRUE
......
return (num ? fc_isalnum(c) : fc_isalpha(c)) || c == '_';
}
/**********************************************************************//**
Utility routine used in word_wrap_helptext()
returns whether it's OK to insert a line break before the passed in char,
most non-alphanumeric are OK, test high bit to rule out UTF-8.
**************************************************************************/
static bool is_delim(char ch)
{
if (isalnum(ch) || ch & 0x80) {
return FALSE;
} else {
return (ch != '%' && ch != '.' && ch != ',' && ch != '?'
&& ch != '!' && ch != ';' && ch != ':' && ch != ')');
}
}
/**********************************************************************//**
Utility routine used in word_wrap_helptext()
starting at a location in a string, find the offsets of the next 2
delims, and return those offset values. Return value -1 means not found.
**************************************************************************/
static void find_next_delims(char *start_ptr,
int *delim1_offset, int *delim2_offset)
{
char *p = start_ptr;
*delim1_offset = -1;
*delim2_offset = -1;
while (*p && !is_delim(*p)) {
p++;
}
if (*p) {
*delim1_offset = p - start_ptr;
} else {
return;
}
p++;
while (*p && !is_delim(*p)) {
p++;
}
if (*p) {
*delim2_offset = p - start_ptr;
}
}
/**********************************************************************//**
Utility routine used in secfile_save() when writing out helptext strings.
When a helptext string has "\n\" followed by a newline, that gets lost
when it's read in. This re-inserts the "\n\" so the output will look
the same.
Also tries to keep output lines to be shorter than MAX_LINE_LEN chars, by
inserting new lines as needed.
Assumes the struct entry is type ENTRY_STR.
**************************************************************************/
static void word_wrap_helptext(struct entry *pentry, int indent)
{
static char new_buf[8192];
char *new_buf_ptr = new_buf;
char *buf_ptr = pentry->string.value;
char *end_new_buf_ptr;
int width = MAX_LINE_LEN - indent;
size_t str_length;
bool is_finished = FALSE;
char *break_ptr, *p;
int num_undone;
int delim1_offset, delim2_offset;
int looked_at;
char *old_val;
fc_assert(pentry->type == ENTRY_STR);
/* look for newline chars */
while (*buf_ptr) {
if (*buf_ptr == '\n') {
/* found a newline char, insert "\n\" */
*new_buf_ptr++ = '\\';
*new_buf_ptr++ = 'n';
*new_buf_ptr++ = '\\';
*new_buf_ptr++ = *buf_ptr++;
}
*new_buf_ptr++ = *buf_ptr++;
}
*new_buf_ptr = 0;
buf_ptr = new_buf;
/* do word wrapping */
str_length = strlen(new_buf);
end_new_buf_ptr = new_buf + str_length;
p = new_buf;
num_undone = str_length;
looked_at = 0;
while (! is_finished) {
if (num_undone > width) {
find_next_delims(p, &delim1_offset, &delim2_offset);
if (delim1_offset == -1) {
is_finished = TRUE;
} else {
if (looked_at + delim1_offset < width
&& (looked_at + delim2_offset >= width || delim2_offset == -1)) {
break_ptr = p + delim1_offset;
/* found where we want to word wrap */
/* insert '\' and newline char into new_buf at break_ptr */
/* first, move to make room */
p = end_new_buf_ptr;
while (p >= break_ptr) {
*(p + 2) = *p;
p--;
}
*break_ptr++ = '\\';
*break_ptr++ = '\n';
end_new_buf_ptr += 2;
/* update for next time thru loop */
num_undone = end_new_buf_ptr - break_ptr;
looked_at = 0;
p = break_ptr + 1;
width = MAX_LINE_LEN;
} else {
/* still looking, update for next time thru loop */
p += delim1_offset + 1;
looked_at += delim1_offset + 1;
}
/* if now pointing at a new line, update for next time thru loop */
if (*p == '\n') {
looked_at = 0;
width = MAX_LINE_LEN;
}
}
} else {
is_finished = TRUE;
}
}
/* We free() old value only after we've placed the new one, to
* support secfile_replace_str_vec() calls that want to keep some of
* the entries from the old vector in the new one. We don't want
* to lose the entry in between. */
old_val = pentry->string.value;
pentry->string.value = fc_strdup(buf_ptr);
free(old_val);
}
/**********************************************************************//**
Utility routine used in secfile_save() when writing out strings.
Returns the length the string will be when written out.
Assumes the struct entry is type ENTRY_STR.
**************************************************************************/
static size_t entry_str_length(struct entry *pentry)
{
size_t len;
fc_assert(pentry->type == ENTRY_STR);
/* + 2 for the enclosing " chars */
len = strlen(pentry->string.value) + 2;
if (pentry->string.gt_marking) {
len +=3; /* + 3 for the initial "_(" and terminating ")" */
}
return len;
}
/**********************************************************************//**
Save the previously filled in section_file to disk.
......
const struct entry_list_link *ent_iter, *save_iter, *col_iter;
struct entry *pentry, *col_pentry;
int i;
/* these vars are only used for ENTRY_STR's */
bool need_new_line = FALSE;
int col, indent, entry_len;
SECFILE_RETURN_VAL_IF_FAIL(secfile, nullptr, secfile != nullptr, FALSE);
......
}
}
if (icol == 0 && pentry->type == ENTRY_STR) {
col = entry_str_length(pentry) + 1;
}
if (icol > 0) {
fz_fprintf(fs, ",");
if (pentry->type == ENTRY_STR) {
word_wrap_helptext(pentry, col);
}
}
entry_to_file(pentry, fs);
......
} else {
/* Classic entry. */
col_entry_name = entry_name(pentry);
fz_fprintf(fs, "%s=", col_entry_name);
indent = fz_fprintf(fs, "%s=", col_entry_name);
col = indent;
/* for ENTRY_STR's, wrap long lines */
if (pentry->type == ENTRY_STR) {
word_wrap_helptext(pentry, indent);
/* + 1 for the comma */
entry_len = entry_str_length(pentry) + 1;
col += entry_len;
}
entry_to_file(pentry, fs);
/* Check for vector. */
......
break;
}
fz_fprintf(fs, ",");
col++;
/* for ENTRY_STR's, wrap long lines */
if (pentry->type == ENTRY_STR) {
word_wrap_helptext(col_pentry, indent);
/* + 1 for the comma */
entry_len = entry_str_length(col_pentry) + 1;
if (col + entry_len > MAX_LINE_LEN) {
need_new_line = TRUE;
}
if (need_new_line) {
fz_fprintf(fs, "\n%*s", indent, " ");
need_new_line = FALSE;
col = indent + entry_len;
} else {
col += entry_len;
}
}
entry_to_file(col_pentry, fs);
ent_iter = col_iter;
}
......
return TRUE;
}
/************************************************************************//**
Copies a string and convert the following characters:
- '\"' to "\\\"".
****************************************************************************/
static void make_escapes_quotes(const char *str, char *buf, size_t buf_len)
{
char *dest = buf;
/* Sometimes we insert a character, so keep
* place for '\0' and an extra character. */
const char *max = buf + buf_len - 1;
while (*str != '\0' && dest < max) {
if (*str == '\"') {
*dest++ = '\\';
max--;
}
*dest++ = *str++;
}
*dest = 0;
}
/**********************************************************************//**
Push an entry into a file stream.
**************************************************************************/
......
break;
case ENTRY_STR:
if (pentry->string.escaped) {
make_escapes(pentry->string.value, buf, sizeof(buf));
make_escapes_quotes(pentry->string.value, buf, sizeof(buf));
if (pentry->string.gt_marking) {
fz_fprintf(fs, "_(\"%s\")", buf);
} else {
utility/support.c
return ret;
}
/************************************************************************//**
Copies a string and convert the following characters:
- '\n' to "\\n".
- '\\' to "\\\\".
- '\"' to "\\\"".
See also remove_escapes().
****************************************************************************/
void make_escapes(const char *str, char *buf, size_t buf_len)
{
char *dest = buf;
/* Sometimes we insert 2 characters at once ('\n' -> "\\n"), so keep
* place for '\0' and an extra character. */
const char *const max = buf + buf_len - 2;
while (*str != '\0' && dest < max) {
switch (*str) {
case '\n':
*dest++ = '\\';
*dest++ = 'n';
str++;
break;
case '\\':
case '\"':
*dest++ = '\\';
fc__fallthrough;
default:
*dest++ = *str++;
break;
}
}
*dest = 0;
}
/************************************************************************//**
Copies a string. Backslash followed by a genuine newline always
removes the newline.
......
- '\n' -> newline translation.
- Other '\?' sequences (any character '?') are just passed
through with the '\' removed (eg, includes '\\', '\"').
See also make_escapes().
****************************************************************************/
void remove_escapes(const char *str, bool full_escapes,
char *buf, size_t buf_len)
utility/support.h
#endif /* WORDS_BIGENDIAN */
}
void make_escapes(const char *str, char *buf, size_t buf_len);
void remove_escapes(const char *str, bool full_escapes,
char *buf, size_t buf_len);
    (1-1/1)