Skip to content

Commit

Permalink
wip string trimming
Browse files Browse the repository at this point in the history
  • Loading branch information
kjk committed Dec 28, 2023
1 parent 2dd55b0 commit 9398232
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 26 deletions.
76 changes: 63 additions & 13 deletions src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1004,24 +1004,73 @@ static bool __cmdIdInList(UINT_PTR cmdId, UINT_PTR* idsList, int n) {
#define cmdIdInList(name) __cmdIdInList(md.idOrSubmenu, name, dimof(name))

// TODO: write it in a way that handles unicode
static TempStr ShortenString(char* menuString, size_t maxLen) {
size_t menuStrLen = str::Len(menuString);
static TempStr ShortenStringTemp(char* s, int maxLen) {
int nRunes = utf8StrLen((u8*)s);
if (nRunes <= maxLen) {
return s;
}
size_t menuStrLen = str::Len(s);
if (menuStrLen <= maxLen) {
return menuString;
return s;
}
char* newStr = AllocArrayTemp<char>(maxLen);
char* ret = AllocArrayTemp<char>(maxLen);
const size_t half = maxLen / 2;
const size_t strSize = menuStrLen + 1; // size()+1 because wcslen() doesn't include \0
const size_t strSize = menuStrLen + 1; // size()+1 because w hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhcslen() doesn't include \0
// Copy first N/2 characters, move last N/2 characters to the halfway point
for (size_t i = 0; i < half; i++) {
newStr[i] = menuString[i];
newStr[i + half] = menuString[strSize - half + i];
ret[i] = s[i];
ret[i + half] = s[strSize - half + i];
}
// Add ellipsis
newStr[half - 2] = newStr[half - 1] = newStr[half] = '.';
ret[half - 2] = ret[half - 1] = ret[half] = '.';
// Ensure null-terminated string
newStr[maxLen - 1] = '\0';
return newStr;
ret[maxLen - 1] = '\0';
return ret;
}

static TempStr ShortenStringUtf8Temp(char* s, int maxRunes) {
int nRunes = utf8StrLen((u8*)s);
if (nRunes < 0) {
return ShortenStringTemp(s, maxRunes);
}
if (nRunes <= maxRunes) {
return s;
}
int toRemove = nRunes - maxRunes - 3; // 3 for "..."
int removeStartingAt = (nRunes / 2) - (toRemove / 2);
char* ret = AllocArrayTemp<char>(maxRunes * 4 + 1); // * 4 over-allocates but should be always safe
char* tmp = ret;
int n;
for (int i = 0; i < nRunes; i++) {
n = utf8CharLen((u8*)s);
CrashIf(n <= 0);
if (i < removeStartingAt || i >= removeStartingAt + toRemove) {
switch (n) {
default:
CrashIf(true);
break;
case 4:
*tmp++ = *s++;
__fallthrough;
case 3:
*tmp++ = *s++;
__fallthrough;
case 2:
*tmp++ = *s++;
__fallthrough;
case 1:
*tmp++ = *s++;
}
} else if (i == removeStartingAt) {
*tmp++ = '.';
*tmp++ = '.';
*tmp++ = '.';
s += n;
} else {
s += n;
}
}
return ret;
}

static void AddFileMenuItem(HMENU menuFile, const char* filePath, int index) {
Expand All @@ -1033,8 +1082,9 @@ static void AddFileMenuItem(HMENU menuFile, const char* filePath, int index) {
TempStr menuString = path::GetBaseNameTemp(filePath);
// If the name is too long, save only the ends glued together
// E.g. 'Very Long PDF Name (3).pdf' -> 'Very Long...e (3).pdf'
const size_t MAX_LEN = 70;
menuString = ShortenString(menuString, MAX_LEN);
const size_t MAX_LEN = 5;
// 70;
menuString = ShortenStringUtf8Temp(menuString, MAX_LEN);

TempStr fileName = MenuToSafeStringTemp(menuString);
int menuIdx = (int)((index + 1) % 10);
Expand Down Expand Up @@ -1062,7 +1112,7 @@ static void AppendRecentFilesToMenu(HMENU m) {
}
AddFileMenuItem(m, fp, i);
}
#if 0
#if 1
AddFileMenuItem(
m,
"\xf0\x9f\xa4\xa3\xf0\x9f\x98\x8a\xf0\x9f\x98\x82\xe2\x9d\xa4\xf0\x9f\x98\x8d\xf0\x9f\x98\x92\xf0\x9f\x91\x8c"
Expand Down
54 changes: 41 additions & 13 deletions src/utils/StrUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,39 @@ static const u8 trailingBytesForUTF8[256] = {
* definition of UTF-8 goes up to 4-byte sequences.
*/

static bool isLegalUTF8(const u8* source, int length) {
static bool isLegalUTF8(const u8* src, int length) {
u8 a;
const u8* srcptr = source + length;
for (int i = 0; i < length; i++) {
a = src[i];
if (a == 0) {
return false;
}
}
const u8* end = src + length;

switch (length) {
default:
return false;
/* Everything else falls through when "true"... */
case 4:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF) {
a = (*--end);
if (a < 0x80 || a > 0xBF) {
return false;
}
__fallthrough;
case 3:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF) {
a = (*--end);
if (a < 0x80 || a > 0xBF) {
return false;
}
__fallthrough;
case 2:
if ((a = (*--srcptr)) > 0xBF) {
a = (*--end);
if (a > 0xBF) {
return false;
}

switch (*source) {
switch (*src) {
/* no fall-through in this inner switch */
case 0xE0:
if (a < 0xA0) {
Expand All @@ -111,21 +122,20 @@ static bool isLegalUTF8(const u8* source, int length) {
return false;
}
}

__fallthrough;
case 1:
if (*source >= 0x80 && *source < 0xC2) {
if (*src >= 0x80 && *src < 0xC2) {
return false;
}
}

return *source <= 0xF4;
return *src <= 0xF4;
}

/* --------------------------------------------------------------------- */

/*
* Exported function to return whether a UTF-8 sequence is legal or not.
* This is not used here; it's just exported.
* return true if a UTF-8 sequence is legal
*/
bool isLegalUTF8Sequence(const u8* source, const u8* sourceEnd) {
int n = trailingBytesForUTF8[*source] + 1;
Expand All @@ -136,8 +146,7 @@ bool isLegalUTF8Sequence(const u8* source, const u8* sourceEnd) {
}

/*
* Exported function to return whether a UTF-8 string is legal or not.
* This is not used here; it's just exported.
* return true if UTF-8 string is legal.
*/
bool isLegalUTF8String(const u8** source, const u8* sourceEnd) {
while (*source != sourceEnd) {
Expand All @@ -150,6 +159,25 @@ bool isLegalUTF8String(const u8** source, const u8* sourceEnd) {
return true;
}

// return -1 if not a valid utf8 string
int utf8StrLen(const u8* s) {
int len = 0;
while (*s) {
int n = trailingBytesForUTF8[*s] + 1;
if (!isLegalUTF8(s, n)) {
return -1;
}
s += n;
len++;
}
return len;
}

int utf8CharLen(const u8* s) {
int n = trailingBytesForUTF8[*s] + 1;
return n;
}

// --- end of Unicode, Inc. utf8 code

bool IsEqual(const ByteSlice& d1, const ByteSlice& d2) {
Expand Down
2 changes: 2 additions & 0 deletions src/utils/StrUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

bool isLegalUTF8Sequence(const u8* source, const u8* sourceEnd);
bool isLegalUTF8String(const u8** source, const u8* sourceEnd);
int utf8StrLen(const u8* s);
int utf8CharLen(const u8* s);

struct ByteSlice {
u8* d = nullptr;
Expand Down

0 comments on commit 9398232

Please sign in to comment.