diff --git a/WinPort/src/APIStringMap.cpp b/WinPort/src/APIStringMap.cpp index 7b0cd1c96..a0d6f35d1 100644 --- a/WinPort/src/APIStringMap.cpp +++ b/WinPort/src/APIStringMap.cpp @@ -98,8 +98,14 @@ WINPORT_DECL(LCMapStringEx, INT, (LPCWSTR name, DWORD flags, LPCWSTR src, INT sr * and skips white space and punctuation characters for * NORM_IGNORESYMBOLS. */ - if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) - continue; + if (flags & NORM_IGNORESYMBOLS) { + if (uint64_t(wch) <= 0xffff) { + if (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)) + continue; + } else if (iswspace(wch) || iswpunct(wch)) { + continue; + } + } len++; } return len; @@ -110,9 +116,15 @@ WINPORT_DECL(LCMapStringEx, INT, (LPCWSTR name, DWORD flags, LPCWSTR src, INT sr for (dst_ptr = dst; srclen && dstlen; src++, srclen--) { WCHAR wch = *src; - if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) - continue; - *dst_ptr++ = towupper(wch); + if (uint64_t(wch) <= 0xffff) { + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + *dst_ptr++ = toupperW(wch); + } else { + if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) + continue; + *dst_ptr++ = towupper(wch); + } dstlen--; } } @@ -121,9 +133,17 @@ WINPORT_DECL(LCMapStringEx, INT, (LPCWSTR name, DWORD flags, LPCWSTR src, INT sr for (dst_ptr = dst; srclen && dstlen; src++, srclen--) { WCHAR wch = *src; - if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) - continue; - *dst_ptr++ = towlower(wch); + if (uint64_t(wch) <= 0xffff) { + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + *dst_ptr++ = tolowerW(wch); + + } else { + if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) + continue; + *dst_ptr++ = towlower(wch); + } + dstlen--; } } @@ -137,8 +157,12 @@ WINPORT_DECL(LCMapStringEx, INT, (LPCWSTR name, DWORD flags, LPCWSTR src, INT sr for (dst_ptr = dst; srclen && dstlen; src++, srclen--) { WCHAR wch = *src; - if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) + if (uint64_t(wch) <= 0xffff) { + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + } else if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch))) { continue; + } *dst_ptr++ = wch; dstlen--; } @@ -182,7 +206,6 @@ INT WINAPI WINPORT(CompareStringEx)(LPCWSTR locale, DWORD flags, LPCWSTR str1, I if (len2 < 0) len2 = wcslen(str2); ret = wine_compare_string(flags, str1, len1, str2, len2); - if (ret) /* need to translate result */ return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN; return CSTR_EQUAL; @@ -200,6 +223,89 @@ WINPORT_DECL(CompareStringA, int, ( LCID Locale, DWORD dwCmpFlags, return WINPORT(CompareString)( Locale, dwCmpFlags, &wstr1[0], l1, &wstr2[0], l2); } +static BOOL WINPORT(GetStringType)( DWORD type, LPCWSTR src, INT count, LPWORD chartype ) +{ + static const unsigned char type2_map[16] = + { + C2_NOTAPPLICABLE, /* unassigned */ + C2_LEFTTORIGHT, /* L */ + C2_RIGHTTOLEFT, /* R */ + C2_EUROPENUMBER, /* EN */ + C2_EUROPESEPARATOR, /* ES */ + C2_EUROPETERMINATOR, /* ET */ + C2_ARABICNUMBER, /* AN */ + C2_COMMONSEPARATOR, /* CS */ + C2_BLOCKSEPARATOR, /* B */ + C2_SEGMENTSEPARATOR, /* S */ + C2_WHITESPACE, /* WS */ + C2_OTHERNEUTRAL, /* ON */ + C2_RIGHTTOLEFT, /* AL */ + C2_NOTAPPLICABLE, /* NSM */ + C2_NOTAPPLICABLE, /* BN */ + C2_OTHERNEUTRAL /* LRE, LRO, RLE, RLO, PDF */ + }; + + if (!src) + { + WINPORT(SetLastError)( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (count == -1) count = wcslen(src) + 1; + switch(type) + { + case CT_CTYPE1: + while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff; + break; + case CT_CTYPE2: + while (count--) *chartype++ = type2_map[get_char_typeW( *src++ ) >> 12]; + break; + case CT_CTYPE3: + { + while (count--) + { + int c = *src; + WORD type1, type3 = 0; /* C3_NOTAPPLICABLE */ + + type1 = get_char_typeW( *src++ ) & 0xfff; + /* try to construct type3 from type1 */ + if(type1 & C1_SPACE) type3 |= C3_SYMBOL; + if(type1 & C1_ALPHA) type3 |= C3_ALPHA; + if ((c>=0x30A0)&&(c<=0x30FF)) type3 |= C3_KATAKANA; + if ((c>=0x3040)&&(c<=0x309F)) type3 |= C3_HIRAGANA; + if ((c>=0x4E00)&&(c<=0x9FAF)) type3 |= C3_IDEOGRAPH; + if (c == 0x0640) type3 |= C3_KASHIDA; + if ((c>=0x3000)&&(c<=0x303F)) type3 |= C3_SYMBOL; + + if ((c>=0xD800)&&(c<=0xDBFF)) type3 |= C3_HIGHSURROGATE; + if ((c>=0xDC00)&&(c<=0xDFFF)) type3 |= C3_LOWSURROGATE; + + if ((c>=0xFF00)&&(c<=0xFF60)) type3 |= C3_FULLWIDTH; + if ((c>=0xFF00)&&(c<=0xFF20)) type3 |= C3_SYMBOL; + if ((c>=0xFF3B)&&(c<=0xFF40)) type3 |= C3_SYMBOL; + if ((c>=0xFF5B)&&(c<=0xFF60)) type3 |= C3_SYMBOL; + if ((c>=0xFF21)&&(c<=0xFF3A)) type3 |= C3_ALPHA; + if ((c>=0xFF41)&&(c<=0xFF5A)) type3 |= C3_ALPHA; + if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_FULLWIDTH; + if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_SYMBOL; + + if ((c>=0xFF61)&&(c<=0xFFDC)) type3 |= C3_HALFWIDTH; + if ((c>=0xFF61)&&(c<=0xFF64)) type3 |= C3_SYMBOL; + if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_KATAKANA; + if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_ALPHA; + if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_HALFWIDTH; + if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_SYMBOL; + *chartype++ = type3; + } + break; + } + default: + WINPORT(SetLastError)( ERROR_INVALID_PARAMETER ); + return FALSE; + } + return TRUE; +} + ////////////////////////// extern "C" { WINPORT_DECL(LCMapString, INT, (LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)) @@ -222,21 +328,37 @@ extern "C" { WINPORT_DECL(IsCharLower, BOOL, (WCHAR ch)) { + if (uint64_t(ch) <= 0xffff) { + WORD type; + return WINPORT(GetStringType)( CT_CTYPE1, &ch, 1, &type ) && (type & C1_LOWER); + } return iswlower(ch); } WINPORT_DECL(IsCharUpper, BOOL, (WCHAR ch)) { + if (uint64_t(ch) <= 0xffff) { + WORD type; + return WINPORT(GetStringType)( CT_CTYPE1, &ch, 1, &type ) && (type & C1_UPPER); + } return iswupper(ch); } WINPORT_DECL(IsCharAlphaNumeric, BOOL, (WCHAR ch)) { + if (uint64_t(ch) <= 0xffff) { + WORD type; + return WINPORT(GetStringType)( CT_CTYPE1, &ch, 1, &type ) && (type & (C1_ALPHA|C1_DIGIT)); + } return iswalnum(ch); } WINPORT_DECL(IsCharAlpha, BOOL, (WCHAR ch)) { + if (uint64_t(ch) <= 0xffff) { + WORD type; + return WINPORT(GetStringType)( CT_CTYPE1, &ch, 1, &type ) && (type & C1_ALPHA); + } return iswalpha(ch); } diff --git a/WinPort/src/Backend/SudoAskpassImpl.cpp b/WinPort/src/Backend/SudoAskpassImpl.cpp index 99b745cdb..ed389b78b 100644 --- a/WinPort/src/Backend/SudoAskpassImpl.cpp +++ b/WinPort/src/Backend/SudoAskpassImpl.cpp @@ -41,7 +41,7 @@ class SudoAskpassScreen RES_CANCEL } _result = RES_PENDING; bool _password_expected = false; - bool _need_repaint = false; + bool _need_repaint = true; // 0 - password is empty, 1 - non-empty but yet not hashed, otherwise - hash value uint64_t _panno_hash = 0; @@ -137,18 +137,31 @@ class SudoAskpassScreen ci.Attributes = (x == _rect.Left || x == _rect.Right || y == _rect.Top || y == _rect.Bottom) ? AttrFrame : AttrInner; COORD pos{x, y}; - g_winport_con_out->Write(ci, pos); + // force repant if frame is damaged (likely by app's interface painted from other thread) + if (!_need_repaint && (y == _rect.Top || x == _rect.Left || x == _rect.Right)) { + CHAR_INFO ci_orig{}; + g_winport_con_out->Read(ci_orig, pos); + if (ci_orig.Char.UnicodeChar != ci.Char.UnicodeChar || ci_orig.Attributes != ci.Attributes) { + _need_repaint = true; + } + } + if (_need_repaint) { + g_winport_con_out->Write(ci, pos); + } } } - g_winport_con_out->SetAttributes(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - WriteCentered(_title, _rect.Top + 1); - WriteCentered(_key_hint, _rect.Top + 3); + if (_need_repaint) { + g_winport_con_out->SetAttributes(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + WriteCentered(_title, _rect.Top + 1); + WriteCentered(_key_hint, _rect.Top + 3); - g_winport_con_out->SetAttributes(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); - WriteCentered(_text, _rect.Top + 2); - if (_password_expected) { - PaintPasswordPanno(); + g_winport_con_out->SetAttributes(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + WriteCentered(_text, _rect.Top + 2); + if (_password_expected) { + PaintPasswordPanno(); + } + _need_repaint = false; } } @@ -246,19 +259,17 @@ class SudoAskpassScreen if (g_winport_con_in->WaitForNonEmptyWithTimeout(700, _cip)) { DispatchInput(); - } else if (_password_expected) { - const uint64_t hash = TypedPasswordHash(); - if (_panno_hash != hash) { - _panno_hash = hash; - _need_repaint = true; + } else { + if (_password_expected) { + const uint64_t hash = TypedPasswordHash(); + if (_panno_hash != hash) { + _panno_hash = hash; + } } - } - if (_result != RES_PENDING) - return _result == RES_OK; + if (_result != RES_PENDING) + return _result == RES_OK; - if (_need_repaint) { - _need_repaint = false; Repaint(); } } diff --git a/WinPort/src/Backend/TTY/TTYBackend.cpp b/WinPort/src/Backend/TTY/TTYBackend.cpp index 7ddd30257..b00475219 100644 --- a/WinPort/src/Backend/TTY/TTYBackend.cpp +++ b/WinPort/src/Backend/TTY/TTYBackend.cpp @@ -222,7 +222,12 @@ void TTYBackend::ReaderThread() } else { if (!strchr(_nodetect, 'x') || strstr(_nodetect, "xi")) { - _ttyx = StartTTYX(_full_exe_path, !strstr(_nodetect, "xi")); + + // disable xi on Wayland as it not work there anyway and also causes delays + const char *xdg_st = getenv("XDG_SESSION_TYPE"); + bool on_wayland = (xdg_st && strcasecmp(xdg_st, "wayland") == 0); + + _ttyx = StartTTYX(_full_exe_path, !strstr(_nodetect, "xi") && !on_wayland); } if (_ttyx) { if (!_ext_clipboard) { @@ -295,6 +300,12 @@ void TTYBackend::ReaderLoop() int rs; + // Enable esc expiration on Wayland as Xi not work there + const char *xdg_st = getenv("XDG_SESSION_TYPE"); + if ((xdg_st && strcasecmp(xdg_st, "wayland") == 0) && !_esc_expiration) { + _esc_expiration = 100; + } + if (!idle_expired && _esc_expiration > 0 && !_far2l_tty) { struct timeval tv; tv.tv_sec = _esc_expiration / 1000; diff --git a/WinPort/wineguts/casemap.c b/WinPort/wineguts/casemap.c index ac6c250c3..059bc7eac 100644 --- a/WinPort/wineguts/casemap.c +++ b/WinPort/wineguts/casemap.c @@ -7,15 +7,16 @@ #include "unicode.h" -const WCHAR wine_casemap_lower[4013] = + +const USHORT wine_casemap_lower[4259] = { /* index */ 0x01bf, 0x02bf, 0x03bf, 0x044f, 0x054f, 0x064f, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x06af, 0x0100, 0x0100, 0x077d, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x087d, 0x097c, - 0x0100, 0x0a79, 0x0100, 0x0100, 0x0afd, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0bfd, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0873, 0x0100, 0x0973, 0x0a72, + 0x0100, 0x0b6f, 0x0100, 0x0100, 0x0bf3, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0cf3, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, @@ -30,7 +31,7 @@ const WCHAR wine_casemap_lower[4013] = 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0cf0, 0x0dce, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0de6, 0x0ec4, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, @@ -41,7 +42,7 @@ const WCHAR wine_casemap_lower[4013] = 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0ead, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0fa3, /* defaults */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -291,6 +292,38 @@ const WCHAR wine_casemap_lower[4013] = 0x97d0, 0x97d0, 0x97d0, 0x97d0, 0x97d0, 0x97d0, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1c0a .. 0x1cff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf440, 0xf440, + 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, + 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, + 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, + 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, + 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, 0xf440, + 0xf440, 0x0000, 0x0000, 0xf440, 0xf440, 0xf440, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1e00 .. 0x1eff */ 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, @@ -492,7 +525,7 @@ const WCHAR wine_casemap_lower[4013] = 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x5abc, 0x5ab1, 0x5ab5, 0x5abf, 0x5abc, 0x0000, 0x5aee, 0x5ad6, - 0x5aeb, 0x03a0, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x5aeb, 0x03a0, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -533,15 +566,15 @@ const WCHAR wine_casemap_lower[4013] = 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; -const WCHAR wine_casemap_upper[4570] = +const USHORT wine_casemap_upper[4828] = { /* index */ 0x019f, 0x029f, 0x039f, 0x045a, 0x0556, 0x0656, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x06dd, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x07db, 0x0864, 0x0963, 0x0a63, - 0x0100, 0x0b57, 0x0100, 0x0100, 0x0bdc, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0cc6, 0x0dc6, 0x0100, 0x0100, + 0x06dd, 0x0100, 0x0100, 0x07dd, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x08db, 0x0964, 0x0a63, 0x0b63, + 0x0100, 0x0c57, 0x0100, 0x0100, 0x0cdc, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0dc6, 0x0ec6, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, @@ -556,8 +589,8 @@ const WCHAR wine_casemap_upper[4570] = 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0e85, 0x0f62, - 0x0100, 0x0100, 0x0100, 0x101a, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0f85, 0x1062, + 0x0100, 0x0100, 0x0100, 0x111c, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, @@ -567,7 +600,7 @@ const WCHAR wine_casemap_upper[4570] = 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x10da, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x11dc, /* defaults */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -779,7 +812,7 @@ const WCHAR wine_casemap_upper[4570] = 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 0x1379 .. 0x13ff */ + /* 0x1079 .. 0x10ff */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -790,13 +823,46 @@ const WCHAR wine_casemap_upper[4570] = 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0bc0, + 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, + 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, + 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, + 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, + 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, + 0x0bc0, 0x0bc0, 0x0000, 0x0000, 0x0bc0, 0x0bc0, 0x0bc0, + /* 0x1300 .. 0x13ff */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, - 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, /* 0x1c02 .. 0x1cff */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -1073,7 +1139,7 @@ const WCHAR wine_casemap_upper[4570] = 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -1083,12 +1149,13 @@ const WCHAR wine_casemap_upper[4570] = 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 0xab48 .. 0xabff */ + /* 0xab46 .. 0xabff */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0xfc60, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfc60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, @@ -1098,8 +1165,7 @@ const WCHAR wine_casemap_upper[4570] = 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, - 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, 0x6830, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x6830, 0x6830, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -1107,6 +1173,7 @@ const WCHAR wine_casemap_upper[4570] = 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, /* 0xff40 .. 0xffff */ 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, diff --git a/WinPort/wineguts/compose.c b/WinPort/wineguts/compose.c index f49f28e32..7ad6e72ca 100644 --- a/WinPort/wineguts/compose.c +++ b/WinPort/wineguts/compose.c @@ -9,7 +9,7 @@ #include "unicode.h" -static const WCHAR table[0x85e] = +static const USHORT table[0x85e] = { /* second chars + offsets */ 0x0300, 0x0047, 0x0301, 0x009b, 0x0302, 0x0111, 0x0303, 0x0131, @@ -385,13 +385,13 @@ static const WCHAR table[0x85e] = 0x30d8, 0x30da, 0x30db, 0x30dd }; -static inline int binary_search( WCHAR ch, int low, int high ) +static inline int binary_search( USHORT chu, int low, int high ) { while (low <= high) { int pos = (low + high) / 2; - if (table[2 * pos] < ch) low = pos + 1; - else if (table[2 * pos] > ch) high = pos - 1; + if (table[2 * pos] < chu) low = pos + 1; + else if (table[2 * pos] > chu) high = pos - 1; else return pos; } return -1; @@ -402,7 +402,7 @@ WCHAR wine_compose( const WCHAR *str ) int pos, idx = 1, start = 0, count = 70; for (;;) { - if ((pos = binary_search( str[idx], start, count - 1 )) == -1) return 0; + if ((pos = binary_search( (USHORT)str[idx], start, count - 1 )) == -1) return 0; if (!idx--) return table[2 * pos + 1]; start = table[2 * pos + 1]; count = table[2 * pos + 3]; diff --git a/WinPort/wineguts/decompose.c b/WinPort/wineguts/decompose.c index e604120ba..0fcae1bf0 100644 --- a/WinPort/wineguts/decompose.c +++ b/WinPort/wineguts/decompose.c @@ -8,7 +8,7 @@ #include "unicode.h" -static const WCHAR table[5856] = +static const USHORT table[5856] = { /* index */ 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0100, 0x0160, 0x0100, @@ -933,7 +933,7 @@ static const WCHAR table[5856] = 0x05d1, 0x05bf, 0x05db, 0x05bf, 0x05e4, 0x05bf, 0x0000, 0x0000 }; -static const WCHAR compatmap_table[8154] = +static const USHORT compatmap_table[8154] = { /* index */ 0x0110, 0x0120, 0x0130, 0x0140, 0x0100, 0x0150, 0x0160, 0x0100, @@ -2200,7 +2200,7 @@ static const WCHAR compatmap_table[8154] = 0x25cb }; -static const WCHAR *get_compatmap_entry( WCHAR ch, unsigned int *len ) +static const USHORT *get_compatmap_entry( WCHAR ch, unsigned int *len ) { unsigned short offset_offs = compatmap_table[compatmap_table[((USHORT)ch) >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf); unsigned short start = compatmap_table[offset_offs]; @@ -2217,7 +2217,7 @@ static const WCHAR *get_compatmap_entry( WCHAR ch, unsigned int *len ) unsigned int DECLSPEC_HIDDEN wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen ) { - const WCHAR *ptr = NULL; + const USHORT *ptr = NULL; unsigned int res, len, dst_pos = 0; *dst = ch; diff --git a/WinPort/wineguts/sortkey.c b/WinPort/wineguts/sortkey.c index 205f7f52e..79ef86a75 100644 --- a/WinPort/wineguts/sortkey.c +++ b/WinPort/wineguts/sortkey.c @@ -169,28 +169,38 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst enum weight { - UNICODE_WEIGHT, - DIACRITIC_WEIGHT, - CASE_WEIGHT + UNICODE_WEIGHT = 0x01, + DIACRITIC_WEIGHT = 0x02, + CASE_WEIGHT = 0x04 }; -static unsigned int get_weight(WCHAR ch, enum weight type) +static void eval_weights(WCHAR ch1, WCHAR ch2, unsigned int types, unsigned int *r1, unsigned int *r2) { - unsigned int ret; - - ret = collation_table[collation_table[((USHORT)ch) >> 8] + (ch & 0xff)]; - if (ret == (unsigned int)-1) - return ch; - - switch(type) - { - case UNICODE_WEIGHT: - return ret >> 16; - case DIACRITIC_WEIGHT: - return (ret >> 8) & 0xff; - case CASE_WEIGHT: - default: - return (ret >> 4) & 0x0f; + unsigned int w1 = collation_table[collation_table[((USHORT)ch1) >> 8] + (ch1 & 0xff)]; + unsigned int w2 = collation_table[collation_table[((USHORT)ch2) >> 8] + (ch2 & 0xff)]; + if (w1 == (unsigned int)-1) + w1 = ch1; + if (w2 == (unsigned int)-1) + w2 = ch2; + *r1 = 0; + *r2 = 0; + if (types & UNICODE_WEIGHT) { + *r1 = w1 >> 16; + *r2 = w2 >> 16; + } + if ((*r1 == *r2) && (types & DIACRITIC_WEIGHT) != 0) { + *r1 = (w1 >> 8) & 0xff; + *r2 = (w2 >> 8) & 0xff; + } + if ((*r1 == *r2) && (types & CASE_WEIGHT) != 0) { + *r1 = (w1 >> 4) & 0x0f; + *r2 = (w2 >> 4) & 0x0f; + if (*r1 && *r2 && *r1 != *r2) { + // dirty workaround to make BIG letters be first in sort + int t = *r1; + *r1 = *r2; + *r2 = t; + } } } @@ -206,7 +216,7 @@ static void inc_str_pos(const WCHAR **str, int *len, int *dpos, int *dlen) } static inline int compare_weights(int flags, const WCHAR *str1, int len1, - const WCHAR *str2, int len2, enum weight type) + const WCHAR *str2, int len2, unsigned int types) { int dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0; WCHAR dstr1[4], dstr2[4]; @@ -248,7 +258,7 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1, /* hyphen and apostrophe are treated differently depending on * whether SORT_STRINGSORT specified or not */ - if (type == UNICODE_WEIGHT && !(flags & SORT_STRINGSORT)) + if ((types & UNICODE_WEIGHT) != 0 && !(flags & SORT_STRINGSORT)) { if (dstr1[dpos1] == '-' || dstr1[dpos1] == '\'') { @@ -265,23 +275,13 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1, } } - ce1 = get_weight(dstr1[dpos1], type); - if (!ce1) - { - inc_str_pos(&str1, &len1, &dpos1, &dlen1); - continue; - } - ce2 = get_weight(dstr2[dpos2], type); - if (!ce2) - { - inc_str_pos(&str2, &len2, &dpos2, &dlen2); - continue; - } - - if (ce1 - ce2) return ce1 - ce2; - - inc_str_pos(&str1, &len1, &dpos1, &dlen1); - inc_str_pos(&str2, &len2, &dpos2, &dlen2); + eval_weights(dstr1[dpos1], dstr2[dpos2], types, &ce1, &ce2); + if (ce1 && ce2 && ce1 != ce2) + return ce1 - ce2; + if (!ce1 || ce2) + inc_str_pos(&str1, &len1, &dpos1, &dlen1); + if (!ce2 || ce1) + inc_str_pos(&str2, &len2, &dpos2, &dlen2); } while (len1) { @@ -292,7 +292,7 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1, } if (!dlen1) dlen1 = wine_decompose(0, *str1, dstr1, 4); - ce1 = get_weight(dstr1[dpos1], type); + eval_weights(dstr1[dpos1], 0, types, &ce1, &ce2); if (ce1) break; inc_str_pos(&str1, &len1, &dpos1, &dlen1); } @@ -305,7 +305,7 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1, } if (!dlen2) dlen2 = wine_decompose(0, *str2, dstr2, 4); - ce2 = get_weight(dstr2[dpos2], type); + eval_weights(0, dstr2[dpos2], types, &ce1, &ce2); if (ce2) break; inc_str_pos(&str2, &len2, &dpos2, &dlen2); } @@ -315,15 +315,10 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1, int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2) { - int ret; - - ret = compare_weights(flags, str1, len1, str2, len2, UNICODE_WEIGHT); - if (!ret) - { - if (!(flags & NORM_IGNORENONSPACE)) - ret = compare_weights(flags, str1, len1, str2, len2, DIACRITIC_WEIGHT); - if (!ret && !(flags & NORM_IGNORECASE)) - ret = compare_weights(flags, str1, len1, str2, len2, CASE_WEIGHT); - } - return ret; + unsigned int types = UNICODE_WEIGHT; + if (!(flags & NORM_IGNORENONSPACE)) + types|= DIACRITIC_WEIGHT; + if (!(flags & NORM_IGNORECASE)) + types|= CASE_WEIGHT; + return compare_weights(flags, str1, len1, str2, len2, types); } diff --git a/WinPort/wineguts/unicode.h b/WinPort/wineguts/unicode.h index b408f2345..ff158790a 100644 --- a/WinPort/wineguts/unicode.h +++ b/WinPort/wineguts/unicode.h @@ -123,14 +123,18 @@ WINE_UNICODE_INLINE int wine_is_dbcs_leadbyte( const union cptable *table, unsig WINE_UNICODE_INLINE WCHAR tolowerW( WCHAR ch ) { - extern const WCHAR wine_casemap_lower[]; - return ch + wine_casemap_lower[wine_casemap_lower[((USHORT)ch) >> 8] + (ch & 0xff)]; + extern const USHORT wine_casemap_lower[]; + USHORT chu = (USHORT)ch; + chu+= wine_casemap_lower[wine_casemap_lower[chu >> 8] + (chu & 0xff)]; + return chu; } WINE_UNICODE_INLINE WCHAR toupperW( WCHAR ch ) { - extern const WCHAR wine_casemap_upper[]; - return ch + wine_casemap_upper[wine_casemap_upper[((USHORT)ch) >> 8] + (ch & 0xff)]; + extern const USHORT wine_casemap_upper[]; + USHORT chu = (USHORT)ch; + chu+= wine_casemap_upper[wine_casemap_upper[chu >> 8] + (chu & 0xff)]; + return chu; } /* the character type contains the C1_* flags in the low 12 bits */ diff --git a/far2l/bootstrap/scripts/FarEng.hlf.m4 b/far2l/bootstrap/scripts/FarEng.hlf.m4 index bbe89d9d5..cf49c20dd 100644 --- a/far2l/bootstrap/scripts/FarEng.hlf.m4 +++ b/far2l/bootstrap/scripts/FarEng.hlf.m4 @@ -135,10 +135,12 @@ $ # FAR2L features - Getting Started# - #TTY#: plain terminal mode, no X11 dependencies, UX with some restrictions (works fully when running in the relevant terminal emulators, using their advanced keyboard-protocols, see list below). You can see FAR2L version and currently used backend in window title or by ~pseudo-command~@SpecCmd@ #far:about#. Wayland has security restriction for data access via X11; for full functionality run FAR2L-GUI in #xWayland# mode (see below). - If you have FAR2L-GUI installed, then when you run FAR2L it will try to use GUI mode. - To force run in terminal mode TTY|Xi use in command line: #far2l --tty#; - to force run in plain mode TTY use in command line: #far2l --tty --nodetect --ee#; - run FAR2L-GUI from command line in background without blocking terminal: #far2l --notty &# + Far2l running and selecting backend: + - if you have FAR2L-GUI installed, then when you run FAR2L it will try to use GUI mode; + - to force run in terminal mode TTY|Xi use in command line: #far2l --tty#; + - to force run in terminal mode TTY|X use in command line: #far2l --tty --nodetect=xi#; + - to force run in plain mode TTY use in command line: #far2l --tty --nodetect --ee#; + - run FAR2L-GUI from command line in background without blocking terminal: #far2l --notty &# (see details in ~Command line switches~@CmdLine@ or #far2l --help#). @@ -152,8 +154,8 @@ $ # FAR2L features - Getting Started# For adequate work FAR2L GUI in Wayland it helps to start FAR2L in mode #xWayland# by setting the environment variable #GDK_BACKEND=x11#: - running from console: #GDK_BACKEND=x11 far2l#; - inside desktop entry #/usr/share/applications/far2l.desktop# replace #Exec=far2l# with #Exec=env GDK_BACKEND=x11 far2l# - For applications running in a terminal emulator, xWayland mode does not provide full access, and the advice is to run only the TTY backend: - - forced non-use of X11 features when running in the console: #far2l --tty --nodetect# + For applications running in a terminal emulator, xWayland mode does not provide full access, and the advice is to run the TTY or only TTY|X backend: + - forced non-use of X11 extended keys features when running in the console: #far2l --tty --nodetect=xi# #macOS workaround# if far2l in macOS regularly asks permission to folders @@ -200,29 +202,33 @@ and in #terminal settings# option #OSC 52 must be allowed# #Terminals and ssh-clients supporting extended FAR2L keyboard shortcuts for plain terminal version FAR2L TTY# - Internal terminal in FAR2L-GUI (Linux, macOS, *BSD), see ~UI backends~@UIBackends@ and in help of #NetRocks plugin# section #Command line and remote FAR2L# -(keys and clipboard by FAR2L TTY extensions support) +(~TTY|F backend~@UIBackends@: keys and clipboard by FAR2L TTY extensions support) - kovidgoyal's kitty (Linux, macOS, *BSD): ~https://github.com/kovidgoyal/kitty~@https://github.com/kovidgoyal/kitty@ & ~https://sw.kovidgoyal.net/kitty~@https://sw.kovidgoyal.net/kitty@ -(keys by kovidgoyal's kitty keyboard protocol; for clipboard need turn on OSC 52) +(~TTY|k backend~@UIBackends@: keys by kovidgoyal's kitty keyboard protocol; +for clipboard need turn on OSC 52) - Wez's Terminal Emulator (Linux, FreeBSD, Windows): ~https://github.com/wez/wezterm~@https://github.com/wez/wezterm@ & ~https://wezfurlong.org/wezterm~@https://wezfurlong.org/wezterm@ -(keys in Linux, FreeBSD by kovidgoyal's kitty keyboard protocol; keys in Windows by win32-input-mode which enable by default; for clipboard need turn on OSC 52) +(~TTY|k backend~@UIBackends@: keys in Linux, FreeBSD by kovidgoyal's kitty keyboard protocol; +~TTY|w backend~@UIBackends@: keys in Windows by win32-input-mode which enable by default; +for clipboard need turn on OSC 52) [in macOS & in Windows in wezterm the kitty keyboard protocol support not working] - iTerm2 (macOS): ~https://gitlab.com/gnachman/iterm2~@https://gitlab.com/gnachman/iterm2@ & ~https://iterm2.com~@https://iterm2.com@ -(keys by iTerm2 "raw keyboard" protocol; for clipboard need turn on OSC 52) +(~TTY|a backend~@UIBackends@: keys by iTerm2 "raw keyboard" protocol; +for clipboard need turn on OSC 52) - Windows Terminal -(keys by win32-input-mode; for clipboard need turn on OSC 52; has mouse bug: ~https://github.com/microsoft/terminal/issues/15083~@https://github.com/microsoft/terminal/issues/15083@) +(~TTY|w backend~@UIBackends@: keys by win32-input-mode; for clipboard need turn on OSC 52; has mouse bug: ~https://github.com/microsoft/terminal/issues/15083~@https://github.com/microsoft/terminal/issues/15083@) - putty4far2l (Windows ssh-client): ~https://github.com/ivanshatsky/putty4far2l/releases~@https://github.com/ivanshatsky/putty4far2l/releases@ & ~https://github.com/unxed/putty4far2l~@https://github.com/unxed/putty4far2l@ -(keys and clipboard by FAR2L TTY extensions support) +(~TTY|F backend~@UIBackends@: keys and clipboard by FAR2L TTY extensions support) - cyd01's KiTTY (Windows ssh-client): ~https://github.com/cyd01/KiTTY~@https://github.com/cyd01/KiTTY@ & ~https://www.9bis.net/kitty~@https://www.9bis.net/kitty@ -(keys and clipboard by FAR2L TTY extensions support) +(~TTY|F backend~@UIBackends@: keys and clipboard by FAR2L TTY extensions support) - putty-nd (Windows ssh-client): ~https://sourceforge.net/projects/putty-nd~@https://sourceforge.net/projects/putty-nd@ & ~https://github.com/noodle1983/putty-nd~@https://github.com/noodle1983/putty-nd@ -(keys and clipboard by FAR2L TTY extensions support) +(~TTY|F backend~@UIBackends@: keys and clipboard by FAR2L TTY extensions support) #Location of FAR2L settings and history# @@ -1602,6 +1608,13 @@ to listen all your keystrokes, grab clipboard content, get windows snapshots etc is the only secure way to run far2l remotely on untrusted server while supporting all usual far2l hotkeys and other UX conveniences. + - Terminal emulators specific Backends (uses these terminal extensions to get state of all keyboard keys; +in pure TTY| to access clipboard you must turn on OSC 52 in both the FAR2L settings and the terminal settings; +TTY|X uses X11 to access clipboard): + - #TTY|a# or #TTY|Xa backend:# renders into Apple iTerm2 terminal. + - #TTY|k# or #TTY|Xk backend:# renders into kovidgoyal's Kitty (and any terminals with kovidgoyal's kitty keyboard protocol). + - #TTY|w# or #TTY|Xw backend:# renders into Windows Terminal (and any terminals with win32 input mode). + List and links to supported terminals see in ~FAR2L features - Getting Started~@Far2lGettingStarted@. @ConfirmDlg $ #Confirmations# diff --git a/far2l/bootstrap/scripts/FarRus.hlf.m4 b/far2l/bootstrap/scripts/FarRus.hlf.m4 index dc1b51d51..2503492da 100644 --- a/far2l/bootstrap/scripts/FarRus.hlf.m4 +++ b/far2l/bootstrap/scripts/FarRus.hlf.m4 @@ -139,10 +139,12 @@ $ # Особенности FAR2L - начало работы# - #TTY# - чистый терминальный режим, никаких иксовых зависимостей, UX с некоторыми ограничениями (полноценно работает при запуске в соответствующих эмуляторах терминалов, используя их расширенные возможности передачи клавиш, см. список ниже). Версию FAR2L и используемый бекенд можно увидеть в заголовке окна или через ~псевдо-команду~@SpecCmd@ #far:about#. В Wayland получение данных через X11 ограничено; для полноценной работы запускайте FAR2L-GUI в режиме #xWayland# (см. ниже). - Если у Вас установлена версия GUI, то при запуске будет пытаться использоваться она. - Для принудительного запуска терминального варианта TTY|Xi используйте в командной строке: #far2l --tty#; - для принудительного запуска минимального варианта TTY используйте в командной строке: #far2l --tty --nodetect --ee#; - фоновый запуск FAR2L-GUI из командной строки без блокировки терминала: #far2l --notty &# + Запуск far2l и выбор бекенда: + - если у Вас установлена версия GUI, то при запуске будет пытаться использоваться она; + - для принудительного запуска терминального варианта TTY|Xi используйте в командной строке: #far2l --tty#; + - для принудительного запуска терминального варианта TTY|X используйте в командной строке: #far2l --tty --nodetect=xi#; + - для принудительного запуска минимального варианта TTY используйте в командной строке: #far2l --tty --nodetect --ee#; + - фоновый запуск FAR2L-GUI из командной строки без блокировки терминала: #far2l --notty &# (подробнее про ключи запуска в ~Параметры командной строки~@CmdLine@ или #far2l --help#). @@ -156,8 +158,8 @@ $ # Особенности FAR2L - начало работы# Для адекватной работы FAR GUI в Wayland помогает запустить в режиме #xWayland#, указав переменную среды #GDK_BACKEND=x11#: - запуск из консоли: #GDK_BACKEND=x11 far2l#; - внутри ярлыка #/usr/share/applications/far2l.desktop# заменить #Exec=far2l# на #Exec=env GDK_BACKEND=x11 far2l# - При запуске в эмуляторе терминала режим xWayland не даёт полноценного доступа и тут совет запускать только бекенд TTY: - - принудительное неиспользование возможностей X11 при запуске в консоли: #far2l --tty --nodetect# + При запуске в эмуляторе терминала режим xWayland не даёт полноценного доступа и тут совет запускать бекенд TTY или только TTY|X: + - принудительное неиспользование расширенных клавиатурных возможностей X11 при запуске в консоли: #far2l --tty --nodetect=xi# #Костыль для macOS#, если far2l в macOS рагулярно запрашивает доступ к папкам @@ -204,29 +206,33 @@ $ # Особенности FAR2L - начало работы# #Терминалы и ssh-клиенты, поддерживающие расширенные сочетания клавиш FAR2L для чистой терминальной версии FAR2L TTY# - Встроенный терминал FAR2L-GUI (Linux, macOS, *BSD), см. ~Режимы интерфейса~@UIBackends@ и в помощи #NetRocks plugin# раздел #Command line and remote FAR2L# -(клавиши и буфер обмена через FAR2L TTY extensions support) +(~TTY|F режим~@UIBackends@: клавиши и буфер обмена через FAR2L TTY extensions support) - kovidgoyal's kitty (Linux, macOS, *BSD): ~https://github.com/kovidgoyal/kitty~@https://github.com/kovidgoyal/kitty@ & ~https://sw.kovidgoyal.net/kitty~@https://sw.kovidgoyal.net/kitty@ -(клавиши через kovidgoyal's kitty keyboard protocol; для взаимодействия с клипбордом включить OSC 52) +(~TTY|k режим~@UIBackends@: клавиши через kovidgoyal's kitty keyboard protocol; +для взаимодействия с клипбордом включить OSC 52) - Wez's Terminal Emulator (Linux, FreeBSD, Windows): ~https://github.com/wez/wezterm~@https://github.com/wez/wezterm@ & ~https://wezfurlong.org/wezterm~@https://wezfurlong.org/wezterm@ -(клавиши в Linux, FreeBSD через kovidgoyal's kitty keyboard protocol; клавиши в Windows через win32-input-mode, который включен по умолчанию; для взаимодействия с клипбордом включить OSC 52) +(~TTY|k режим~@UIBackends@: клавиши в Linux, FreeBSD через kovidgoyal's kitty keyboard protocol; +~TTY|w режим~@UIBackends@: клавиши в Windows через win32-input-mode, который включен по умолчанию; +для взаимодействия с клипбордом включить OSC 52) [в macOS и в Windows в wezterm поддержка режима kitty не работает] - iTerm2 (macOS): ~https://gitlab.com/gnachman/iterm2~@https://gitlab.com/gnachman/iterm2@ & ~https://iterm2.com~@https://iterm2.com@ -(клавиши через iTerm2 "raw keyboard" protocol; для взаимодействия с клипбордом включить OSC 52) +(~TTY|a режим~@UIBackends@: клавиши через iTerm2 "raw keyboard" protocol; для взаимодействия с клипбордом включить OSC 52) - Windows Terminal [в win11 стоит из коробки, в win10 надо ставить] -(клавиши через win32-input-mode; для взаимодействия с клипбордом включить OSC 52; присутствует баг с мышью: ~https://github.com/microsoft/terminal/issues/15083~@https://github.com/microsoft/terminal/issues/15083@) +(~TTY|w режим~@UIBackends@: клавиши через win32-input-mode; для взаимодействия с клипбордом включить OSC 52; +присутствует баг с мышью: ~https://github.com/microsoft/terminal/issues/15083~@https://github.com/microsoft/terminal/issues/15083@) - putty4far2l (Windows ssh-клиент): ~https://github.com/ivanshatsky/putty4far2l/releases~@https://github.com/ivanshatsky/putty4far2l/releases@ & ~https://github.com/unxed/putty4far2l~@https://github.com/unxed/putty4far2l@ -(клавиши и буфер обмена через FAR2L TTY extensions support) +(~TTY|F режим~@UIBackends@: клавиши и буфер обмена через FAR2L TTY extensions support) - cyd01's KiTTY (Windows ssh-клиент): ~https://github.com/cyd01/KiTTY~@https://github.com/cyd01/KiTTY@ & ~https://www.9bis.net/kitty~@https://www.9bis.net/kitty@ -(клавиши и буфер обмена через FAR2L TTY extensions support) +(~TTY|F режим~@UIBackends@: клавиши и буфер обмена через FAR2L TTY extensions support) - putty-nd (Windows ssh-клиент): ~https://sourceforge.net/projects/putty-nd~@https://sourceforge.net/projects/putty-nd@ & ~https://github.com/noodle1983/putty-nd~@https://github.com/noodle1983/putty-nd@ -(клавиши и буфер обмена через FAR2L TTY extensions support) +(~TTY|F режим~@UIBackends@: клавиши и буфер обмена через FAR2L TTY extensions support) #Расположение персональных настроек FAR2L и истории# @@ -1648,6 +1654,13 @@ $ #Режимы интерфейса# единственным безопасным методом удаленного запуска far2l на не доверенном сервере с поддержкой всех привычных клавиатурных сочетаний и прочих удобств. + - Terminal emulators specific Backends (uses these terminal extensions to get state of all keyboard keys; +in pure TTY| to access clipboard you must turn on OSC 52 in both the FAR2L settings and the terminal settings; +TTY|X uses X11 to access clipboard): + - #TTY|a# or #TTY|Xa backend:# renders into Apple iTerm2 terminal. + - #TTY|k# or #TTY|Xk backend:# renders into kovidgoyal's Kitty (and any terminals with kovidgoyal's kitty keyboard protocol). + - #TTY|w# or #TTY|Xw backend:# renders into Windows Terminal (and any terminals with win32 input mode). + List and links to supported terminals see in ~FAR2L features - Getting Started~@Far2lGettingStarted@. @ConfirmDlg $ #Подтверждения# diff --git a/far2l/bootstrap/scripts/FarUkr.hlf.m4 b/far2l/bootstrap/scripts/FarUkr.hlf.m4 index fefefee7a..6a460dc74 100644 --- a/far2l/bootstrap/scripts/FarUkr.hlf.m4 +++ b/far2l/bootstrap/scripts/FarUkr.hlf.m4 @@ -1483,14 +1483,14 @@ $ #Режими інтерфейсу# - #Режим GUI:# виводить інтерфейс у своє власне графічне вікно, забезпечуючи найповнішу підтримка клавіатурних комбінацій. -- #Режим TTY:# виводить інтерфейс у стандартний термінал. Це найбільш сумісний спосіб, але він надає + - #Режим TTY:# виводить інтерфейс у стандартний термінал. Це найбільш сумісний спосіб, але він надає найменш повну підтримку клавіатурних комбінацій, немає загального буфера обміну тощо. - #Режим TTY|X:# виводить інтерфейс у звичайний термінал, але використовує X11 для доступу до буфера обміну та для отримання станів клавіш-модифікаторів Це забезпечує більш зручне використання, але все ще деякі клавіатурні комбінації можуть не підтримуватись. - #Режим TTY|Xi:# виводить інтерфейс у звичайний термінал, але використовує X11 з розширеннями Xi для доступу до буфера обміну та для отримання станів усіх клавіш клавіатури. Це забезпечує найзручніше використання у звичайному терміналі. -- #Режим TTY|F:# виводить інтерфейс термінал створений іншим додатком far2l instance. Це забезпечує рівень + - #Режим TTY|F:# виводить інтерфейс термінал створений іншим додатком far2l instance. Це забезпечує рівень зручність використання аналогічний режиму GUI (якщо термінал наданий GUI версією far2l). Якщо ви хочете запустити far2l віддалено з максимальною зручністю, то рекомендується або запустити його із сесії @@ -1503,6 +1503,12 @@ $ #Режими інтерфейсу# єдиним безпечним методом віддаленого запуску far2l на не довіреному сервері з підтримкою всіх звичних клавіатурних поєднань та інших зручностей. + - Terminal emulators specific Backends (uses these terminal extensions to get state of all keyboard keys; +in pure TTY| to access clipboard you must turn on OSC 52 in both the FAR2L settings and the terminal settings; +TTY|X uses X11 to access clipboard): + - #TTY|a# or #TTY|Xa backend:# renders into Apple iTerm2 terminal. + - #TTY|k# or #TTY|Xk backend:# renders into kovidgoyal's Kitty (and any terminals with kovidgoyal's kitty keyboard protocol). + - #TTY|w# or #TTY|Xw backend:# renders into Windows Terminal (and any terminals with win32 input mode). @ConfirmDlg $ #Підтвердження# diff --git a/far2l/bootstrap/scripts/farlang.templ.m4 b/far2l/bootstrap/scripts/farlang.templ.m4 index aa047845f..6a9da814b 100644 --- a/far2l/bootstrap/scripts/farlang.templ.m4 +++ b/far2l/bootstrap/scripts/farlang.templ.m4 @@ -12366,27 +12366,27 @@ l: "Редагування розмальовки файлів" "Мяняць афарбоўку файлаў" -HighlightMarkChar -"Оп&циональный символ пометки," -"Optional markin&g character," -"Volitelný &znak pro označení určených souborů," -"Optionale Markierun&g mit Zeichen," -"Megadható &jelölő karakter" -"Opcjonalny znak &wyróżniający zaznaczone pliki," -"Ca&racter opcional para marcar archivos específicos" -"Оп&ціональний символ позначки," -"Ап&цыянальны сімвал адзнакі," +HighlightMarking +"Ма&ркировка" +"Markin&g" +"O&značení" +"Markierun&g" +"&Jelzés" +"Cecho&wanie" +"Ma&rcado" +"Ма&ркування" +"М&аркіроўка" HighlightTransparentMarkChar -"прозра&чный" -"tra&nsparent" -"průh&ledný" -"tra&nsparent" +"Прозра&чный" +"Tra&nsparent" +"Průh&ledný" +"Tra&nsparent" "át&látszó" -"prze&zroczyste" -"tra&nsparente" -"проз&орий" -"празр&ысты" +"Prze&zroczyste" +"Tra&nsparente" +"Проз&орий" +"Празр&ысты" HighlightColors " Цвета файлов (\"чёрный на чёрном\" - цвет по умолчанию) " @@ -12506,7 +12506,7 @@ HighlightExample2 "║ fájlneve.kit│" "║ nazwa.roz │" "║ nombre.ext │" -"║filename.ext │" +"║ filename.ext│" "║ filename.ext│" HighlightContinueProcessing diff --git a/far2l/bootstrap/trash.sh b/far2l/bootstrap/trash.sh index 14b129a42..e2af561f4 100755 --- a/far2l/bootstrap/trash.sh +++ b/far2l/bootstrap/trash.sh @@ -12,7 +12,10 @@ if [ -x ~/.config/far2l/trash.sh ]; then . ~/.config/far2l/trash.sh fi -if command -v gio >/dev/null 2>&1; then +if command -v kioclient >/dev/null 2>&1; then + kioclient move "$1" trash:/ 2>"$2" + +elif command -v gio >/dev/null 2>&1; then gio trash -f -- "$1" 2>"$2" elif command -v gvfs-trash >/dev/null 2>&1; then diff --git a/far2l/src/console/interf.cpp b/far2l/src/console/interf.cpp index 558d1067c..10704da87 100644 --- a/far2l/src/console/interf.cpp +++ b/far2l/src/console/interf.cpp @@ -488,6 +488,14 @@ void InitRecodeOutTable() //_SVS(SysLogDump("Oem2Unicode",0,(LPBYTE)Oem2Unicode,sizeof(Oem2Unicode),nullptr)); } +void Text(int X, int Y, int Color, const WCHAR *Str, size_t Length) +{ + CurColor = FarColorToReal(Color); + CurX = X; + CurY = Y; + Text(Str, Length); +} + void Text(int X, int Y, int Color, const WCHAR *Str) { CurColor = FarColorToReal(Color); diff --git a/far2l/src/console/interf.hpp b/far2l/src/console/interf.hpp index 0752bcc6d..42d4e0619 100644 --- a/far2l/src/console/interf.hpp +++ b/far2l/src/console/interf.hpp @@ -85,6 +85,7 @@ void GetRealCursorPos(SHORT &X, SHORT &Y); void ScrollScreen(int Count); void Text(int X, int Y, int Color, const WCHAR *Str); +void Text(int X, int Y, int Color, const WCHAR *Str, size_t Length); void Text(const WCHAR *Str, size_t Length = (size_t)-1); void Text(FarLangMsg MsgId); void VText(const WCHAR *Str); diff --git a/far2l/src/filefilterparams.cpp b/far2l/src/filefilterparams.cpp index b18cb6fbc..24e21c7fd 100644 --- a/far2l/src/filefilterparams.cpp +++ b/far2l/src/filefilterparams.cpp @@ -260,11 +260,6 @@ void FileFilterParams::GetColors(HighlightDataColor *Colors) const *Colors = FHighlight.Colors; } -wchar_t FileFilterParams::GetMarkChar() const -{ - return (wchar_t)(FHighlight.Colors.MarkChar & 0xffff); // higher half used for something else -} - bool FileFilterParams::FileInFilter(const FileListItem &fli, uint64_t CurrentTime) const { return FileInFilterImpl(fli.strName, fli.FileAttr, fli.FileSize, fli.CreationTime, fli.AccessTime, @@ -381,13 +376,18 @@ void MenuString(FARString &strDest, FileFilterParams *FF, bool bHighlightType, i const wchar_t Format1b[] = L"%-22.22ls %lc %-38.38ls %-2.2ls %lc %ls"; const wchar_t Format1c[] = L"&%lc. %-18.18ls %lc %-38.38ls %-2.2ls %lc %ls"; const wchar_t Format1d[] = L" %-18.18ls %lc %-38.38ls %-2.2ls %lc %ls"; - const wchar_t Format2[] = L"%-3.3ls %lc %-38.38ls %-3.3ls %lc %ls"; + + const wchar_t Format2[] = L"%ls %lc %-38.38ls %-3.3ls %lc %ls"; +// const wchar_t Format2[] = L"%-5.5ls %lc %-38.38ls %-3.3ls %lc %ls"; const wchar_t DownArrow = 0x2193; const wchar_t *Name, *Mask; - wchar_t MarkChar[] = L"\" \""; DWORD IncludeAttr, ExcludeAttr; bool UseMask, UseSize, UseDate, RelativeDate; + HighlightDataColor hl; + #define MARK_STRING_PREVIEW_LENGTH 5 + wchar_t MarkStrPrw[MARK_STRING_PREVIEW_LENGTH + 4] = {0}; + if (bPanelType) { Name = Title; UseMask = true; @@ -396,10 +396,20 @@ void MenuString(FARString &strDest, FileFilterParams *FF, bool bHighlightType, i ExcludeAttr = FILE_ATTRIBUTE_DIRECTORY; RelativeDate = UseDate = UseSize = false; } else { - MarkChar[1] = FF->GetMarkChar(); - if (!MarkChar[1]) - *MarkChar = 0; + FF->GetColors(&hl); + size_t ng = 0, mcl = 0; + + if (hl.MarkLen) { + ng = MARK_STRING_PREVIEW_LENGTH; + mcl = StrSizeOfCells(hl.Mark, hl.MarkLen, ng, false); + memcpy(MarkStrPrw, hl.Mark, mcl * sizeof(wchar_t)); + ng = StrCellsCount( MarkStrPrw, mcl ); + } + for (int i = ng; i < MARK_STRING_PREVIEW_LENGTH; i++, mcl++) { + MarkStrPrw[mcl] = 32; + } + MarkStrPrw[mcl] = 0; Name = FF->GetTitle(); UseMask = FF->GetMask(&Mask); @@ -442,7 +452,7 @@ void MenuString(FARString &strDest, FileFilterParams *FF, bool bHighlightType, i if (FF->GetContinueProcessing()) SizeDate[2] = DownArrow; - strDest.Format(Format2, MarkChar, BoxSymbols[BS_V1], Attr, SizeDate, BoxSymbols[BS_V1], + strDest.Format(Format2, MarkStrPrw, BoxSymbols[BS_V1], Attr, SizeDate, BoxSymbols[BS_V1], UseMask ? Mask : L""); } else { SizeDate[2] = 0; @@ -462,6 +472,27 @@ void MenuString(FARString &strDest, FileFilterParams *FF, bool bHighlightType, i RemoveTrailingSpaces(strDest); } +struct filterpar_highlight_state_s +{ + CHAR_INFO vbuff[32 * 4]; + uint32_t outlen[4]; + HighlightDataColor hl; + +// CHAR_INFO vbuff[64]; // draw buffer +// uint64_t color; // rgb | flags | index +// uint32_t id; +// uint32_t offset; +// uint32_t index; // foreground or background index +// bool bTransparent; // color = 0 +// std::function RefreshColor; +// size_t Offset; + +// intptr_t WINAPI ColorPanelUserProc(HANDLE hDlg, int Msg, int Param1, intptr_t Param2); +//LONG_PTR WINAPI ColorPanelUserProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) + +// color_panel_state(); +}; + enum enumFileFilterConfig { ID_FF_TITLE, @@ -552,14 +583,23 @@ enum enumFileFilterConfig ID_FF_MAKETRANSPARENT, }; -static void HighlightDlgUpdateUserControl(CHAR_INFO *VBufColorExample, HighlightDataColor &Colors) +#if 0 + +static void HighlightDlgUpdateUserControl(filterpar_highlight_state_s *fphlstate) { - const wchar_t *ptr; - DWORD64 Color; + DWORD64 Color, ColorM; const DWORD FarColor[] = {COL_PANELTEXT, COL_PANELSELECTEDTEXT, COL_PANELCURSOR, COL_PANELSELECTEDCURSOR}; + static const wchar_t *wstrFilenameExample = L"filename.ext"; + HighlightDataColor *hl = &fphlstate->hl; + size_t ng = 12, mcl; + mcl = StrSizeOfCells(hl->Mark, hl->MarkLen, ng, false); + ng = StrCellsCount( hl->Mark, mcl ); + + for (int i = 0; i < 4; i++) { + + CHAR_INFO *vbuff = &fphlstate->vbuff[26 * i]; - for (int j = 0; j < 4; j++) { - Color = (Colors.Color[HIGHLIGHTCOLORTYPE_FILE][j] & 0xFFFFFFFFFFFF00FF); + Color = (hl->Color[HIGHLIGHTCOLORTYPE_FILE][i] & 0xFFFFFFFFFFFF00FF); if (Color) { if (Color & 0x000000FFFFFF0000) { Color|= FOREGROUND_TRUECOLOR; @@ -568,32 +608,46 @@ static void HighlightDlgUpdateUserControl(CHAR_INFO *VBufColorExample, Highlight Color|= BACKGROUND_TRUECOLOR; } } else { - Color = FarColorToReal(FarColor[j]); + Color = FarColorToReal(FarColor[i]); } - if (Colors.MarkChar & 0x0000FFFF) - ptr = Msg::HighlightExample2; + if (hl->Color[HIGHLIGHTCOLORTYPE_MARKCHAR][i] & 0x00FF) + ColorM = hl->Color[HIGHLIGHTCOLORTYPE_MARKCHAR][i] & 0x00FF; else - ptr = Msg::HighlightExample1; + ColorM = Color; - for (int k = 0; k < 15; k++) { - VBufColorExample[15 * j + k].Char.UnicodeChar = ptr[k]; - VBufColorExample[15 * j + k].Attributes = Color; + vbuff->Char.UnicodeChar = BoxSymbols[BS_V2]; + vbuff->Attributes = FarColorToReal(COL_PANELBOX); + ++vbuff; + + for (int j = 0; j < mcl ; j++) { + vbuff[j].Char.UnicodeChar = hl->Mark[j]; + vbuff[j].Attributes = ColorM; } + vbuff += mcl; - if (Colors.MarkChar & 0x0000FFFF) { - VBufColorExample[15 * j + 1].Char.UnicodeChar = (WCHAR)Colors.MarkChar & 0x0000FFFF; + for (int j = 0; j < 12 ; j++) { + vbuff[j].Char.UnicodeChar = wstrFilenameExample[j]; + vbuff[j].Attributes = Color; + } + vbuff += 12; - if (Colors.Color[HIGHLIGHTCOLORTYPE_MARKCHAR][j] & 0x00FF) - VBufColorExample[15 * j + 1].Attributes = - Colors.Color[HIGHLIGHTCOLORTYPE_MARKCHAR][j] & 0x00FF; + for (int j = 0; j < 12 - ng ; j++) { // trailing spaces + vbuff[j].Char.UnicodeChar = 32; + vbuff[j].Attributes = Color; } + vbuff += 12 - ng; - VBufColorExample[15 * j].Attributes = FarColorToReal(COL_PANELBOX); - VBufColorExample[15 * j + 14].Attributes = FarColorToReal(COL_PANELBOX); + fphlstate->outlen[i] = 12 + mcl + (12 - ng) + 2; + + vbuff->Char.UnicodeChar = BoxSymbols[BS_V1]; + vbuff->Attributes = FarColorToReal(COL_PANELBOX); } + } +#endif + void FilterDlgRelativeDateItemsUpdate(HANDLE hDlg, bool bClear) { SendDlgMessage(hDlg, DM_ENABLEREDRAW, FALSE, 0); @@ -626,11 +680,75 @@ void FilterDlgRelativeDateItemsUpdate(HANDLE hDlg, bool bClear) LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) { + filterpar_highlight_state_s *fphlstate = (filterpar_highlight_state_s *)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); + bool bColorConfig = (fphlstate); + switch (Msg) { case DN_INITDIALOG: { FilterDlgRelativeDateItemsUpdate(hDlg, false); return TRUE; } + + case DN_DRAWDLGITEM: { + + if (Param1 != ID_HER_COLOREXAMPLE) + break; + + static const DWORD FarColor[] = {COL_PANELTEXT, COL_PANELSELECTEDTEXT, COL_PANELCURSOR, COL_PANELSELECTEDCURSOR}; + static const wchar_t VerticalLine0[] = {BoxSymbols[BS_V2], 0}; + static const wchar_t VerticalLine1[] = {BoxSymbols[BS_V1], 0}; + static const wchar_t *wstrFilenameExample = L"filename.ext"; + static const wchar_t *wstrSpaces = L" "; + + HighlightDataColor *hl = &fphlstate->hl; + DWORD64 Color, ColorM, ColorB = FarColorToReal(COL_PANELBOX); + + FarDialogItem di; + SendDlgMessage(hDlg, DM_GETDLGITEMSHORT, Param1, (LONG_PTR)&di); + SMALL_RECT drect; + SendDlgMessage(hDlg, DM_GETDLGRECT, 0, (LONG_PTR)&drect); + + size_t ng = 12, mcl; + mcl = StrSizeOfCells(hl->Mark, hl->MarkLen, ng, false); + ng = StrCellsCount( hl->Mark, mcl ); + + for (int i = 0; i < 4; i++) { + + int x = drect.Left + di.X1; + int y = drect.Top + di.Y1 + i; + + Color = (hl->Color[HIGHLIGHTCOLORTYPE_FILE][i] & 0xFFFFFFFFFFFF00FF); + if (Color) { + if (Color & 0x000000FFFFFF0000) { + Color|= FOREGROUND_TRUECOLOR; + } + if (Color & 0xFFFFFF0000000000) { + Color|= BACKGROUND_TRUECOLOR; + } + } else { + Color = FarColorToReal(FarColor[i]); + } + + if (hl->Color[HIGHLIGHTCOLORTYPE_MARKCHAR][i] & 0x00FF) + ColorM = hl->Color[HIGHLIGHTCOLORTYPE_MARKCHAR][i] & 0x00FF; + else + ColorM = Color; + + Text(x, y, ColorB, VerticalLine0, 1); + x++; + Text(x, y, ColorM, hl->Mark, mcl); + x += ng; + Text(x, y, Color, wstrFilenameExample, 12); + x += 12; + Text(x, y, Color, wstrSpaces, 12-ng); + x += (12 - ng); + Text(x, y, ColorB, VerticalLine1, 1); + } + + return 0; + } + break; + case DN_BTNCLICK: { if (Param1 == ID_FF_CURRENT || Param1 == ID_FF_BLANK) // Current и Blank { @@ -662,7 +780,6 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P } else if (Param1 == ID_FF_RESET) // Reset { SendDlgMessage(hDlg, DM_ENABLEREDRAW, FALSE, 0); - LONG_PTR ColorConfig = SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); SendDlgMessage(hDlg, DM_SETTEXTPTR, ID_FF_MASKEDIT, (LONG_PTR)L"*"); SendDlgMessage(hDlg, DM_SETTEXTPTR, ID_FF_SIZEFROMEDIT, (LONG_PTR)L""); SendDlgMessage(hDlg, DM_SETTEXTPTR, ID_FF_SIZETOEDIT, (LONG_PTR)L""); @@ -671,7 +788,7 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P SendDlgMessage(hDlg, DM_SETCHECK, I, BSTATE_3STATE); } - if (!ColorConfig) + if (!bColorConfig) SendDlgMessage(hDlg, DM_SETCHECK, ID_FF_DIRECTORY, BSTATE_UNCHECKED); FarListPos LPos = {0, 0}; @@ -682,7 +799,7 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P SendDlgMessage(hDlg, DM_SETCHECK, ID_FF_DATERELATIVE, BSTATE_UNCHECKED); FilterDlgRelativeDateItemsUpdate(hDlg, true); SendDlgMessage(hDlg, DM_SETCHECK, ID_FF_MATCHATTRIBUTES, - ColorConfig ? BSTATE_UNCHECKED : BSTATE_CHECKED); + bColorConfig ? BSTATE_UNCHECKED : BSTATE_CHECKED); SendDlgMessage(hDlg, DM_ENABLEREDRAW, TRUE, 0); break; } else if (Param1 == ID_FF_MAKETRANSPARENT) { @@ -702,34 +819,32 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P case DN_MOUSECLICK: if ((Msg == DN_BTNCLICK && Param1 >= ID_HER_NORMALFILE && Param1 <= ID_HER_SELECTEDCURSORMARKING) - || (Msg == DN_MOUSECLICK && Param1 == ID_HER_COLOREXAMPLE - && ((MOUSE_EVENT_RECORD *)Param2)->dwButtonState - == FROM_LEFT_1ST_BUTTON_PRESSED)) { - HighlightDataColor *EditData = - (HighlightDataColor *)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); + || (Msg == DN_MOUSECLICK && Param1 == ID_HER_COLOREXAMPLE && + ((MOUSE_EVENT_RECORD *)Param2)->dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)) { if (Msg == DN_MOUSECLICK) { Param1 = ID_HER_NORMALFILE + ((MOUSE_EVENT_RECORD *)Param2)->dwMousePosition.Y * 2; if (((MOUSE_EVENT_RECORD *)Param2)->dwMousePosition.X == 1 - && (EditData->MarkChar & 0x0000FFFF)) + && (fphlstate->hl.MarkLen)) Param1 = ID_HER_NORMALMARKING + ((MOUSE_EVENT_RECORD *)Param2)->dwMousePosition.Y * 2; } // Color[0=file, 1=mark][0=normal,1=selected,2=undercursor,3=selectedundercursor] - DWORD64 Color = EditData->Color[(Param1 - ID_HER_NORMALFILE) & 1][(Param1 - ID_HER_NORMALFILE) / 2]; + DWORD64 Color = fphlstate->hl.Color[(Param1 - ID_HER_NORMALFILE) & 1][(Param1 - ID_HER_NORMALFILE) / 2]; GetColorDialogForFileFilter(Color); - EditData->Color[(Param1 - ID_HER_NORMALFILE) & 1][(Param1 - ID_HER_NORMALFILE) / 2] = Color; - FarDialogItem *ColorExample = - (FarDialogItem *)malloc(SendDlgMessage(hDlg, DM_GETDLGITEM, ID_HER_COLOREXAMPLE, 0)); - SendDlgMessage(hDlg, DM_GETDLGITEM, ID_HER_COLOREXAMPLE, (LONG_PTR)ColorExample); - wchar_t MarkChar[2]; - // MarkChar это FIXEDIT размером в 1 символ так что проверять размер строки не надо - SendDlgMessage(hDlg, DM_GETTEXTPTR, ID_HER_MARKEDIT, (LONG_PTR)MarkChar); - EditData->MarkChar = *MarkChar; - HighlightDlgUpdateUserControl(ColorExample->Param.VBuf, *EditData); - SendDlgMessage(hDlg, DM_SETDLGITEM, ID_HER_COLOREXAMPLE, (LONG_PTR)ColorExample); - free(ColorExample); + fphlstate->hl.Color[(Param1 - ID_HER_NORMALFILE) & 1][(Param1 - ID_HER_NORMALFILE) / 2] = Color; + + int nLength = (int)SendDlgMessage(hDlg, DM_GETTEXTLENGTH, ID_HER_MARKEDIT, 0); + if (nLength > HIGHLIGHT_MAX_MARK_LENGTH ) { + SendDlgMessage(hDlg, DM_SETTEXTPTR, ID_HER_MARKEDIT, (LONG_PTR)&fphlstate->hl.Mark[0]); + } + else { + SendDlgMessage(hDlg, DM_GETTEXTPTR, ID_HER_MARKEDIT, (LONG_PTR)&fphlstate->hl.Mark[0]); + fphlstate->hl.MarkLen = nLength; + } + +// HighlightDlgUpdateUserControl(fphlstate); return TRUE; } @@ -737,18 +852,17 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P case DN_EDITCHANGE: if (Param1 == ID_HER_MARKEDIT) { - HighlightDataColor *EditData = - (HighlightDataColor *)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); - FarDialogItem *ColorExample = - (FarDialogItem *)malloc(SendDlgMessage(hDlg, DM_GETDLGITEM, ID_HER_COLOREXAMPLE, 0)); - SendDlgMessage(hDlg, DM_GETDLGITEM, ID_HER_COLOREXAMPLE, (LONG_PTR)ColorExample); - wchar_t MarkChar[2]; - // MarkChar это FIXEDIT размером в 1 символ так что проверять размер строки не надо - SendDlgMessage(hDlg, DM_GETTEXTPTR, ID_HER_MARKEDIT, (LONG_PTR)MarkChar); - EditData->MarkChar = *MarkChar; - HighlightDlgUpdateUserControl(ColorExample->Param.VBuf, *EditData); - SendDlgMessage(hDlg, DM_SETDLGITEM, ID_HER_COLOREXAMPLE, (LONG_PTR)ColorExample); - free(ColorExample); + + int nLength = (int)SendDlgMessage(hDlg, DM_GETTEXTLENGTH, ID_HER_MARKEDIT, 0); + if (nLength > HIGHLIGHT_MAX_MARK_LENGTH ) { + SendDlgMessage(hDlg, DM_SETTEXTPTR, ID_HER_MARKEDIT, (LONG_PTR)&fphlstate->hl.Mark[0]); + } + else { + SendDlgMessage(hDlg, DM_GETTEXTPTR, ID_HER_MARKEDIT, (LONG_PTR)&fphlstate->hl.Mark[0]); + fphlstate->hl.MarkLen = nLength; + } + +// HighlightDlgUpdateUserControl(fphlstate); return TRUE; } @@ -766,8 +880,7 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P bTemp = bTemp && (!*temp || CheckFileSizeStringFormat(temp)); if (!bTemp) { - LONG_PTR ColorConfig = SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); - Message(MSG_WARNING, 1, ColorConfig ? Msg::FileHilightTitle : Msg::FileFilterTitle, + Message(MSG_WARNING, 1, bColorConfig ? Msg::FileHilightTitle : Msg::FileFilterTitle, Msg::BadFileSizeFormat, Msg::Ok); return FALSE; } @@ -781,7 +894,7 @@ LONG_PTR WINAPI FileFilterConfigDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_P bool FileFilterConfig(FileFilterParams *FF, bool ColorConfig) { - const wchar_t VerticalLine[] = {BoxSymbols[BS_T_H1V1], BoxSymbols[BS_V1], BoxSymbols[BS_V1], + static const wchar_t VerticalLine[] = {BoxSymbols[BS_T_H1V1], BoxSymbols[BS_V1], BoxSymbols[BS_V1], BoxSymbols[BS_V1], BoxSymbols[BS_B_H1V1], 0}; // Временная маска. CFileMask FileMask; @@ -878,8 +991,8 @@ bool FileFilterConfig(FileFilterParams *FF, bool ColorConfig) {DI_CHECKBOX, 64, 14, 0, 14, {}, DIF_3STATE, Msg::FileFilterAttrDevSock }, {DI_TEXT, -1, 15, 0, 15, {}, DIF_SEPARATOR, Msg::HighlightColors }, - {DI_TEXT, 7, 16, 0, 16, {}, 0, Msg::HighlightMarkChar }, - {DI_FIXEDIT, 5, 16, 5, 16, {}, 0, L"" }, + {DI_TEXT, 16, 16, 0, 16, {}, 0, Msg::HighlightMarking }, + {DI_EDIT, 5, 16, 14, 16, {}, 0, L"" }, {DI_CHECKBOX, 0, 16, 0, 16, {}, 0, Msg::HighlightTransparentMarkChar}, {DI_BUTTON, 5, 17, 0, 17, {}, DIF_BTNNOCLOSE | DIF_NOBRACKETS, Msg::HighlightFileName1 }, @@ -891,7 +1004,7 @@ bool FileFilterConfig(FileFilterParams *FF, bool ColorConfig) {DI_BUTTON, 5, 20, 0, 20, {}, DIF_BTNNOCLOSE | DIF_NOBRACKETS, Msg::HighlightFileName4 }, {DI_BUTTON, 0, 20, 0, 20, {}, DIF_BTNNOCLOSE | DIF_NOBRACKETS, Msg::HighlightMarking4 }, - {DI_USERCONTROL, 73 - 15 - 1, 17, 73 - 2, 20, {}, DIF_NOFOCUS, L"" }, + {DI_USERCONTROL, 54, 17, 79, 20, {}, DIF_NOFOCUS, L"" }, {DI_CHECKBOX, 5, 21, 0, 21, {}, 0, Msg::HighlightContinueProcessing }, {DI_TEXT, 0, 17, 0, 17, {}, DIF_SEPARATOR, L"" }, @@ -946,16 +1059,18 @@ bool FileFilterConfig(FileFilterParams *FF, bool ColorConfig) + (int)FilterDlg[ID_HER_NORMALFILE].strData.GetLength() - (FilterDlg[ID_HER_NORMALFILE].strData.Contains(L'&') ? 1 : 0) + 1; - CHAR_INFO VBufColorExample[15 * 4] = {}; - HighlightDataColor Colors; - FF->GetColors(&Colors); - HighlightDlgUpdateUserControl(VBufColorExample, Colors); - FilterDlg[ID_HER_COLOREXAMPLE].VBuf = VBufColorExample; - wchar_t MarkChar[] = {(wchar_t)Colors.MarkChar & 0x0000FFFF, 0}; - FilterDlg[ID_HER_MARKEDIT].strData = MarkChar; - FilterDlg[ID_HER_MARKTRANSPARENT].Selected = (Colors.MarkChar & 0xFF0000 ? 1 : 0); + filterpar_highlight_state_s fphlstate; + + FF->GetColors(&fphlstate.hl); +// HighlightDlgUpdateUserControl(&fphlstate); + FilterDlg[ID_HER_COLOREXAMPLE].VBuf = fphlstate.vbuff; + + FilterDlg[ID_HER_MARKEDIT].strData = fphlstate.hl.Mark; + FilterDlg[ID_HER_MARKTRANSPARENT].Selected = (fphlstate.hl.bTransparent ? 1 : 0); + FilterDlg[ID_HER_CONTINUEPROCESSING].Selected = (FF->GetContinueProcessing() ? 1 : 0); FilterDlg[ID_FF_NAMEEDIT].strData = FF->GetTitle(); + const wchar_t *FMask; FilterDlg[ID_FF_MATCHMASK].Selected = FF->GetMask(&FMask) ? 1 : 0; FilterDlg[ID_FF_MASKEDIT].strData = FMask; @@ -1095,7 +1210,7 @@ bool FileFilterConfig(FileFilterParams *FF, bool ColorConfig) } Dialog Dlg(FilterDlg, ARRAYSIZE(FilterDlg), FileFilterConfigDlgProc, - (LONG_PTR)(ColorConfig ? &Colors : nullptr)); + (LONG_PTR)(ColorConfig ? &fphlstate : nullptr)); Dlg.SetHelp(ColorConfig ? L"HighlightEdit" : L"Filter"); Dlg.SetPosition(-1, -1, FilterDlg[ID_FF_TITLE].X2 + 4, FilterDlg[ID_FF_TITLE].Y2 + 2); Dlg.SetAutomation(ID_FF_MATCHMASK, ID_FF_MASKEDIT, DIF_DISABLE, DIF_NONE, DIF_NONE, DIF_DISABLE); @@ -1130,12 +1245,9 @@ bool FileFilterConfig(FileFilterParams *FF, bool ColorConfig) if (FilterDlg[ID_FF_MATCHMASK].Selected && !FileMask.Set(FilterDlg[ID_FF_MASKEDIT].strData, 0)) continue; - if (FilterDlg[ID_HER_MARKTRANSPARENT].Selected) - Colors.MarkChar|= 0x00FF0000; - else - Colors.MarkChar&= 0x0000FFFF; + fphlstate.hl.bTransparent = FilterDlg[ID_HER_MARKTRANSPARENT].Selected; - FF->SetColors(&Colors); + FF->SetColors(&fphlstate.hl); FF->SetContinueProcessing(FilterDlg[ID_HER_CONTINUEPROCESSING].Selected != 0); FF->SetTitle(FilterDlg[ID_FF_NAMEEDIT].strData); FF->SetMask(FilterDlg[ID_FF_MATCHMASK].Selected != 0, FilterDlg[ID_FF_MASKEDIT].strData); diff --git a/far2l/src/filefilterparams.hpp b/far2l/src/filefilterparams.hpp index a3b1976a6..11ab79143 100644 --- a/far2l/src/filefilterparams.hpp +++ b/far2l/src/filefilterparams.hpp @@ -156,7 +156,7 @@ class FileFilterParams bool GetSize(const wchar_t **SizeAbove, const wchar_t **SizeBelow) const; bool GetAttr(DWORD *AttrSet, DWORD *AttrClear) const; void GetColors(HighlightDataColor *Colors) const; - wchar_t GetMarkChar() const; + int GetSortGroup() const { return FHighlight.SortGroup; } bool GetContinueProcessing() const { return FHighlight.bContinueProcessing; } DWORD GetFlags(enumFileFilterFlagsType FType) const { return FFlags[FType]; } diff --git a/far2l/src/help.cpp b/far2l/src/help.cpp index 347f7b0f2..4f807d39d 100644 --- a/far2l/src/help.cpp +++ b/far2l/src/help.cpp @@ -1266,7 +1266,7 @@ int Help::JumpTopic(const wchar_t *JumpTopic) DeleteEndSlash(strFullPath, true); strFullPath+= L"/"; strFullPath+= strNewTopic.CPtr() + (IsSlash(strNewTopic.At(0)) ? 1 : 0); - BOOL addSlash = DeleteEndSlash(strFullPath); + bool addSlash = DeleteEndSlash(strFullPath); ConvertNameToFull(strFullPath, strNewTopic); strFullPath.Format(addSlash ? HelpFormatLink : HelpFormatLinkModule, strNewTopic.CPtr(), wcschr(StackData.strSelTopic.CPtr() + 2, HelpEndLink) + 1); diff --git a/far2l/src/hilight.cpp b/far2l/src/hilight.cpp index 2a8257c2d..829ba6e9c 100644 --- a/far2l/src/hilight.cpp +++ b/far2l/src/hilight.cpp @@ -62,7 +62,7 @@ struct HighlightStrings *Mask, *NormalColor, *SelectedColor, *CursorColor, *SelectedCursorColor, *MarkCharNormalColor, *MarkCharSelectedColor, *MarkCharCursorColor, *MarkCharSelectedCursorColor, *MarkChar, *ContinueProcessing, *UseDate, *DateType, *DateAfter, *DateBefore, *DateRelative, *UseSize, - *SizeAbove, *SizeBelow, *HighlightEdit, *HighlightList; + *SizeAbove, *SizeBelow, *HighlightEdit, *HighlightList, *MarkStr; }; static const HighlightStrings HLS = {"UseAttr", "IncludeAttributes", "ExcludeAttributes", "AttrSet", @@ -70,7 +70,7 @@ static const HighlightStrings HLS = {"UseAttr", "IncludeAttributes", "ExcludeAtt "SelectedCursorColor", "MarkCharNormalColor", "MarkCharSelectedColor", "MarkCharCursorColor", "MarkCharSelectedCursorColor", "MarkChar", "ContinueProcessing", "UseDate", "DateType", "DateAfter", "DateBefore", "DateRelative", "UseSize", "SizeAboveS", "SizeBelowS", "HighlightEdit", - "HighlightList"}; + "HighlightList", "MarkStr" }; static const char fmtFirstGroup[] = "Group%d"; static const char fmtUpperGroup[] = "UpperGroup%d"; @@ -191,7 +191,31 @@ static void LoadFilter(FileFilterParams *HData, ConfigReader &cfg_reader, const cfg_reader.GetULL(HLS.MarkCharCursorColor, 0); Colors.Color[HIGHLIGHTCOLORTYPE_MARKCHAR][HIGHLIGHTCOLOR_SELECTEDUNDERCURSOR] = cfg_reader.GetULL(HLS.MarkCharSelectedCursorColor, 0); - Colors.MarkChar = cfg_reader.GetUInt(HLS.MarkChar, 0); + + { // Load Mark str + FARString strMark = cfg_reader.GetString(HLS.MarkStr, L""); + DWORD dwMarkLen = strMark.GetLength(); + DWORD dwMarkChar = cfg_reader.GetUInt(HLS.MarkChar, 0); + + Colors.bTransparent = (dwMarkChar & 0xFF0000); + dwMarkChar &= 0x0000FFFF; + + if (dwMarkLen) { + if (dwMarkLen > HIGHLIGHT_MAX_MARK_LENGTH) + dwMarkLen = HIGHLIGHT_MAX_MARK_LENGTH; + + memcpy(&Colors.Mark[0], strMark.GetBuffer(), sizeof(wchar_t) * dwMarkLen); + strMark.ReleaseBuffer(); + } + else if (dwMarkChar) { + Colors.Mark[0] = dwMarkChar; + dwMarkLen = 1; + } + + Colors.Mark[dwMarkLen] = 0; // terminate + Colors.MarkLen = dwMarkLen; + } + HData->SetColors(&Colors); HData->SetContinueProcessing(cfg_reader.GetInt(HLS.ContinueProcessing, 0) != 0); } @@ -261,9 +285,11 @@ static const DWORD FarColor[] = {COL_PANELTEXT, COL_PANELSELECTEDTEXT, COL_PANEL static const HighlightDataColor DefaultStartingColors = { - {0xFF00, 0xFF00, 0xFF00, 0xFF00, // Color[0] - 0xFF00, 0xFF00, 0xFF00, 0xFF00}, // Color[1] - 0x00FF0000 // MarkChar + {0xFF00, 0xFF00, 0xFF00, 0xFF00, // Color[0][4] + 0xFF00, 0xFF00, 0xFF00, 0xFF00}, // Color[1][4] + {0}, // wchar_t Mark + 0, // size_t MarkLen; + true // bool bTransparent; }; const HighlightDataColor ZeroColors{0}; @@ -309,8 +335,10 @@ static void ApplyColors(HighlightDataColor *DestColors, HighlightDataColor *SrcC } // Унаследуем пометку из Src если она не прозрачная - if (!(SrcColors->MarkChar & 0x00FF0000)) - DestColors->MarkChar = SrcColors->MarkChar; + if (!SrcColors->bTransparent && SrcColors->MarkLen) { + DestColors->MarkLen = SrcColors->MarkLen; + memcpy(&DestColors->Mark[0], &SrcColors->Mark[0], sizeof(wchar_t) * SrcColors->MarkLen); + } } /* @@ -344,8 +372,8 @@ static void ApplyFinalColors(HighlightDataColor *Colors) } // Если символ пометки прозрачный то его как бы и нет вообще. - if (Colors->MarkChar & 0x00FF0000) - Colors->MarkChar = 0; +// if (Colors->MarkChar & 0x00FF0000) +// Colors->MarkChar = 0; // Параноя но случится может: // Обработаем black on black снова чтоб обработались унаследованые цвета. @@ -769,20 +797,24 @@ static void SaveFilter(FileFilterParams *CurHiData, ConfigWriter &cfg_writer, bo DWORD DateType; FILETIME DateAfter, DateBefore; bool bRelative; + cfg_writer.SetInt(HLS.UseDate, CurHiData->GetDate(&DateType, &DateAfter, &DateBefore, &bRelative) ? 1 : 0); cfg_writer.SetUInt(HLS.DateType, DateType); cfg_writer.SetPOD(HLS.DateAfter, DateAfter); cfg_writer.SetPOD(HLS.DateBefore, DateBefore); cfg_writer.SetInt(HLS.DateRelative, bRelative ? 1 : 0); + const wchar_t *SizeAbove = nullptr, *SizeBelow = nullptr; cfg_writer.SetInt(HLS.UseSize, CurHiData->GetSize(&SizeAbove, &SizeBelow) ? 1 : 0); cfg_writer.SetString(HLS.SizeAbove, SizeAbove); cfg_writer.SetString(HLS.SizeBelow, SizeBelow); + DWORD AttrSet = 0, AttrClear = 0; cfg_writer.SetInt(HLS.UseAttr, CurHiData->GetAttr(&AttrSet, &AttrClear) ? 1 : 0); cfg_writer.SetUInt((bSortGroup ? HLS.AttrSet : HLS.IncludeAttributes), AttrSet); cfg_writer.SetUInt((bSortGroup ? HLS.AttrClear : HLS.ExcludeAttributes), AttrClear); + HighlightDataColor Colors{}; CurHiData->GetColors(&Colors); cfg_writer.SetULL(HLS.NormalColor, Colors.Color[HIGHLIGHTCOLORTYPE_FILE][HIGHLIGHTCOLOR_NORMAL]); @@ -800,7 +832,20 @@ static void SaveFilter(FileFilterParams *CurHiData, ConfigWriter &cfg_writer, bo Colors.Color[HIGHLIGHTCOLORTYPE_MARKCHAR][HIGHLIGHTCOLOR_UNDERCURSOR]); cfg_writer.SetULL(HLS.MarkCharSelectedCursorColor, Colors.Color[HIGHLIGHTCOLORTYPE_MARKCHAR][HIGHLIGHTCOLOR_SELECTEDUNDERCURSOR]); - cfg_writer.SetUInt(HLS.MarkChar, Colors.MarkChar); + + { // Save Mark str + FARString strMark = L""; + DWORD dwMarkChar = (Colors.MarkLen == 1) ? Colors.Mark[0] : 0; + dwMarkChar |= (0xFF0000 * Colors.bTransparent); + + cfg_writer.SetUInt(HLS.MarkChar, dwMarkChar); + + if (Colors.MarkLen > 1) + strMark = Colors.Mark; + + cfg_writer.SetString(HLS.MarkStr, strMark); + } + cfg_writer.SetInt(HLS.ContinueProcessing, (CurHiData->GetContinueProcessing() ? 1 : 0)); } @@ -856,8 +901,14 @@ void HighlightFiles::SaveHiData() static bool operator==(const HighlightDataColor &color1, const HighlightDataColor &color2) { - if (color1.MarkChar != color2.MarkChar) + if (color1.MarkLen != color2.MarkLen) return false; + if (color1.bTransparent != color2.bTransparent) + return false; + + if (color1.MarkLen) + if (memcmp(&color1.Mark[0], &color2.Mark[0], sizeof(wchar_t) * color1.MarkLen)) + return false; for (size_t i = 0; i < ARRAYSIZE(color1.Color); ++i) { for (size_t j = 0; j < ARRAYSIZE(color1.Color[i]); ++j) { @@ -874,7 +925,7 @@ struct HighlightDataColorHash { size_t operator()(const HighlightDataColor &color) const { - size_t out = color.MarkChar; + size_t out = color.MarkLen * 0xFFFF; for (size_t i = 0; i < ARRAYSIZE(color.Color); ++i) { for (size_t j = 0; j < ARRAYSIZE(color.Color[i]); ++j) { out^= color.Color[i][j] + ((i ^ j) << 16); diff --git a/far2l/src/hilight.hpp b/far2l/src/hilight.hpp index 40a28218b..2dc8d846c 100644 --- a/far2l/src/hilight.hpp +++ b/far2l/src/hilight.hpp @@ -36,6 +36,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "CFileMask.hpp" #include "array.hpp" +#define HIGHLIGHT_MAX_MARK_LENGTH 8 + class VMenu; class FileFilterParams; struct FileListItem; @@ -56,7 +58,9 @@ struct HighlightDataColor DWORD64 Color[2][4]; // [0=file, 1=mark][0=normal,1=selected,2=undercursor,3=selectedundercursor]; // if HIBYTE == 0xFF then transparent // nonzero upper 3 bytes meaning foreground RGB, nonzero lower 3 bytes meaning background RGB - DWORD MarkChar; + wchar_t Mark[HIGHLIGHT_MAX_MARK_LENGTH + 1]; // + null terminator + uint32_t MarkLen; + bool bTransparent; }; class HighlightFiles diff --git a/far2l/src/main.cpp b/far2l/src/main.cpp index cb68f9e0b..eefd002ea 100644 --- a/far2l/src/main.cpp +++ b/far2l/src/main.cpp @@ -760,6 +760,11 @@ int _cdecl main(int argc, char *argv[]) setlocale(LC_ALL, ""); // otherwise non-latin keys missing with XIM input method + const char *lcc = getenv("LC_COLLATE"); + if (lcc && *lcc) { + setlocale(LC_COLLATE, lcc); + } + SetupFarPath(argv[0]); { // if CONFIG_INI is not present => first start & opt for show Help "FAR2L features - Getting Started" diff --git a/far2l/src/mix/pathmix.cpp b/far2l/src/mix/pathmix.cpp index d2f54db7c..bd3ed661b 100644 --- a/far2l/src/mix/pathmix.cpp +++ b/far2l/src/mix/pathmix.cpp @@ -292,11 +292,11 @@ bool DeleteEndSlash(wchar_t *Path, bool AllEndSlash) return Ret; } -BOOL DeleteEndSlash(std::wstring &strPath, bool AllEndSlash) +bool DeleteEndSlash(std::wstring &strPath, bool AllEndSlash) { - BOOL out = FALSE; + bool out = false; while (!strPath.empty() && IsSlash(strPath.back())) { - out = TRUE; + out = true; strPath.pop_back(); if (!AllEndSlash) break; @@ -304,7 +304,7 @@ BOOL DeleteEndSlash(std::wstring &strPath, bool AllEndSlash) return out; } -BOOL DeleteEndSlash(FARString &strPath, bool AllEndSlash) +bool DeleteEndSlash(FARString &strPath, bool AllEndSlash) { size_t LenToSlash = strPath.GetLength(); @@ -315,10 +315,10 @@ BOOL DeleteEndSlash(FARString &strPath, bool AllEndSlash) } if (LenToSlash == strPath.GetLength()) - return FALSE; + return false; strPath.Truncate(LenToSlash); - return TRUE; + return true; } bool CutToSlash(FARString &strStr, bool bInclude) diff --git a/far2l/src/mix/pathmix.hpp b/far2l/src/mix/pathmix.hpp index 866786e66..71209f365 100644 --- a/far2l/src/mix/pathmix.hpp +++ b/far2l/src/mix/pathmix.hpp @@ -90,8 +90,8 @@ void AddEndSlash(std::wstring &strPath); BOOL WINAPI AddEndSlash(wchar_t *Path); bool DeleteEndSlash(wchar_t *Path, bool AllEndSlash = false); -BOOL DeleteEndSlash(std::wstring &strPath, bool AllEndSlash = false); -BOOL DeleteEndSlash(FARString &strPath, bool AllEndSlash = false); +bool DeleteEndSlash(std::wstring &strPath, bool AllEndSlash = false); +bool DeleteEndSlash(FARString &strPath, bool AllEndSlash = false); const wchar_t *FirstSlash(const wchar_t *String); const wchar_t *LastSlash(const wchar_t *String); diff --git a/far2l/src/mkdir.cpp b/far2l/src/mkdir.cpp index 56098c321..2a2a7df87 100644 --- a/far2l/src/mkdir.cpp +++ b/far2l/src/mkdir.cpp @@ -139,10 +139,10 @@ void ShellMakeDir(Panel *SrcPanel) } for (wchar_t *ChPtr = lpwszDirName; *ChPtr; ChPtr++) { if (IsSlash(*ChPtr)) { - WCHAR Ch = ChPtr[1]; + wchar_t Ch = ChPtr[1]; ChPtr[1] = 0; - if (*lpwszDirName && (apiGetFileAttributes(lpwszDirName) == INVALID_FILE_ATTRIBUTES) + if ((apiGetFileAttributes(lpwszDirName) == INVALID_FILE_ATTRIBUTES) && apiCreateDirectory(lpwszDirName, nullptr)) { TreeList::AddTreeName(lpwszDirName); bSuccess = true; @@ -165,16 +165,15 @@ void ShellMakeDir(Panel *SrcPanel) bSkip = !DirList.IsLastElement(DI); break; // Jump to directory always if it existed before creation attempt } else if (LastError == ERROR_INVALID_NAME || LastError == ERROR_DIRECTORY) { - int ret; - if (DirList.IsLastElement(DI)) - ret = Message(MSG_WARNING | MSG_ERRORTYPE, 1, Msg::Error, Msg::CannotCreateFolder, - strOriginalDirName, Msg::Cancel); + if (DirList.IsLastElement(DI)) { + Message(MSG_WARNING | MSG_ERRORTYPE, 1, Msg::Error, Msg::CannotCreateFolder, + strOriginalDirName, Msg::Ok); + bSkip = false; + } else - ret = Message(MSG_WARNING | MSG_ERRORTYPE, 2, Msg::Error, Msg::CannotCreateFolder, - strOriginalDirName, Msg::Cancel, Msg::Skip); - - bSkip = ret == 1; + bSkip = (0==Message(MSG_WARNING | MSG_ERRORTYPE, 2, Msg::Error, Msg::CannotCreateFolder, + strOriginalDirName, Msg::Skip, Msg::Cancel)); if (bSuccess || bSkip) break; diff --git a/far2l/src/panels/flshow.cpp b/far2l/src/panels/flshow.cpp index 9ae8b5c9d..3364a41d2 100644 --- a/far2l/src/panels/flshow.cpp +++ b/far2l/src/panels/flshow.cpp @@ -53,7 +53,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern PanelViewSettings ViewSettingsArray[]; extern int ColumnTypeWidth[]; -static wchar_t OutCharacter[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static wchar_t OutCharacter[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static FarLangMsg __FormatEndSelectedPhrase(int Count) { @@ -945,20 +945,25 @@ void FileList::ShowList(int ShowStatus, int StartColumn) Width-= 2; } - if (ListData[ListPos]->ColorsPtr->MarkChar && Opt.Highlight && Width > 1) { - Width--; - OutCharacter[0] = (wchar_t)(ListData[ListPos]->ColorsPtr->MarkChar & 0xffff); - const auto OldColor = GetColor(); + { // Draw mark str + const HighlightDataColor *const hl = ListData[ListPos]->ColorsPtr; + if ( Opt.Highlight && Width > 2 && hl->MarkLen ) { - if (!ShowStatus) - SetShowColor(ListPos, HIGHLIGHTCOLORTYPE_MARKCHAR); + const auto OldColor = GetColor(); + size_t ng = Width, outlen; - Text(OutCharacter); - SetColor(OldColor); + outlen = StrSizeOfCells(hl->Mark, hl->MarkLen, ng, false); + Width -= ng; + + if (!ShowStatus) + SetShowColor(ListPos, HIGHLIGHTCOLORTYPE_MARKCHAR); + + Text(hl->Mark, outlen); + SetColor(OldColor); + } } const wchar_t *NamePtr = ListData[ListPos]->strName; - const wchar_t *NameCopy = NamePtr; if (ViewFlags & COLUMN_NAMEONLY) { diff --git a/utils/src/Escaping.cpp b/utils/src/Escaping.cpp index cb9a31f47..105b90650 100644 --- a/utils/src/Escaping.cpp +++ b/utils/src/Escaping.cpp @@ -91,14 +91,14 @@ void QuoteCmdArg(std::wstring &str) { QuoteCmdArgT(str); } void QuoteCmdArgIfNeed(std::string &str) { - if (str.find_first_of(" \"\'\r\n\t&|;,()`$") != std::string::npos) { + if (str.find_first_of(" \\\"\'\r\n\t&|;,()`$") != std::string::npos) { QuoteCmdArg(str); } } void QuoteCmdArgIfNeed(std::wstring &str) { - if (str.find_first_of(L" \"\'\r\n\t&|;,()`$") != std::wstring::npos) { + if (str.find_first_of(L" \\\"\'\r\n\t&|;,()`$") != std::wstring::npos) { QuoteCmdArg(str); } }