Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2022-11-05 20:31:53 +0300
committerGitHub <noreply@github.com>2022-11-05 20:31:53 +0300
commit253a6b140797e035eb9301a1632fed2408a837e2 (patch)
treeed6be316904b5d5ff11b7bfa46e7037fc2ec51d5
parent89eaed71c674aadda536408638e3416bc7f4c053 (diff)
support full-width/composite characters and true color palette in terminal (#1386)
Added normal support for full-width (CJK etc) and composite (using diacritics) characters. IMPORTANT: WINPORT API changed in binary incompatible way in order to implement this.
-rw-r--r--README.md20
-rw-r--r--WinPort/CMakeLists.txt1
-rw-r--r--WinPort/FarTTY.h10
-rw-r--r--WinPort/WinCompat.h55
-rw-r--r--WinPort/WinPort.h7
-rw-r--r--WinPort/src/APIConsole.cpp75
-rw-r--r--WinPort/src/Backend/Backend.h8
-rw-r--r--WinPort/src/Backend/TTY/IsUnstableWidthChar.cpp415
-rw-r--r--WinPort/src/Backend/TTY/IsUnstableWidthChar_mk.cpp72
-rw-r--r--WinPort/src/Backend/TTY/TTYBackend.cpp115
-rw-r--r--WinPort/src/Backend/TTY/TTYBackend.h3
-rw-r--r--WinPort/src/Backend/TTY/TTYOutput.cpp149
-rw-r--r--WinPort/src/Backend/TTY/TTYOutput.h31
-rw-r--r--WinPort/src/Backend/WX/Paint.cpp294
-rw-r--r--WinPort/src/Backend/WX/Paint.h18
-rw-r--r--WinPort/src/Backend/WX/wxMain.cpp14
-rw-r--r--WinPort/src/Backend/WX/wxMain.h1
-rw-r--r--WinPort/src/Backend/WX/wxWinTranslations.cpp32
-rw-r--r--WinPort/src/Backend/WX/wxWinTranslations.h7
-rw-r--r--WinPort/src/ConsoleBuffer.cpp29
-rw-r--r--WinPort/src/ConsoleBuffer.h2
-rw-r--r--WinPort/src/ConsoleOutput.cpp143
-rw-r--r--WinPort/src/ConsoleOutput.h15
-rw-r--r--far2l/CMakeLists.txt1
-rw-r--r--far2l/far2sdk/farplug-mb.h23
-rw-r--r--far2l/far2sdk/farplug-wide.h21
-rw-r--r--far2l/src/Mounts.cpp12
-rw-r--r--far2l/src/ViewerPrinter.cpp50
-rw-r--r--far2l/src/base/FARString.cpp26
-rw-r--r--far2l/src/base/FARString.hpp6
-rw-r--r--far2l/src/cmdline.cpp7
-rw-r--r--far2l/src/console/AnsiEsc.cpp138
-rw-r--r--far2l/src/console/AnsiEsc.hpp19
-rw-r--r--far2l/src/console/interf.cpp44
-rw-r--r--far2l/src/console/interf.hpp4
-rw-r--r--far2l/src/copy.cpp18
-rw-r--r--far2l/src/datetime.cpp4
-rw-r--r--far2l/src/delete.cpp2
-rw-r--r--far2l/src/dialog.cpp24
-rw-r--r--far2l/src/dizlist.cpp2
-rw-r--r--far2l/src/dlgedit.cpp8
-rw-r--r--far2l/src/dlgedit.hpp4
-rw-r--r--far2l/src/edit.cpp489
-rw-r--r--far2l/src/edit.hpp25
-rw-r--r--far2l/src/editor.cpp228
-rw-r--r--far2l/src/execute.cpp2
-rw-r--r--far2l/src/execute_oscmd.cpp2
-rw-r--r--far2l/src/fileedit.cpp18
-rw-r--r--far2l/src/filetype.cpp4
-rw-r--r--far2l/src/fileview.cpp2
-rw-r--r--far2l/src/flshow.cpp180
-rw-r--r--far2l/src/foldtree.cpp2
-rw-r--r--far2l/src/headers.hpp1
-rw-r--r--far2l/src/help.cpp2
-rw-r--r--far2l/src/infolist.cpp4
-rw-r--r--far2l/src/keybar.cpp6
-rw-r--r--far2l/src/locale/codepage.cpp2
-rw-r--r--far2l/src/locale/locale.hpp6
-rw-r--r--far2l/src/message.cpp2
-rw-r--r--far2l/src/mix/StrCells.cpp159
-rw-r--r--far2l/src/mix/StrCells.h10
-rw-r--r--far2l/src/mix/format.cpp90
-rw-r--r--far2l/src/mix/format.hpp51
-rw-r--r--far2l/src/mix/panelmix.cpp8
-rw-r--r--far2l/src/mix/strmix.cpp130
-rw-r--r--far2l/src/mix/strmix.hpp2
-rw-r--r--far2l/src/plug/PluginA.cpp17
-rw-r--r--far2l/src/plug/PluginW.cpp12
-rw-r--r--far2l/src/plug/wrap.cpp8
-rw-r--r--far2l/src/qview.cpp4
-rw-r--r--far2l/src/treelist.cpp10
-rw-r--r--far2l/src/usermenu.cpp2
-rw-r--r--far2l/src/viewer.cpp27
-rw-r--r--far2l/src/viewer.hpp2
-rw-r--r--far2l/src/vmenu.cpp36
-rw-r--r--far2l/src/vt/VTFar2lExtensios.cpp13
-rw-r--r--far2l/src/vt/VTFar2lExtensios.h1
-rw-r--r--far2l/src/vt/vtansi.cpp47
-rw-r--r--far2l/src/vt/vtlog.cpp8
-rw-r--r--far2l/src/vt/vtshell.cpp33
-rw-r--r--far2l/src/vt/vtshell_leader.cpp2
-rw-r--r--utils/CMakeLists.txt2
-rw-r--r--utils/include/VT256ColorTable.h13
-rw-r--r--utils/include/utils.h17
-rw-r--r--utils/src/CharClasses.cpp464
-rw-r--r--utils/src/CharClasses_mk.cpp79
-rw-r--r--utils/src/VT256ColorTable.cpp244
87 files changed, 2653 insertions, 1742 deletions
diff --git a/README.md b/README.md
index d453e15d..b1e34c77 100644
--- a/README.md
+++ b/README.md
@@ -209,6 +209,12 @@ While FAR internally is UTF16 (because WinPort contains UTF16-related stuff), na
Inspect all printf format strings: unlike Windows, in Linux both wide and multibyte printf-like functions have the same multibyte and wide specifiers. This means that %s is always multibyte while %ls is always wide. So, any %s used in wide-printf-s or %ws used in any printf should be replaced with %ls.
Update from 27aug: now it's possible by defining WINPORT_DIRECT to avoid renaming used Windows API and also to avoid changing format strings as swprintf will be intercepted by a compatibility wrapper.
+Update from 03/11/22: far2l's console emulator capable to correctly render full-width and combining characters as well as 24 bit colors. This caused following deviation of console-simulation functions behavior comparing to original Win32 API counterparts:
+ * CHAR_INFO's Char::UnicodeChar field extended to 64 bit length to be able to associate sequence of multiple WCHARs with single cell.
+ * Writing to console full-width character causes two cells to be used: first will get given character code in UnicodeChar field but next one will have UnicodeChar set to zero.
+ * Writing combined characters - normal character followed by set of diactrical marks - will make UnicodeChar field to contain so-called 'composite' character code that represents sequence of character codes registered with WINPORT(CompositeCharRegister). Actual sequence of WCHARs can be obtained by WINPORT(CompositeCharLookup). There is macro CI_USING_COMPOSITE_CHAR that allows to detect if given CHAR_INFO contains composite character code or normal WCHAR.
+ * Both above transformations happen automatically _only_ if using WriteConsole API. If one uses WriteConsoleOutput - then its up to caller to perform that transformations. Failing to do so will cause incorrect rendering of full-width or diactrical characters.
+ * CHAR_INFO's and CONSOLE_SCREEN_BUFFER_INFO's Attributes fields extended to 64 bit to be able to hold 24 bit RGB colors in higher bytes. Use macroses GET_RGB_FORE/GET_RGB_BACK/SET_RGB_FORE/SET_RGB_BACK/SET_RGB_BOTH to access that colors. Note that such colors will be used only if FOREGROUND_TRUECOLOR/BACKGROUND_TRUECOLOR attribute is set. Old attributes define colors from usual 16-elements palette used to render if ..._TRUECOLOR is not set or if backend's target doesn't support more than 16 colors.
## Plugin API
@@ -234,6 +240,20 @@ far2l supports calling APIs from different threads by marshalling API calls from
If plugin implements tasks running in background it may invoke this function to indicate about pending task in left-top corner.
Info is a short description of task or just its owner and must be same string when invoked with Started TRUE or FALSE.
+* `size_t StrCellsCount(const wchar_t *Str, size_t CharsCount);`
+Returns count of console cells which will be used to display given string of CharsCount characters.
+
+* `size_t StrSizeOfCells(const wchar_t *Str, size_t CharsCount, size_t *CellsCount, BOOL RoundUp);`
+Returns count of characters which will be used to fill up to CellsCount cells from given string of CharsCount characters.
+RoundUp argument tells what to do with full-width characters that crossed by CellsCount.
+On return CellsCount contains cells count that will be filled by returned characters count, that:
+ Can be smaller than initial value if string has too few characters to fill all CellsCount cells or if RoundUp was set to FALSE and last character would then overflow wanted amount.
+ Can be larger by one than initial value if RoundUp was set to TRUE and last full-width character crossed initial value specified in *CellsCount.
+
+* `TruncStr and TruncPathStr`
+ This two functions not added but changed to use console cells count as string limiting factor.
+
+
### Added following commands into FILE_CONTROL_COMMANDS:
* `FCTL_GETPANELPLUGINHANDLE`
Can be used to interract with plugin that renders other panel.
diff --git a/WinPort/CMakeLists.txt b/WinPort/CMakeLists.txt
index 2467b440..62d8320b 100644
--- a/WinPort/CMakeLists.txt
+++ b/WinPort/CMakeLists.txt
@@ -36,7 +36,6 @@ src/Backend/TTY/TTYOutput.cpp
src/Backend/TTY/TTYFar2lClipboardBackend.cpp
src/Backend/TTY/TTYNegotiateFar2l.cpp
src/Backend/TTY/TTYXGlue.cpp
-src/Backend/TTY/IsUnstableWidthChar.cpp
)
add_library (WinPort ${SOURCES})
diff --git a/WinPort/FarTTY.h b/WinPort/FarTTY.h
index 261bdb73..486b53ee 100644
--- a/WinPort/FarTTY.h
+++ b/WinPort/FarTTY.h
@@ -73,6 +73,16 @@ Note that in descriptions below arguments are listed in stack top->bottom order.
*/
#define FARTTY_INTERRACT_SET_FKEY_TITLES 'f'
+/** Request color palette info
+ In:
+ N/A
+ Out:
+ uint8_t maximum count of color resolution bits supported (4, 8, 24)
+ uint8_t reserved and set to zero, client should ignore it
+*/
+#define FARTTY_INTERRACT_GET_COLOR_PALETTE 'p'
+
+
/** Declares that client supports specified extra features, so server _may_ change its hehaviour accordingly if it also supports some of them
In:
uint64_t (set of FARTTY_FEAT_* bit flags)
diff --git a/WinPort/WinCompat.h b/WinPort/WinCompat.h
index 6ea69075..17286f60 100644
--- a/WinPort/WinCompat.h
+++ b/WinPort/WinCompat.h
@@ -466,7 +466,7 @@ typedef struct _SMALL_RECT {
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition;
- WORD wAttributes;
+ DWORD64 wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO, *PCONSOLE_SCREEN_BUFFER_INFO;
@@ -476,14 +476,43 @@ typedef struct _CONSOLE_CURSOR_INFO {
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
+typedef DWORD64 COMP_CHAR;
+
typedef struct _CHAR_INFO {
union {
- WCHAR UnicodeChar;
+ // WCHAR or result of CompositeCharRegister() can be differentiated
+ // using CI_USING_COMPOSITE_CHAR() that checks presence of highest bit
+ // to change this field better use CI_SET_WCHAR/CI_SET_WCATTR/CI_SET_COMPOSITE
+ // that guards against unwanted sign extension if casting from wchar_t
+ COMP_CHAR UnicodeChar;
CHAR AsciiChar;
} Char;
- WORD Attributes;
+
+ // low 16 bits - usual attributes, followed by two 24-bit RGB colors that used
+ // if FOREGROUND_TRUECOLOR/BACKGROUND_TRUECOLOR defined and backend supports truecolor
+ DWORD64 Attributes;
} CHAR_INFO, *PCHAR_INFO;
+#define COMPOSITE_CHAR_MARK (COMP_CHAR(1) << 63)
+
+#define CI_SET_ATTR(CI, ATTR) { (CI).Attributes = (DWORD64)ATTR; }
+#define CI_SET_WCHAR(CI, WC) { (CI).Char.UnicodeChar = (COMP_CHAR)(uint32_t)(WC); }
+#define CI_SET_COMPOSITE(CI, PWC) { (CI).Char.UnicodeChar = WINPORT(CompositeCharRegister)(PWC); }
+
+#define CI_SET_WCATTR(CI, WC, ATTR) {(CI).Char.UnicodeChar = (COMP_CHAR)(uint32_t)(WC); (CI).Attributes = (DWORD64)ATTR;}
+
+#define CI_USING_COMPOSITE_CHAR(CI) ( ((CI).Char.UnicodeChar & COMPOSITE_CHAR_MARK) != 0 )
+#define CI_FULL_WIDTH_CHAR(CI) ( (!CI_USING_COMPOSITE_CHAR(CI) && IsCharFullWidth((CI).Char.UnicodeChar)) \
+ || (CI_USING_COMPOSITE_CHAR(CI) && IsCharFullWidth(*WINPORT(CompositeCharLookup)((CI).Char.UnicodeChar))))
+
+#define GET_RGB_FORE(ATTR) ((DWORD)(((ATTR) >> 16) & 0xffffff))
+#define GET_RGB_BACK(ATTR) ((DWORD)(((ATTR) >> 40) & 0xffffff))
+#define SET_RGB_FORE(ATTR, RGB) \
+ ((ATTR) = ((ATTR) & 0xffffff000000ffff) | FOREGROUND_TRUECOLOR | ((((DWORD64)(RGB)) & 0xffffff) << 16))
+#define SET_RGB_BACK(ATTR, RGB) \
+ ((ATTR) = ((ATTR) & 0x000000ffffffffff) | BACKGROUND_TRUECOLOR | ((((DWORD64)(RGB)) & 0xffffff) << 40))
+#define SET_RGB_BOTH(ATTR, RGB_FORE, RGB_BACK) \
+ ((ATTR) = ((ATTR) & 0xffff) | FOREGROUND_TRUECOLOR | BACKGROUND_TRUECOLOR | ((((DWORD64)(RGB_FORE)) & 0xffffff) << 16) | ((((DWORD64)(RGB_BACK)) & 0xffffff) << 40) )
typedef struct _WINDOW_BUFFER_SIZE_RECORD {
COORD dwSize;
@@ -578,15 +607,17 @@ typedef struct _INPUT_RECORD {
#define BACKGROUND_GREEN 0x0020 // background color contains green.
#define BACKGROUND_RED 0x0040 // background color contains red.
#define BACKGROUND_INTENSITY 0x0080 // background color is intensified.
-#define COMMON_LVB_LEADING_BYTE 0x0100 // Leading Byte of DBCS
-#define COMMON_LVB_TRAILING_BYTE 0x0200 // Trailing Byte of DBCS
-#define COMMON_LVB_GRID_HORIZONTAL 0x0400 // DBCS: Grid attribute: top horizontal.
-#define COMMON_LVB_GRID_LVERTICAL 0x0800 // DBCS: Grid attribute: left vertical.
-#define COMMON_LVB_GRID_RVERTICAL 0x1000 // DBCS: Grid attribute: right vertical.
-#define COMMON_LVB_REVERSE_VIDEO 0x4000 // DBCS: Reverse fore/back ground attribute.
-#define COMMON_LVB_UNDERSCORE 0x8000 // DBCS: Underscore.
-
-#define COMMON_LVB_SBCSDBCS 0x0300 // SBCS or DBCS flag.
+#define FOREGROUND_TRUECOLOR 0x0100 // Use 24 bit RGB colors set by SET_RGB_FORE
+#define BACKGROUND_TRUECOLOR 0x0200 // Use 24 bit RGB colors set by SET_RGB_BACK
+#define COMMON_LVB_REVERSE_VIDEO 0x4000 // Reverse fore/back ground attribute.
+#define COMMON_LVB_UNDERSCORE 0x8000 // Underscore.
+
+// Constants below not implemented and their bit values are reserved and must be zero-inited
+// #define COMMON_LVB_GRID_HORIZONTAL
+// #define COMMON_LVB_GRID_LVERTICAL
+// #define COMMON_LVB_GRID_RVERTICAL
+// #define COMMON_LVB_SBCSDBCS
+
//
diff --git a/WinPort/WinPort.h b/WinPort/WinPort.h
index 093b5156..8a7e0c9a 100644
--- a/WinPort/WinPort.h
+++ b/WinPort/WinPort.h
@@ -36,13 +36,15 @@ extern "C" {
WINPORT_DECL(GetConsoleMode,BOOL,(HANDLE hConsoleHandle,LPDWORD lpMode));
WINPORT_DECL(SetConsoleMode,BOOL,(HANDLE hConsoleHandle, DWORD dwMode));
WINPORT_DECL(ScrollConsoleScreenBuffer,BOOL,(HANDLE hConsoleOutput, const SMALL_RECT *lpScrollRectangle, const SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, const CHAR_INFO *lpFill));
- WINPORT_DECL(SetConsoleTextAttribute,BOOL,(HANDLE hConsoleOutput, WORD wAttributes));
+ WINPORT_DECL(SetConsoleTextAttribute,BOOL,(HANDLE hConsoleOutput, DWORD64 qAttributes));
+ WINPORT_DECL(CompositeCharRegister,COMP_CHAR,(const WCHAR *lpSequence));
+ WINPORT_DECL(CompositeCharLookup,const WCHAR *,(COMP_CHAR CompositeChar));
WINPORT_DECL(WriteConsole,BOOL,(HANDLE hConsoleOutput, const WCHAR *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved));
WINPORT_DECL(WriteConsoleOutput,BOOL,(HANDLE hConsoleOutput,const CHAR_INFO *lpBuffer,COORD dwBufferSize,COORD dwBufferCoord,PSMALL_RECT lpScreenRegion));
WINPORT_DECL(WriteConsoleOutputCharacter,BOOL,(HANDLE hConsoleOutput, const WCHAR *lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten));
WINPORT_DECL(WaitConsoleInput, BOOL,(DWORD dwTimeout));
WINPORT_DECL(ReadConsoleOutput, BOOL, (HANDLE hConsoleOutput, CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpScreenRegion));
- WINPORT_DECL(FillConsoleOutputAttribute, BOOL, (HANDLE hConsoleOutput, WORD wAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten));
+ WINPORT_DECL(FillConsoleOutputAttribute, BOOL, (HANDLE hConsoleOutput, DWORD64 qAttributes, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten));
WINPORT_DECL(FillConsoleOutputCharacter, BOOL, (HANDLE hConsoleOutput, WCHAR cCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten));
WINPORT_DECL(SetConsoleActiveScreenBuffer, BOOL,(HANDLE hConsoleOutput));
@@ -56,6 +58,7 @@ extern "C" {
WINPORT_DECL(SetConsoleDisplayMode,BOOL,(DWORD ModeFlags));
WINPORT_DECL(GetConsoleDisplayMode,BOOL,(LPDWORD lpModeFlags));
WINPORT_DECL(SetConsoleWindowMaximized,VOID,(BOOL Maximized));
+ WINPORT_DECL(GetConsoleColorPalette,BYTE,()); // Returns current color resolution: 4, 8, 24
//WINPORT_DECL(AddConsoleAlias, BOOL,( LPCWSTR Source, LPCWSTR Target, LPCWSTR ExeName));
WINPORT_DECL(GetConsoleAlias, DWORD,(LPWSTR lpSource, LPWSTR lpTargetBuffer, DWORD TargetBufferLength, LPWSTR lpExeName));
diff --git a/WinPort/src/APIConsole.cpp b/WinPort/src/APIConsole.cpp
index cb46698c..6bc7c1bd 100644
--- a/WinPort/src/APIConsole.cpp
+++ b/WinPort/src/APIConsole.cpp
@@ -1,4 +1,6 @@
#include <mutex>
+#include <map>
+#include <vector>
#include "WinPort.h"
#include "Backend.h"
@@ -137,9 +139,9 @@ extern "C" {
}
- WINPORT_DECL(SetConsoleTextAttribute,BOOL,(HANDLE hConsoleOutput, WORD wAttributes))
+ WINPORT_DECL(SetConsoleTextAttribute,BOOL,(HANDLE hConsoleOutput, DWORD64 qAttributes))
{
- g_winport_con_out->SetAttributes(wAttributes);
+ g_winport_con_out->SetAttributes(qAttributes);
return TRUE;
}
@@ -167,9 +169,9 @@ extern "C" {
return TRUE;
}
- WINPORT_DECL(FillConsoleOutputAttribute, BOOL, (HANDLE hConsoleOutput, WORD wAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten))
+ WINPORT_DECL(FillConsoleOutputAttribute, BOOL, (HANDLE hConsoleOutput, DWORD64 qAttributes, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten))
{
- *lpNumberOfAttrsWritten = g_winport_con_out->FillAttributeAt(wAttribute, nLength, dwWriteCoord);
+ *lpNumberOfAttrsWritten = g_winport_con_out->FillAttributeAt(qAttributes, nLength, dwWriteCoord);
return TRUE;
}
@@ -345,4 +347,69 @@ extern "C" {
{
return g_winport_con_out->SetFKeyTitles(titles) ? TRUE : FALSE;
}
+
+ WINPORT_DECL(GetConsoleColorPalette,BYTE,())
+ {
+ return g_winport_con_out->GetColorPalette();
+ }
+
+ static struct {
+ struct Cmp
+ {
+ bool operator()(const WCHAR *a, const WCHAR *b) const { return wcscmp(a, b) < 0; }
+ };
+ std::mutex mtx;
+ std::vector<WCHAR *> id2str;
+ std::map<const WCHAR *, COMP_CHAR, Cmp> str2id;
+ } s_composite_chars;
+
+ WINPORT_DECL(CompositeCharRegister,COMP_CHAR,(const WCHAR *lpSequence))
+ {
+ if (!lpSequence[0]) {
+ return 0;
+ }
+ if (!lpSequence[1]) {
+ return lpSequence[0];
+ }
+
+ std::lock_guard<std::mutex> lock(s_composite_chars.mtx);
+ auto it = s_composite_chars.str2id.find(lpSequence);
+ if (it != s_composite_chars.str2id.end()) {
+ return it->second | COMPOSITE_CHAR_MARK;
+ }
+ wchar_t *wd = wcsdup(lpSequence);
+ try {
+ if (!wd)
+ throw std::logic_error("wcsdup failed");
+
+ const COMP_CHAR id = COMP_CHAR(s_composite_chars.id2str.size());
+ s_composite_chars.id2str.emplace_back(wd);
+ s_composite_chars.str2id.emplace(wd, id);
+ return id | COMPOSITE_CHAR_MARK;
+
+ } catch (std::exception &e) {
+ fprintf(stderr, "%s: %s for '%ls'\n", __FUNCTION__, e.what(), lpSequence);
+ free(wd);
+ }
+ return 0;
+ }
+
+ WINPORT_DECL(CompositeCharLookup,const WCHAR *,(COMP_CHAR CompositeChar))
+ {
+ if ((CompositeChar & COMPOSITE_CHAR_MARK) == 0) {
+ fprintf(stderr, "%s: invoked for not composite-char 0x%llx\n",
+ __FUNCTION__, (unsigned long long)CompositeChar);
+ return L"\u2022";
+ }
+
+ const COMP_CHAR id = CompositeChar & (~COMPOSITE_CHAR_MARK);
+
+ std::lock_guard<std::mutex> lock(s_composite_chars.mtx);
+ if (id >= (COMP_CHAR)s_composite_chars.id2str.size()) {
+ fprintf(stderr, "%s: out of range composite-char 0x%llx\n",
+ __FUNCTION__, (unsigned long long)CompositeChar);
+ return L"\u2022";
+ }
+ return s_composite_chars.id2str[id];
+ }
}
diff --git a/WinPort/src/Backend/Backend.h b/WinPort/src/Backend/Backend.h
index fe0372c4..2173f4b2 100644
--- a/WinPort/src/Backend/Backend.h
+++ b/WinPort/src/Backend/Backend.h
@@ -30,6 +30,7 @@ public:
virtual void OnConsoleDisplayNotification(const wchar_t *title, const wchar_t *text) = 0;
virtual bool OnConsoleBackgroundMode(bool TryEnterBackgroundMode) = 0;
virtual bool OnConsoleSetFKeyTitles(const char **titles) = 0;
+ virtual BYTE OnConsoleGetColorPalette() = 0;
};
class IClipboardBackend
@@ -139,8 +140,8 @@ protected:
public:
virtual void SetBackend(IConsoleOutputBackend *listener) = 0;
- virtual void SetAttributes(USHORT attributes) = 0;
- virtual USHORT GetAttributes() = 0;
+ virtual void SetAttributes(DWORD64 attributes) = 0;
+ virtual DWORD64 GetAttributes() = 0;
virtual void SetCursor(COORD pos) = 0;
virtual void SetCursor(UCHAR height, bool visible) = 0;
virtual COORD GetCursor() = 0;
@@ -166,7 +167,7 @@ public:
virtual size_t WriteString(const WCHAR *data, size_t count) = 0;
virtual size_t WriteStringAt(const WCHAR *data, size_t count, COORD &pos) = 0;
virtual size_t FillCharacterAt(WCHAR cCharacter, size_t count, COORD &pos) = 0;
- virtual size_t FillAttributeAt(WORD wAttribute, size_t count, COORD &pos) = 0;
+ virtual size_t FillAttributeAt(DWORD64 qAttribute, size_t count, COORD &pos) = 0;
virtual bool Scroll(const SMALL_RECT *lpScrollRectangle, const SMALL_RECT *lpClipRectangle,
COORD dwDestinationOrigin, const CHAR_INFO *lpFill) = 0;
@@ -182,6 +183,7 @@ public:
virtual void ConsoleDisplayNotification(const WCHAR *title, const WCHAR *text) = 0;
virtual bool ConsoleBackgroundMode(bool TryEnterBackgroundMode) = 0;
virtual bool SetFKeyTitles(const CHAR **titles) = 0;
+ virtual BYTE GetColorPalette() = 0;
inline std::wstring GetTitle()
{
diff --git a/WinPort/src/Backend/TTY/IsUnstableWidthChar.cpp b/WinPort/src/Backend/TTY/IsUnstableWidthChar.cpp
deleted file mode 100644
index 636266c3..00000000
--- a/WinPort/src/Backend/TTY/IsUnstableWidthChar.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-// this file autogenerated by IsUnstableWidthChar_mk.cpp
-
-#include <wchar.h>
-
-bool IsUnstableWidthChar(wchar_t c)
-{
- return (c >= 0x300 && c <= 0x36f)
- || (c >= 0x483 && c <= 0x487)
- || (c >= 0x591 && c <= 0x5bd)
- || (c == 0x5bf)
- || (c == 0x5c1 || c == 0x5c2)
- || (c == 0x5c4 || c == 0x5c5)
- || (c == 0x5c7)
- || (c >= 0x610 && c <= 0x61a)
- || (c == 0x620)
- || (c >= 0x622 && c <= 0x65f)
- || (c >= 0x66e && c <= 0x673)
- || (c >= 0x675 && c <= 0x6d3)
- || (c >= 0x6d5 && c <= 0x6dc)
- || (c >= 0x6df && c <= 0x6e4)
- || (c == 0x6e7 || c == 0x6e8)
- || (c >= 0x6ea && c <= 0x6ef)
- || (c >= 0x6fa && c <= 0x6fc)
- || (c == 0x6ff)
- || (c >= 0x710 && c <= 0x74a)
- || (c >= 0x74d && c <= 0x77f)
- || (c >= 0x7a6 && c <= 0x7b0)
- || (c >= 0x7ca && c <= 0x7f3)
- || (c == 0x7fa)
- || (c == 0x7fd)
- || (c >= 0x816 && c <= 0x819)
- || (c >= 0x81b && c <= 0x823)
- || (c >= 0x825 && c <= 0x827)
- || (c >= 0x829 && c <= 0x82d)
- || (c >= 0x840 && c <= 0x85b)
- || (c == 0x860)
- || (c >= 0x862 && c <= 0x865)
- || (c >= 0x867 && c <= 0x86a)
- || (c >= 0x8a0 && c <= 0x8ac)
- || (c >= 0x8ae && c <= 0x8b4)
- || (c >= 0x8b6 && c <= 0x8c7)
- || (c >= 0x8d3 && c <= 0x8e1)
- || (c >= 0x8e3 && c <= 0x903)
- || (c >= 0x93a && c <= 0x93c)
- || (c >= 0x93e && c <= 0x94f)
- || (c >= 0x951 && c <= 0x957)
- || (c == 0x962 || c == 0x963)
- || (c >= 0x981 && c <= 0x983)
- || (c == 0x9bc)
- || (c >= 0x9be && c <= 0x9c4)
- || (c == 0x9c7 || c == 0x9c8)
- || (c >= 0x9cb && c <= 0x9cd)
- || (c == 0x9d7)
- || (c == 0x9e2 || c == 0x9e3)
- || (c == 0x9fe)
- || (c >= 0xa01 && c <= 0xa03)
- || (c == 0xa3c)
- || (c >= 0xa3e && c <= 0xa42)
- || (c == 0xa47 || c == 0xa48)
- || (c >= 0xa4b && c <= 0xa4d)
- || (c == 0xa51)
- || (c == 0xa70 || c == 0xa71)
- || (c == 0xa75)
- || (c >= 0xa81 && c <= 0xa83)
- || (c == 0xabc)
- || (c >= 0xabe && c <= 0xac5)
- || (c >= 0xac7 && c <= 0xac9)
- || (c >= 0xacb && c <= 0xacd)
- || (c == 0xae2 || c == 0xae3)
- || (c >= 0xafa && c <= 0xaff)
- || (c >= 0xb01 && c <= 0xb03)
- || (c == 0xb3c)
- || (c >= 0xb3e && c <= 0xb44)
- || (c == 0xb47 || c == 0xb48)
- || (c >= 0xb4b && c <= 0xb4d)
- || (c >= 0xb55 && c <= 0xb57)
- || (c == 0xb62 || c == 0xb63)
- || (c == 0xb82)
- || (c >= 0xbbe && c <= 0xbc2)
- || (c >= 0xbc6 && c <= 0xbc8)
- || (c >= 0xbca && c <= 0xbcd)
- || (c == 0xbd7)
- || (c >= 0xc00 && c <= 0xc04)
- || (c >= 0xc3e && c <= 0xc44)
- || (c >= 0xc46 && c <= 0xc48)
- || (c >= 0xc4a && c <= 0xc4d)
- || (c == 0xc55 || c == 0xc56)
- || (c == 0xc62 || c == 0xc63)
- || (c >= 0xc81 && c <= 0xc83)
- || (c == 0xcbc)
- || (c >= 0xcbe && c <= 0xcc4)
- || (c >= 0xcc6 && c <= 0xcc8)
- || (c >= 0xcca && c <= 0xccd)
- || (c == 0xcd5 || c == 0xcd6)
- || (c == 0xce2 || c == 0xce3)
- || (c >= 0xd00 && c <= 0xd03)
- || (c == 0xd3b || c == 0xd3c)
- || (c >= 0xd3e && c <= 0xd44)
- || (c >= 0xd46 && c <= 0xd48)
- || (c >= 0xd4a && c <= 0xd4d)
- || (c == 0xd57)
- || (c == 0xd62 || c == 0xd63)
- || (c >= 0xd81 && c <= 0xd83)
- || (c == 0xdca)
- || (c >= 0xdcf && c <= 0xdd4)
- || (c == 0xdd6)
- || (c >= 0xdd8 && c <= 0xddf)
- || (c == 0xdf2 || c == 0xdf3)
- || (c == 0xe31)
- || (c >= 0xe34 && c <= 0xe3a)
- || (c >= 0xe47 && c <= 0xe4e)
- || (c == 0xeb1)
- || (c >= 0xeb4 && c <= 0xebc)
- || (c >= 0xec8 && c <= 0xecd)
- || (c == 0xf18 || c == 0xf19)
- || (c == 0xf35)
- || (c == 0xf37)
- || (c == 0xf39)
- || (c == 0xf3e || c == 0xf3f)
- || (c >= 0xf71 && c <= 0xf84)
- || (c == 0xf86 || c == 0xf87)
- || (c >= 0xf8d && c <= 0xf97)
- || (c >= 0xf99 && c <= 0xfbc)
- || (c == 0xfc6)
- || (c >= 0x102b && c <= 0x103e)
- || (c >= 0x1056 && c <= 0x1059)
- || (c >= 0x105e && c <= 0x1060)
- || (c >= 0x1062 && c <= 0x1064)
- || (c >= 0x1067 && c <= 0x106d)
- || (c >= 0x1071 && c <= 0x1074)
- || (c >= 0x1082 && c <= 0x108d)
- || (c == 0x108f)
- || (c >= 0x109a && c <= 0x109d)
- || (c >= 0x1100 && c <= 0x115f)
- || (c >= 0x135d && c <= 0x135f)
- || (c >= 0x1712 && c <= 0x1714)
- || (c >= 0x1732 && c <= 0x1734)
- || (c == 0x1752 || c == 0x1753)
- || (c == 0x1772 || c == 0x1773)
- || (c >= 0x17b4 && c <= 0x17d3)
- || (c == 0x17dd)
- || (c == 0x1807)
- || (c >= 0x180a && c <= 0x180d)
- || (c >= 0x1820 && c <= 0x1878)
- || (c >= 0x1885 && c <= 0x18aa)
- || (c >= 0x1920 && c <= 0x192b)
- || (c >= 0x1930 && c <= 0x193b)
- || (c >= 0x1a17 && c <= 0x1a1b)
- || (c >= 0x1a55 && c <= 0x1a5e)
- || (c >= 0x1a60 && c <= 0x1a7c)
- || (c == 0x1a7f)
- || (c >= 0x1ab0 && c <= 0x1b04)
- || (c >= 0x1b34 && c <= 0x1b44)
- || (c >= 0x1b6b && c <= 0x1b73)
- || (c >= 0x1b80 && c <= 0x1b82)
- || (c >= 0x1ba1 && c <= 0x1bad)
- || (c >= 0x1be6 && c <= 0x1bf3)
- || (c >= 0x1c24 && c <= 0x1c37)
- || (c >= 0x1cd0 && c <= 0x1cd2)
- || (c >= 0x1cd4 && c <= 0x1ce8)
- || (c == 0x1ced)
- || (c == 0x1cf4)
- || (c >= 0x1cf7 && c <= 0x1cf9)
- || (c >= 0x1dc0 && c <= 0x1dff)
- || (c == 0x200d)
- || (c >= 0x20d0 && c <= 0x20ff)
- || (c >= 0x2190 && c <= 0x243f)
- || (c >= 0x25a0 && c <= 0x26ff)
- || (c == 0x2705)
- || (c == 0x270a || c == 0x270b)
- || (c == 0x2728)
- || (c == 0x274c)
- || (c == 0x274e)
- || (c >= 0x2753 && c <= 0x2755)
- || (c == 0x2757)
- || (c >= 0x2795 && c <= 0x2797)
- || (c == 0x27b0)
- || (c == 0x27bf)
- || (c == 0x2b1b || c == 0x2b1c)
- || (c == 0x2b50)
- || (c == 0x2b55)
- || (c >= 0x2cef && c <= 0x2cf1)
- || (c == 0x2d7f)
- || (c >= 0x2de0 && c <= 0x2dff)
- || (c >= 0x2e80 && c <= 0x2e99)
- || (c >= 0x2e9b && c <= 0x2ef3)
- || (c >= 0x2f00 && c <= 0x2fd5)
- || (c >= 0x2ff0 && c <= 0x2ffb)
- || (c >= 0x3000 && c <= 0x303e)
- || (c >= 0x3041 && c <= 0x3096)
- || (c >= 0x3099 && c <= 0x30ff)
- || (c >= 0x3105 && c <= 0x312f)
- || (c >= 0x3131 && c <= 0x318e)
- || (c >= 0x3190 && c <= 0x31e3)
- || (c >= 0x31f0 && c <= 0x321e)
- || (c >= 0x3220 && c <= 0x3247)
- || (c >= 0x3250 && c <= 0x4dbf)
- || (c >= 0x4e00 && c <= 0xa48c)
- || (c >= 0xa490 && c <= 0xa4c6)
- || (c == 0xa66f)
- || (c >= 0xa674 && c <= 0xa67d)
- || (c == 0xa69e || c == 0xa69f)
- || (c == 0xa6f0 || c == 0xa6f1)
- || (c == 0xa802)
- || (c == 0xa806)
- || (c == 0xa80b)
- || (c >= 0xa823 && c <= 0xa827)
- || (c == 0xa82c)
- || (c >= 0xa840 && c <= 0xa872)
- || (c == 0xa880 || c == 0xa881)
- || (c >= 0xa8b4 && c <= 0xa8c5)
- || (c >= 0xa8e0 && c <= 0xa8f1)
- || (c == 0xa8ff)
- || (c >= 0xa926 && c <= 0xa92d)
- || (c >= 0xa947 && c <= 0xa953)
- || (c >= 0xa960 && c <= 0xa97c)
- || (c >= 0xa980 && c <= 0xa983)
- || (c >= 0xa9b3 && c <= 0xa9c0)
- || (c == 0xa9e5)
- || (c >= 0xaa29 && c <= 0xaa36)
- || (c == 0xaa43)
- || (c == 0xaa4c || c == 0xaa4d)
- || (c >= 0xaa7b && c <= 0xaa7d)
- || (c == 0xaab0)
- || (c >= 0xaab2 && c <= 0xaab4)
- || (c == 0xaab7 || c == 0xaab8)
- || (c == 0xaabe || c == 0xaabf)
- || (c == 0xaac1)
- || (c >= 0xaaeb && c <= 0xaaef)
- || (c == 0xaaf5 || c == 0xaaf6)
- || (c >= 0xabe3 && c <= 0xabea)
- || (c == 0xabec || c == 0xabed)
- || (c >= 0xac00 && c <= 0xd7a3)
- || (c >= 0xd800 && c <= 0xdfff)
- || (c >= 0xf900 && c <= 0xfaff)
- || (c == 0xfb1e)
- || (c >= 0xfe00 && c <= 0xfe19)
- || (c >= 0xfe20 && c <= 0xfe52)
- || (c >= 0xfe54 && c <= 0xfe66)
- || (c >= 0xfe68 && c <= 0xfe6b)
- || (c >= 0xff01 && c <= 0xff60)
- || (c >= 0xffe0 && c <= 0xffe6)
- || (c == 0x101fd)
- || (c == 0x102e0)
- || (c >= 0x10376 && c <= 0x1037a)
- || (c >= 0x10a01 && c <= 0x10a03)
- || (c == 0x10a05 || c == 0x10a06)
- || (c >= 0x10a0c && c <= 0x10a0f)
- || (c >= 0x10a38 && c <= 0x10a3a)
- || (c == 0x10a3f)
- || (c >= 0x10ac0 && c <= 0x10ac5)
- || (c == 0x10ac7)
- || (c == 0x10ac9 || c == 0x10aca)
- || (c >= 0x10acd && c <= 0x10ae1)
- || (c >= 0x10ae4 && c <= 0x10ae6)
- || (c >= 0x10aeb && c <= 0x10aef)
- || (c >= 0x10b80 && c <= 0x10b91)
- || (c >= 0x10ba9 && c <= 0x10bae)
- || (c >= 0x10d00 && c <= 0x10d27)
- || (c == 0x10eab || c == 0x10eac)
- || (c >= 0x10f30 && c <= 0x10f44)
- || (c >= 0x10f46 && c <= 0x10f54)
- || (c == 0x10fb0)
- || (c >= 0x10fb2 && c <= 0x10fb6)
- || (c >= 0x10fb8 && c <= 0x10fbf)
- || (c >= 0x10fc1 && c <= 0x10fc4)
- || (c >= 0x10fc9 && c <= 0x10fcb)
- || (c >= 0x11000 && c <= 0x11002)
- || (c >= 0x11038 && c <= 0x11046)
- || (c >= 0x1107f && c <= 0x11082)
- || (c >= 0x110b0 && c <= 0x110ba)
- || (c >= 0x11100 && c <= 0x11102)
- || (c >= 0x11127 && c <= 0x11134)
- || (c == 0x11145 || c == 0x11146)
- || (c == 0x11173)
- || (c >= 0x11180 && c <= 0x11182)
- || (c >= 0x111b3 && c <= 0x111c0)
- || (c >= 0x111c9 && c <= 0x111cc)
- || (c == 0x111ce || c == 0x111cf)
- || (c >= 0x1122c && c <= 0x11237)
- || (c == 0x1123e)
- || (c >= 0x112df && c <= 0x112ea)
- || (c >= 0x11300 && c <= 0x11303)
- || (c == 0x1133b || c == 0x1133c)
- || (c >= 0x1133e && c <= 0x11344)
- || (c == 0x11347 || c == 0x11348)
- || (c >= 0x1134b && c <= 0x1134d)
- || (c == 0x11357)
- || (c == 0x11362 || c == 0x11363)
- || (c >= 0x11366 && c <= 0x1136c)
- || (c >= 0x11370 && c <= 0x11374)
- || (c >= 0x11435 && c <= 0x11446)
- || (c == 0x1145e)
- || (c >= 0x114b0 && c <= 0x114c3)
- || (c >= 0x115af && c <= 0x115b5)
- || (c >= 0x115b8 && c <= 0x115c0)
- || (c == 0x115dc || c == 0x115dd)
- || (c >= 0x11630 && c <= 0x11640)
- || (c >= 0x116ab && c <= 0x116b7)
- || (c >= 0x1171d && c <= 0x1172b)
- || (c >= 0x1182c && c <= 0x1183a)
- || (c >= 0x11930 && c <= 0x11935)
- || (c == 0x11937 || c == 0x11938)
- || (c >= 0x1193b && c <= 0x1193e)
- || (c == 0x11940)
- || (c == 0x11942 || c == 0x11943)
- || (c >= 0x119d1 && c <= 0x119d7)
- || (c >= 0x119da && c <= 0x119e0)
- || (c == 0x119e4)
- || (c >= 0x11a01 && c <= 0x11a0a)
- || (c >= 0x11a33 && c <= 0x11a39)
- || (c >= 0x11a3b && c <= 0x11a3e)
- || (c == 0x11a47)
- || (c >= 0x11a51 && c <= 0x11a5b)
- || (c >= 0x11a8a && c <= 0x11a99)
- || (c >= 0x11c2f && c <= 0x11c36)
- || (c >= 0x11c38 && c <= 0x11c3f)
- || (c >= 0x11c92 && c <= 0x11ca7)
- || (c >= 0x11ca9 && c <= 0x11cb6)
- || (c >= 0x11d31 && c <= 0x11d36)
- || (c == 0x11d3a)
- || (c == 0x11d3c || c == 0x11d3d)
- || (c >= 0x11d3f && c <= 0x11d45)
- || (c == 0x11d47)
- || (c >= 0x11d8a && c <= 0x11d8e)
- || (c == 0x11d90 || c == 0x11d91)
- || (c >= 0x11d93 && c <= 0x11d97)
- || (c >= 0x11ef3 && c <= 0x11ef6)
- || (c >= 0x16af0 && c <= 0x16af4)
- || (c >= 0x16b30 && c <= 0x16b36)
- || (c == 0x16f4f)
- || (c >= 0x16f51 && c <= 0x16f87)
- || (c >= 0x16f8f && c <= 0x16f92)
- || (c >= 0x16fe0 && c <= 0x16fe4)
- || (c == 0x16ff0 || c == 0x16ff1)
- || (c >= 0x17000 && c <= 0x187f7)
- || (c >= 0x18800 && c <= 0x18cd5)
- || (c >= 0x18d00 && c <= 0x18d08)
- || (c >= 0x1b000 && c <= 0x1b11e)
- || (c >= 0x1b150 && c <= 0x1b152)
- || (c >= 0x1b164 && c <= 0x1b167)
- || (c >= 0x1b170 && c <= 0x1b2fb)
- || (c == 0x1bc9d || c == 0x1bc9e)
- || (c >= 0x1d165 && c <= 0x1d169)
- || (c >= 0x1d16d && c <= 0x1d172)
- || (c >= 0x1d17b && c <= 0x1d182)
- || (c >= 0x1d185 && c <= 0x1d18b)
- || (c >= 0x1d1aa && c <= 0x1d1ad)
- || (c >= 0x1d242 && c <= 0x1d244)
- || (c >= 0x1da00 && c <= 0x1da36)
- || (c >= 0x1da3b && c <= 0x1da6c)
- || (c == 0x1da75)
- || (c == 0x1da84)
- || (c >= 0x1da9b && c <= 0x1da9f)
- || (c >= 0x1daa1 && c <= 0x1daaf)
- || (c >= 0x1e000 && c <= 0x1e006)
- || (c >= 0x1e008 && c <= 0x1e018)
- || (c >= 0x1e01b && c <= 0x1e021)
- || (c == 0x1e023 || c == 0x1e024)
- || (c >= 0x1e026 && c <= 0x1e02a)
- || (c >= 0x1e130 && c <= 0x1e136)
- || (c >= 0x1e2ec && c <= 0x1e2ef)
- || (c >= 0x1e8d0 && c <= 0x1e8d6)
- || (c >= 0x1e900 && c <= 0x1e94a)
- || (c == 0x1f004)
- || (c == 0x1f0cf)
- || (c == 0x1f18e)
- || (c >= 0x1f191 && c <= 0x1f19a)
- || (c >= 0x1f200 && c <= 0x1f202)
- || (c >= 0x1f210 && c <= 0x1f23b)
- || (c >= 0x1f240 && c <= 0x1f248)
- || (c == 0x1f250 || c == 0x1f251)
- || (c >= 0x1f260 && c <= 0x1f265)
- || (c >= 0x1f300 && c <= 0x1f320)
- || (c >= 0x1f32d && c <= 0x1f335)
- || (c >= 0x1f337 && c <= 0x1f37c)
- || (c >= 0x1f37e && c <= 0x1f393)
- || (c >= 0x1f3a0 && c <= 0x1f3ca)
- || (c >= 0x1f3cf && c <= 0x1f3d3)
- || (c >= 0x1f3e0 && c <= 0x1f3f0)
- || (c == 0x1f3f4)
- || (c >= 0x1f3f8 && c <= 0x1f43e)
- || (c == 0x1f440)
- || (c >= 0x1f442 && c <= 0x1f4fc)
- || (c >= 0x1f4ff && c <= 0x1f53d)
- || (c >= 0x1f54b && c <= 0x1f54e)
- || (c >= 0x1f550 && c <= 0x1f567)
- || (c == 0x1f57a)
- || (c == 0x1f595 || c == 0x1f596)
- || (c == 0x1f5a4)
- || (c >= 0x1f5fb && c <= 0x1f64f)
- || (c >= 0x1f680 && c <= 0x1f6c5)
- || (c == 0x1f6cc)
- || (c >= 0x1f6d0 && c <= 0x1f6d2)
- || (c >= 0x1f6d5 && c <= 0x1f6d7)
- || (c == 0x1f6eb || c == 0x1f6ec)
- || (c >= 0x1f6f4 && c <= 0x1f6fc)
- || (c >= 0x1f7e0 && c <= 0x1f7eb)
- || (c >= 0x1f90c && c <= 0x1f93a)
- || (c >= 0x1f93c && c <= 0x1f945)
- || (c >= 0x1f947 && c <= 0x1f978)
- || (c >= 0x1f97a && c <= 0x1f9cb)
- || (c >= 0x1f9cd && c <= 0x1f9ff)
- || (c >= 0x1fa70 && c <= 0x1fa74)
- || (c >= 0x1fa78 && c <= 0x1fa7a)
- || (c >= 0x1fa80 && c <= 0x1fa86)
- || (c >= 0x1fa90 && c <= 0x1faa8)
- || (c >= 0x1fab0 && c <= 0x1fab6)
- || (c >= 0x1fac0 && c <= 0x1fac2)
- || (c >= 0x1fad0 && c <= 0x1fad6)
- || (c >= 0x20000 && c <= 0x2fffd)
- || (c >= 0x30000 && c <= 0x3fffd)
- || (c >= 0xe0100 && c <= 0xe01ef)
- ;
-}
diff --git a/WinPort/src/Backend/TTY/IsUnstableWidthChar_mk.cpp b/WinPort/src/Backend/TTY/IsUnstableWidthChar_mk.cpp
deleted file mode 100644
index e5684611..00000000
--- a/WinPort/src/Backend/TTY/IsUnstableWidthChar_mk.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "unicode/uchar.h"
-#include "unicode/utypes.h"
-#include "unicode/stringoptions.h"
-#include "stdio.h"
-
-/// Usage:
-/// g++ -O2 ./IsUnstableWidthChar_mk.cpp -o /tmp/IsUnstableWidthChar_mk -licuuc && /tmp/IsUnstableWidthChar_mk > IsUnstableWidthChar.cpp
-
-static bool IsUnstableWidthBlock(int block)
-{
- return block == UBLOCK_ARROWS
- || block == UBLOCK_MATHEMATICAL_OPERATORS
- || block == UBLOCK_MISCELLANEOUS_TECHNICAL
- || block == UBLOCK_CONTROL_PICTURES
- || block == UBLOCK_GEOMETRIC_SHAPES
- || block == UBLOCK_MISCELLANEOUS_SYMBOLS
- || block == UBLOCK_COMBINING_DIACRITICAL_MARKS
- || block == UBLOCK_COMBINING_MARKS_FOR_SYMBOLS
- || block == UBLOCK_COMBINING_HALF_MARKS
- || block == UBLOCK_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT
- || block == UBLOCK_COMBINING_DIACRITICAL_MARKS_EXTENDED
- ;
-}
-
-int main()
-{
-// printf("%u\n", u_getIntPropertyValue(0xcbe, UCHAR_GENERAL_CATEGORY));
-// return -1;
- UChar32 c, last = 0x10ffff;
- UChar32 unstable_start = 0;
- bool first = true;
- printf("// this file autogenerated by IsUnstableWidthChar_mk.cpp\n\n");
- printf("#include <wchar.h>\n\n");
- printf("bool IsUnstableWidthChar(wchar_t c)\n");
- printf("{\n");
- printf("\treturn ");
- for (c = 1; c <= last + 1; ++c) {
- bool unstable = false;
- if (c <= last) {
- const auto width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
- const auto jt = u_getIntPropertyValue(c, UCHAR_JOINING_TYPE);
- const auto cat = u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY);
- unstable = (width == U_EA_FULLWIDTH || width == U_EA_WIDE
- || (jt != U_JT_NON_JOINING && jt != U_JT_TRANSPARENT)
- || cat == U_NON_SPACING_MARK || cat == U_COMBINING_SPACING_MARK || cat == U_SURROGATE
- || IsUnstableWidthBlock(u_getIntPropertyValue(c, UCHAR_BLOCK)));
- }
-
- if (unstable) {
- if (!unstable_start) {
- unstable_start = c;
- }
-
- } else if (unstable_start) {
- if (first) {
- first = false;
- } else {
- printf("\t || ");
- }
- if (unstable_start + 2 == c) {
- printf("(c == 0x%x || c == 0x%x)\n", (unsigned int)unstable_start, (unsigned int)c - 1);
- } else if (unstable_start + 1 < c) {
- printf("(c >= 0x%x && c <= 0x%x)\n", (unsigned int)unstable_start, (unsigned int)c - 1);
- } else {
- printf("(c == 0x%x)\n", (unsigned int)unstable_start);
- }
- unstable_start = 0;
- }
- }
- printf("\t;\n");
- printf("}\n");
-}
diff --git a/WinPort/src/Backend/TTY/TTYBackend.cpp b/WinPort/src/Backend/TTY/TTYBackend.cpp
index 7c893d83..7271daa1 100644
--- a/WinPort/src/Backend/TTY/TTYBackend.cpp
+++ b/WinPort/src/Backend/TTY/TTYBackend.cpp
@@ -28,8 +28,6 @@
#include "FarTTY.h"
#include "../FSClipboardBackend.h"
-bool IsUnstableWidthChar(wchar_t c);
-
static volatile long s_terminal_size_change_id = 0;
static TTYBackend * g_vtb = nullptr;
@@ -382,18 +380,6 @@ void TTYBackend::DispatchTermResized(TTYOutput &tty_out)
}
}
-bool TTYBackend::IsUnstableWidthCharCached(wchar_t c)
-{
- const size_t h = size_t(c) % ARRAYSIZE(_stable_width_chars_cache);
- if (_stable_width_chars_cache[h] != c) {
- if (IsUnstableWidthChar(c)) {
- return true;
- }
- _stable_width_chars_cache[h] = c;
- }
- return false;
-}
-
//#define LOG_OUTPUT_COUNT
void TTYBackend::DispatchOutput(TTYOutput &tty_out)
{
@@ -404,7 +390,7 @@ void TTYBackend::DispatchOutput(TTYOutput &tty_out)
SMALL_RECT screen_rect = {0, 0, CheckedCast<SHORT>(_cur_width - 1), CheckedCast<SHORT>(_cur_height - 1)};
g_winport_con_out->Read(&_cur_output[0], data_size, data_pos, screen_rect);
#ifdef LOG_OUTPUT_COUNT
- unsigned long printed_count = 0, printed_skipable = 0, forced_by_unstable = 0;
+ unsigned long printed_count = 0, printed_skipable = 0;
#endif
if (_cur_output.empty()) {
;
@@ -422,6 +408,9 @@ void TTYBackend::DispatchOutput(TTYOutput &tty_out)
const auto ApproxWeight = [&](unsigned int x_)
{
+ if (CI_USING_COMPOSITE_CHAR(cur_line[x_])) {
+ return 4;
+ }
return ((cur_line[x_].Char.UnicodeChar > 0x7f) ? 2 : 1);
};
@@ -431,66 +420,6 @@ void TTYBackend::DispatchOutput(TTYOutput &tty_out)
|| cur_line[x_].Attributes != prev_line[x_].Attributes);
};
- const auto WriteLineDebugColored = [&](const CHAR_INFO *line, unsigned int cnt, WORD attrs)
- {
-#if 0 // change to 1 to see affected lines as yellow/green on black
- std::vector<CHAR_INFO> tmp_line(cnt);
- for (unsigned int i = 0; i < cnt; ++i) {
- tmp_line[i].Char.UnicodeChar = line[i].Char.UnicodeChar;
- tmp_line[i].Attributes = attrs;
- }
- tty_out.WriteLine(tmp_line.data(), cnt);
-#else
- tty_out.WriteLine(line, cnt);
-#endif
- };
-
-
-
- if (!_far2l_tty) {
- // If some characters at line 'special' - like fullwidth or diacric then need
- // to write whole line til the end to avoid artifacts on non-far2l terminals.
- bool unstable_cur = false, unstable_prev = false, modified = false;
- for (unsigned int x = 0; x < _cur_width; ++x) {
- if (x + 1 < _cur_width) {
- if (IsUnstableWidthCharCached(cur_line[x].Char.UnicodeChar)) {
- unstable_cur = true;
- }
- if (IsUnstableWidthCharCached(prev_line[x].Char.UnicodeChar)) {
- unstable_prev = true;
- }
- }
- if (Modified(x)) {
- modified = true;
- }
- }
- if (!modified) {
- continue;
- }
- if (unstable_cur) {
- bool prev_simple = false;
- for (unsigned int chunk_x = 0, x = 0; x <= _cur_width; ++x) {
- const bool cur_simple = (x < _cur_width)
- && (WCHAR_IS_PSEUDOGRAPHIC(cur_line[x].Char.UnicodeChar) || cur_line[x].Char.UnicodeChar < 0x7f)
- && (WCHAR_IS_PSEUDOGRAPHIC(prev_line[x].Char.UnicodeChar) || prev_line[x].Char.UnicodeChar < 0x7f);
- if (cur_simple != prev_simple || x == _cur_width) {
- tty_out.MoveCursorStrict(y + 1, chunk_x + 1);
- WriteLineDebugColored(&cur_line[chunk_x], (x - chunk_x), prev_simple
- ? FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
- : FOREGROUND_RED | FOREGROUND_INTENSITY);
- prev_simple = cur_simple;
- chunk_x = x;
- }
- }
- continue;
- }
- if (unstable_prev) {
- tty_out.MoveCursorStrict(y + 1, 1);
- WriteLineDebugColored(cur_line, _cur_width, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
- continue;
- }
- }
-
for (unsigned int x = 0, skipped_start = 0, skipped_weight = 0; x < _cur_width; ++x) {
if (!Modified(x)) {
skipped_weight+= ApproxWeight(x);
@@ -525,9 +454,9 @@ void TTYBackend::DispatchOutput(TTYOutput &tty_out)
}
}
#ifdef LOG_OUTPUT_COUNT
- fprintf(stderr, "!!! OUTPUT_COUNT: (normal=%lu + skipable=%lu + unstable=%lu) = %lu of %lu\n",
- printed_count, printed_skipable, forced_by_unstable,
- printed_count + printed_skipable + forced_by_unstable,
+ fprintf(stderr, "!!! OUTPUT_COUNT: (normal=%lu + skipable=%lu) = %lu of %lu\n",
+ printed_count, printed_skipable,
+ printed_count + printed_skipable,
(unsigned long)_cur_output.size());
#endif
_prev_width = _cur_width;
@@ -677,6 +606,36 @@ bool TTYBackend::OnConsoleSetFKeyTitles(const char **titles)
return (_fkeys_support == FKS_SUPPORTED);
}
+BYTE TTYBackend::OnConsoleGetColorPalette()
+{
+ if (_far2l_tty) try {
+ StackSerializer stk_ser;
+ stk_ser.PushPOD(FARTTY_INTERRACT_GET_COLOR_PALETTE);
+ Far2lInterract(stk_ser, true);
+ uint8_t bits, reserved;
+ stk_ser.PopPOD(bits);
+ stk_ser.PopPOD(reserved);
+ return bits;
+
+ } catch (std::exception &) {
+ return 4;
+ }
+
+ static BYTE s_out = []() {
+ const char *env = getenv("COLORTERM");
+ if (env) {
+ return (strcmp(env, "truecolor") == 0 || strcmp(env, "24bit") == 0) ? 24 : 8;
+ }
+ env = getenv("TERM");
+ if (env && strstr(env, "256") != nullptr) {
+ return 8;
+ }
+ return 4;
+ } ();
+
+ return s_out;
+}
+
void TTYBackend::OnConsoleAdhocQuickEdit()
{
try {
diff --git a/WinPort/src/Backend/TTY/TTYBackend.h b/WinPort/src/Backend/TTY/TTYBackend.h
index e8918e6b..79a29bf6 100644
--- a/WinPort/src/Backend/TTY/TTYBackend.h
+++ b/WinPort/src/Backend/TTY/TTYBackend.h
@@ -19,7 +19,6 @@ class TTYBackend : IConsoleOutputBackend, ITTYInputSpecialSequenceHandler, IFar2
int _stdin = 0, _stdout = 1;
const char *_nodetect = "";
bool _far2l_tty = false;
- wchar_t _stable_width_chars_cache[0x200]{};
enum {
@@ -87,7 +86,6 @@ class TTYBackend : IConsoleOutputBackend, ITTYInputSpecialSequenceHandler, IFar2
ClipboardBackendSetter _clipboard_backend_setter;
- bool IsUnstableWidthCharCached(wchar_t c);
void WriteLineDebugColored(TTYOutput &tty_out, const CHAR_INFO *line, unsigned int cnt, WORD attrs);
void DispatchTermResized(TTYOutput &tty_out);
@@ -115,6 +113,7 @@ protected:
virtual void OnConsoleDisplayNotification(const wchar_t *title, const wchar_t *text);
virtual bool OnConsoleBackgroundMode(bool TryEnterBackgroundMode);
virtual bool OnConsoleSetFKeyTitles(const char **titles);
+ virtual BYTE OnConsoleGetColorPalette();
// ITTYInputSpecialSequenceHandler
virtual void OnInspectKeyEvent(KEY_EVENT_RECORD &event);
diff --git a/WinPort/src/Backend/TTY/TTYOutput.cpp b/WinPort/src/Backend/TTY/TTYOutput.cpp
index 23b883d7..8f8ca44b 100644
--- a/WinPort/src/Backend/TTY/TTYOutput.cpp
+++ b/WinPort/src/Backend/TTY/TTYOutput.cpp
@@ -12,32 +12,107 @@
# include <sys/kbio.h>
#endif
#include <os_call.hpp>
+#include <VT256ColorTable.h>
#include "TTYOutput.h"
#include "FarTTY.h"
#include "WideMB.h"
+#include "WinPort.h"
#define ESC "\x1b"
-TTYOutput::Attributes::Attributes(WORD attributes) :
- foreground_intensive( (attributes & FOREGROUND_INTENSITY) != 0),
- background_intensive( (attributes & BACKGROUND_INTENSITY) != 0),
- foreground(0), background(0)
-{
- if (attributes&FOREGROUND_RED) foreground|= 1;
- if (attributes&FOREGROUND_GREEN) foreground|= 2;
- if (attributes&FOREGROUND_BLUE) foreground|= 4;
+#define ATTRIBUTES_AFFECTING_BACKGROUND \
+ (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY \
+ | BACKGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO | COMMON_LVB_UNDERSCORE)
- if (attributes&BACKGROUND_RED) background|= 1;
- if (attributes&BACKGROUND_GREEN) background|= 2;
- if (attributes&BACKGROUND_BLUE) background|= 4;
+void TTYOutput::TrueColors::AppendSuffix(std::string &out, DWORD rgb)
+{
+ // first try to deduce 256-color palette index...
+ if (_colors256_lookup.empty()) {
+ static_assert(VT_256COLOR_TABLE_COUNT <= 0x100, "Too big VT_256COLOR_TABLE_COUNT");
+ for (size_t i = 0; i < VT_256COLOR_TABLE_COUNT; ++i) {
+ _colors256_lookup[g_VT256ColorTable[i]] = i;
+ }
+ }
+ char buf[64];
+ const auto &it = _colors256_lookup.find(rgb);
+ if (it != _colors256_lookup.end()) {
+ sprintf(buf, "5;%u;", it->second + 16);
+ } else {
+ sprintf(buf, "2;%u;%u;%u;", rgb & 0xff, (rgb >> 8) & 0xff, (rgb >> 16) & 0xff);
+ }
+ out+= buf;
+}
+template <DWORD64 R, DWORD64 G, DWORD64 B>
+ static void AppendAnsiColorSuffix(std::string &out, DWORD64 attr)
+{
+ char ch = '0';
+ if (attr & R) ch+= 1;
+ if (attr & G) ch+= 2;
+ if (attr & B) ch+= 4;
+ out+= ch;
+ out+= ';';
}
-bool TTYOutput::Attributes::operator ==(const Attributes &attr) const
+void TTYOutput::WriteUpdatedAttributes(DWORD64 attr, bool is_space)
{
- return (foreground_intensive == attr.foreground_intensive
- && background_intensive == attr.background_intensive
- && foreground == attr.foreground && background == attr.background);
+ const DWORD64 xa = _prev_attr_valid ? attr ^ _prev_attr : (DWORD64)-1;
+ if (xa == 0) {
+ return;
+ }
+ if (is_space && (xa & ATTRIBUTES_AFFECTING_BACKGROUND) == 0) {
+ if ((attr & BACKGROUND_TRUECOLOR) == 0 || GET_RGB_BACK(xa) == 0) {
+ return;
+ }
+ }
+
+ _tmp_attrs = ESC "[";
+// wikipedia claims that colors 90-97 are nonstandard, so in case of some
+// terminal missing '90–97 Set bright foreground color' - use bold font
+ if (_kernel_tty && (xa & FOREGROUND_INTENSITY) != 0) {
+ _tmp_attrs+= (attr & FOREGROUND_INTENSITY) ? "1;" : "22;";
+ }
+
+ if ( ((xa & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)) != 0)
+ || ((_prev_attr & FOREGROUND_TRUECOLOR) != 0 && (attr & FOREGROUND_TRUECOLOR) == 0) ) {
+ _tmp_attrs+= (attr & FOREGROUND_INTENSITY) ? '9' : '3';
+ AppendAnsiColorSuffix<FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_BLUE>(_tmp_attrs, attr);
+ }
+
+ if ( ((xa & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)) != 0)
+ || ((_prev_attr & BACKGROUND_TRUECOLOR) != 0 && (attr & BACKGROUND_TRUECOLOR) == 0) ) {
+ if (attr & BACKGROUND_INTENSITY) {
+ _tmp_attrs+= "10";
+ } else {
+ _tmp_attrs+= '4';
+ }
+ AppendAnsiColorSuffix<BACKGROUND_RED, BACKGROUND_GREEN, BACKGROUND_BLUE>(_tmp_attrs, attr);
+ }
+
+ if ((attr & FOREGROUND_TRUECOLOR) != 0 && (GET_RGB_FORE(xa) != 0 || (xa & FOREGROUND_TRUECOLOR) != 0)) {
+ _tmp_attrs+= "38;";
+ _true_colors.AppendSuffix(_tmp_attrs, GET_RGB_FORE(attr));
+ }
+
+ if ((attr & BACKGROUND_TRUECOLOR) != 0 && (GET_RGB_BACK(xa) != 0 || (xa & BACKGROUND_TRUECOLOR) != 0)) {
+ _tmp_attrs+= "48;";
+ _true_colors.AppendSuffix(_tmp_attrs, GET_RGB_BACK(attr));
+ }
+
+ if ( (xa & COMMON_LVB_UNDERSCORE) != 0) {
+ _tmp_attrs+= (attr & COMMON_LVB_UNDERSCORE) ? "4;" : "24;";
+ }
+
+ if ( (xa & COMMON_LVB_REVERSE_VIDEO) != 0) {
+ _tmp_attrs+= (attr & COMMON_LVB_REVERSE_VIDEO) ? "7;" : "27;";
+ }
+
+ assert(!_tmp_attrs.empty() && _tmp_attrs.back() == ';');
+ _tmp_attrs.back() = 'm';
+ _prev_attr = attr;
+ _prev_attr_valid = true;
+
+ Write(_tmp_attrs.c_str(), _tmp_attrs.size());
}
///////////////////////
@@ -306,47 +381,25 @@ int TTYOutput::WeightOfHorizontalMoveCursor(unsigned int y, unsigned int x) cons
void TTYOutput::WriteLine(const CHAR_INFO *ci, unsigned int cnt)
{
- std::string tmp;
- for (;cnt; ++ci,--cnt) {
- const bool is_space = (ci->Char.UnicodeChar <= 0x20
+ for (;cnt; ++ci,--cnt, ++_cursor.x) if (ci->Char.UnicodeChar) {
+ const bool is_space = !CI_USING_COMPOSITE_CHAR(*ci) && (
+ ci->Char.UnicodeChar <= 0x20
|| (ci->Char.UnicodeChar >= 0x7f && ci->Char.UnicodeChar < 0xa0)
|| !WCHAR_IS_VALID(ci->Char.UnicodeChar));
- Attributes attr(ci->Attributes);
- if (_attr != attr && (!is_space || _attr.background != attr.background
- || _attr.background_intensive != attr.background_intensive) ) {
+ WriteUpdatedAttributes(ci->Attributes, is_space);
- tmp = ESC "[";
-// wikipedia claims that colors 90-97 are nonstandard, so in case of some
-// terminal missing '90–97 Set bright foreground color' - use bold font
- if (_kernel_tty && _attr.foreground_intensive != attr.foreground_intensive)
- tmp+= attr.foreground_intensive ? "1;" : "22;";
-
- if (_attr.foreground != attr.foreground
- || _attr.foreground_intensive != attr.foreground_intensive) {
- tmp+= attr.foreground_intensive ? '9' : '3';
- tmp+= '0' + attr.foreground;
- tmp+= ';';
- }
+ if (is_space) {
+ WriteWChar(L' ');
- if (_attr.background != attr.background
- || _attr.background_intensive != attr.background_intensive) {
- if (attr.background_intensive) {
- tmp+= "10";
- } else
- tmp+= '4';
- tmp+= '0' + attr.background;
- tmp+= ';';
+ } else if (CI_USING_COMPOSITE_CHAR(*ci)) {
+ for (const WCHAR *pw = WINPORT(CompositeCharLookup)(ci->Char.UnicodeChar); *pw; ++pw) {
+ WriteWChar(*pw);
}
- assert(tmp[tmp.size() - 1] == ';');
- tmp[tmp.size() - 1] = 'm';
- Write(tmp.c_str(), tmp.size());
- _attr = attr;
+ } else {
+ WriteWChar(ci->Char.UnicodeChar);
}
-
- WriteWChar(is_space ? L' ' : ci->Char.UnicodeChar);
- ++_cursor.x;
}
}
diff --git a/WinPort/src/Backend/TTY/TTYOutput.h b/WinPort/src/Backend/TTY/TTYOutput.h
index 8adee54c..7ff4b3df 100644
--- a/WinPort/src/Backend/TTY/TTYOutput.h
+++ b/WinPort/src/Backend/TTY/TTYOutput.h
@@ -1,6 +1,7 @@
#pragma once
#include <stdexcept>
#include <vector>
+#include <map>
#include <WinCompat.h>
#include <StackSerializer.h>
@@ -12,35 +13,33 @@ class TTYOutput
bool visible = false;
} _cursor;
- struct Attributes
- {
- Attributes() = default;
- Attributes(const Attributes &) = default;
- Attributes(WORD attributes);
-
- bool foreground_intensive = false;
- bool background_intensive = false;
- unsigned char foreground = -1;
- unsigned char background = -1;
-
- bool operator ==(const Attributes &attr) const;
- bool operator !=(const Attributes &attr) const {return !(operator ==(attr)); }
- } _attr;
-
- int _out;
std::vector<char> _rawbuf;
struct {
WCHAR wch = 0;
unsigned int count = 0;
std::string tmp;
} _same_chars;
+
+ struct TrueColors {
+ void AppendSuffix(std::string &out, DWORD rgb);
+ std::map<DWORD, BYTE> _colors256_lookup;
+ } _true_colors;
+
+ int _out;
bool _far2l_tty, _kernel_tty;
+ bool _prev_attr_valid{false};
+ DWORD64 _prev_attr{};
+ std::string _tmp_attrs;
void WriteReally(const char *str, int len);
void FinalizeSameChars();
void WriteWChar(WCHAR wch);
void Write(const char *str, int len);
void Format(const char *fmt, ...);
+
+ void AppendTrueColorSuffix(std::string &out, DWORD rgb);
+ void WriteUpdatedAttributes(DWORD64 new_attr, bool is_space);
+
public:
TTYOutput(int out, bool far2l_tty);
~TTYOutput();
diff --git a/WinPort/src/Backend/WX/Paint.cpp b/WinPort/src/Backend/WX/Paint.cpp
index 1173f7c0..d6f47725 100644
--- a/WinPort/src/Backend/WX/Paint.cpp
+++ b/WinPort/src/Backend/WX/Paint.cpp
@@ -6,9 +6,10 @@
#include <wx/graphics.h>
#include "Paint.h"
#include "PathHelpers.h"
+#include "WinPort.h"
#include <utils.h>
-#define ALL_ATTRIBUTES ( FOREGROUND_INTENSITY | BACKGROUND_INTENSITY | \
+#define COLOR_ATTRIBUTES ( FOREGROUND_INTENSITY | BACKGROUND_INTENSITY | \
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | \
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE )
@@ -121,8 +122,8 @@ static void InitializeFont(wxWindow *parent, wxFont& font)
}
ConsolePaintContext::ConsolePaintContext(wxWindow *window) :
- _window(window), _font_width(12), _font_height(16), _font_thickness(2),
- _buffered_paint(false), _sharp(false), _noticed_combinings(false)
+ _window(window), _font_width(12), _font_height(16), _font_descent(0), _font_thickness(2),
+ _buffered_paint(false), _sharp(false)
{
_char_fit_cache.checked.resize(0xffff);
_char_fit_cache.result.resize(0xffff);
@@ -141,18 +142,20 @@ class FontSizeInspector
wxMemoryDC _dc;
int _max_width, _prev_width;
- int _max_height, _prev_height;
+ int _max_height, _prev_height;
+ int _max_descent;
bool _unstable_size, _fractional_size;
void InspectChar(const wchar_t c)
{
wchar_t wz[2] = { c, 0};
- wxSize char_size = _dc.GetTextExtent(wz);
- const int width = char_size.GetWidth();
- const int height = char_size.GetHeight();
+ wxCoord width = 0, height = 0, descent = 0;
+ _dc.GetTextExtent(wz, &width, &height, &descent);
if (_max_width < width) _max_width = width;
if (_max_height < height) _max_height = height;
+ if (_max_descent < descent) _max_descent = descent;
+
if ( _prev_width != width ) {
if (_prev_width!=-1)
_unstable_size = true;
@@ -199,6 +202,7 @@ class FontSizeInspector
bool IsFractionalSize() const { return _fractional_size; }
int GetMaxWidth() const { return _max_width; }
int GetMaxHeight() const { return _max_height; }
+ int GetMaxDescent() const { return _max_descent; }
};
@@ -213,6 +217,7 @@ void ConsolePaintContext::SetFont(wxFont font)
bool is_fractional = fsi.IsFractionalSize();
_font_width = fsi.GetMaxWidth();
_font_height = fsi.GetMaxHeight();
+ _font_descent = fsi.GetMaxDescent();
//font_height+= _font_height/4;
_font_thickness = (_font_width > 8) ? _font_width / 8 : 1;
@@ -269,51 +274,54 @@ void ConsolePaintContext::ShowFontDialog()
SetFont(font);
}
-
-uint8_t ConsolePaintContext::CharFitTest(wxPaintDC &dc, wchar_t c)
+
+uint8_t ConsolePaintContext::CharFitTest(wxPaintDC &dc, const wchar_t *wcz)
{
- const bool cacheable = ((size_t)c <= _char_fit_cache.checked.size());
- if (cacheable && _char_fit_cache.checked[ (size_t)c - 1 ]) {
- return _char_fit_cache.result[ (size_t)c - 1 ];
+#ifdef DYNAMIC_FONTS
+ const bool cacheable = (size_t(wcz[0]) <= _char_fit_cache.checked.size() && wcz[1] == 0);
+ if (cacheable && _char_fit_cache.checked[ size_t(wcz[0]) - 1 ]) {
+ return _char_fit_cache.result[ size_t(wcz[0]) - 1 ];
}
- uint8_t font_index;
- _cft_tmp = wxUniChar(c);
- wxSize char_size = dc.GetTextExtent(_cft_tmp);
- if ((unsigned)char_size.GetWidth() == _font_width
- && (unsigned)char_size.GetHeight() == _font_height) {
- font_index = 0;
- } else {
- font_index = 0xff;
-#ifdef DYNAMIC_FONTS
- for (uint8_t try_index = 1;;++try_index) {
- if (try_index==0xff || (
- (unsigned)char_size.GetWidth() <= _font_width &&
- (unsigned)char_size.GetHeight() <= _font_height))
- {
- if (font_index!=0xff) ApplyFont(dc);
- break;
- }
+ uint8_t font_index = 0;
+ _cft_tmp = wcz;
+ wxCoord w, h = _font_height, d = _font_descent;
+ dc.GetTextExtent(_cft_tmp, &w, &h, &d);
+ for (uint8_t try_index = 1; try_index != 0xff && (unsigned)h > _font_height + std::max(0, int(d) - int(_font_descent)); ++try_index) {
- while (_fonts.size() <= try_index) {
- wxFont smallest = _fonts.back();
- smallest.MakeSmaller();
- smallest.MakeBold();
- _fonts.emplace_back(smallest);
+ if (try_index >= _fonts.size()) {
+ wxFont smallest = _fonts.back();
+ wxSize px_size = smallest.GetPixelSize();
+ if (px_size.GetHeight() <= 4) {
+ break;
}
- dc.SetFont(_fonts[try_index]);
- char_size = dc.GetTextExtent(_cft_tmp);
- font_index = try_index;
+ px_size.SetHeight(px_size.GetHeight() - 1);
+ px_size.SetWidth(0);
+ smallest.SetPixelSize(px_size);
+ _fonts.emplace_back(smallest);
}
-#endif
+ assert(try_index < _fonts.size());
+ dc.SetFont(_fonts[try_index]);
+ dc.GetTextExtent(_cft_tmp, &w, &h, &d);
+ font_index = try_index;
+ }
+ if (font_index != 0) {
+// fprintf(stderr, "Changed[%d] point size = %u -> %u for '%ls'\n",
+// font_index, _fonts[0].GetPointSize(), _fonts[font_index].GetPointSize(), wcz);
+ ApplyFont(dc);
}
if (cacheable) {
- _char_fit_cache.result[ (size_t)c - 1 ] = font_index;
- _char_fit_cache.checked[ (size_t)c - 1 ] = true;
+ _char_fit_cache.result[ size_t(wcz[0]) - 1 ] = font_index;
+ _char_fit_cache.checked[ size_t(wcz[0]) - 1 ] = true;
}
return font_index;
+
+#else
+ return 0;
+
+#endif
}
void ConsolePaintContext::ApplyFont(wxPaintDC &dc, uint8_t index)
@@ -324,8 +332,6 @@ void ConsolePaintContext::ApplyFont(wxPaintDC &dc, uint8_t index)
void ConsolePaintContext::OnPaint(SMALL_RECT *qedit)
{
- _line_combinings_inspected.clear();
-
wxPaintDC dc(_window);
#if wxUSE_GRAPHICS_CONTEXT
wxGraphicsContext* gctx = dc.GetGraphicsContext();
@@ -359,7 +365,6 @@ void ConsolePaintContext::OnPaint(SMALL_RECT *qedit)
ApplyFont(dc);
_cursor_props.Update();
- _cursor_props.combining_offset = 0;
ConsolePainter painter(this, dc, _buffer, _cursor_props);
for (unsigned int cy = (unsigned)area.Top; cy <= (unsigned)area.Bottom; ++cy) {
@@ -385,60 +390,37 @@ void ConsolePaintContext::OnPaint(SMALL_RECT *qedit)
}
painter.LineBegin(cy);
-
- // HACK: combinings characters are kind of characters that combined with prceeding character
- // FAR internally doesn't know about them, treating them as separate characters
- // so here is workaround: when renedring line check each character to be combinings and if so
- // left-adjust positions of all subsequent characters until pseudographic, that typically end of
- // panel
- unsigned int affecting_combinings = 0;
- unsigned short attributes = line->Attributes;
- for (unsigned int char_index = 0; char_index != cw; ++char_index) {
- const auto c = line[char_index].Char.UnicodeChar;
-
- if (WCHAR_IS_COMBINING(c)) {
- ++affecting_combinings;
- // Bit dirty optimization - activate combinings area update
- // correction only if during rendering combinings characters
- // were encountered. So by design there can be single one
- // glitch per whole process life time ..
- _noticed_combinings = true;
- }
- else if (affecting_combinings && (c == '|' || WCHAR_IS_PSEUDOGRAPHIC(c))) {
- // reached panel's edge - space-fill gap caused by combinings
- for (int i = affecting_combinings; i >= 0; --i) {
- painter.NextChar(char_index - i, attributes, ' ');
- }
- painter.LineFlush(char_index);
- affecting_combinings = 0;
- }
-
- const unsigned int cx = (char_index > affecting_combinings) ? char_index - affecting_combinings : 0;
-
- if (cy == (unsigned int)_cursor_props.pos.Y && char_index == (unsigned int)_cursor_props.pos.X) {
- _cursor_props.combining_offset = (SHORT)affecting_combinings;
+ wchar_t tmp_wcz[2] = {0, 0};
+ DWORD64 attributes = line->Attributes;
+ const unsigned int cx_begin = (area.Left > 0 && !line[area.Left].Char.UnicodeChar) ? area.Left - 1 : area.Left;
+ const unsigned int cx_end = std::min(cw, (unsigned)area.Right + 1);
+ for (unsigned int cx = cx_begin; cx < cx_end; ++cx) {
+ if (!line[cx].Char.UnicodeChar) {
+ painter.LineFlush(cx + 1);
+ continue;
}
-
- if (cx > (unsigned)area.Right) {
- break;
+ const wchar_t *pwcz;
+ if (UNLIKELY(CI_USING_COMPOSITE_CHAR(line[cx]))) {
+ pwcz = WINPORT(CompositeCharLookup)(line[cx].Char.UnicodeChar);
+ } else {
+ tmp_wcz[0] = line[cx].Char.UnicodeChar ? wchar_t(line[cx].Char.UnicodeChar) : L' ';
+ pwcz = tmp_wcz;
}
- if (cx >= (unsigned)area.Left) {
- attributes = line[char_index].Attributes;
- if (qedit && cx >= (unsigned)qedit->Left && cx <= (unsigned)qedit->Right
- && cy >= (unsigned)qedit->Top && cy <= (unsigned)qedit->Bottom) {
- attributes^= ALL_ATTRIBUTES;
+ attributes = line[cx].Attributes;
+ if (qedit && cx >= (unsigned)qedit->Left && cx <= (unsigned)qedit->Right
+ && cy >= (unsigned)qedit->Top && cy <= (unsigned)qedit->Bottom) {
+ attributes^= COLOR_ATTRIBUTES;
+ if (attributes & FOREGROUND_TRUECOLOR) {
+ attributes^= 0x000000ffffff0000;
+ }
+ if (attributes & BACKGROUND_TRUECOLOR) {
+ attributes^= 0xffffff0000000000;
}
-
- painter.NextChar(cx, attributes, c);
-
}
+ const int nx = (cx + 1 < cw && !line[cx + 1].Char.UnicodeChar) ? 2 : 1;
+ painter.NextChar(cx, attributes, pwcz, nx);
}
- // space-fill gap caused by combinings if any at the end of line
-// for (int i = affecting_combinings; i >= 0; --i) {
-// painter.NextChar(area.Right + 1 - i, attributes, ' ');
-// }
-
painter.LineFlush(area.Right + 1);
}
}
@@ -451,31 +433,6 @@ void ConsolePaintContext::RefreshArea( const SMALL_RECT &area )
rc.SetRight(((int)area.Right) * _font_width + _font_width - 1);
rc.SetTop(((int)area.Top) * _font_height);
rc.SetBottom(((int)area.Bottom) * _font_height + _font_height - 1);
-
- if (area.Left != 0 && _noticed_combinings) {
- if (_line_combinings_inspected.size() <= (size_t)area.Bottom) {
- _line_combinings_inspected.resize(((size_t)area.Bottom) + 1);
- }
-
- for (SHORT cy = area.Top; cy <= area.Bottom; ++cy) {
- if (!_line_combinings_inspected[cy]) {
- _line_combinings_inspected[cy] = true;
- IConsoleOutput::DirectLineAccess dla(g_winport_con_out, cy);
- const CHAR_INFO *line = dla.Line();
- if (line) {
- for (unsigned int cx = 0; cx < dla.Width(); ++cx) {
- if (WCHAR_IS_COMBINING(line[cx].Char.UnicodeChar)) {
- rc.SetLeft(0);
- rc.SetRight(dla.Width() * _font_width);
- break;
- }
- }
- }
- }
- }
-
- }
-
_window->Refresh(false, &rc);
}
@@ -484,9 +441,17 @@ void ConsolePaintContext::BlinkCursor()
{
if (_cursor_props.Blink()) {
SMALL_RECT area = {
- SHORT(_cursor_props.pos.X - _cursor_props.combining_offset), _cursor_props.pos.Y,
- SHORT(_cursor_props.pos.X - _cursor_props.combining_offset), _cursor_props.pos.Y
+ _cursor_props.pos.X, _cursor_props.pos.Y,
+ _cursor_props.pos.X, _cursor_props.pos.Y
};
+ CHAR_INFO ci{};
+ if (g_winport_con_out->Read(ci, _cursor_props.pos)) {
+ if (!ci.Char.UnicodeChar && area.Left > 0) {
+ --area.Left;
+ } else if (CI_FULL_WIDTH_CHAR(ci)) {
+ ++area.Right;
+ }
+ }
RefreshArea(area);
}
}
@@ -541,7 +506,7 @@ void CursorProps::Update()
ConsolePainter::ConsolePainter(ConsolePaintContext *context, wxPaintDC &dc, wxString &buffer, CursorProps &cursor_props) :
_context(context), _dc(dc), _buffer(buffer), _cursor_props(cursor_props),
- _start_cx((unsigned int)-1), _start_back_cx((unsigned int)-1), _prev_fit_font_index(0)
+ _start_cx((unsigned int)-1), _start_back_cx((unsigned int)-1), _prev_fit_font_index(0), _prev_underlined(false)
{
_dc.SetPen(context->GetTransparentPen());
_dc.SetBackgroundMode(wxPENSTYLE_TRANSPARENT);
@@ -558,16 +523,16 @@ void ConsolePainter::SetFillColor(const WinPortRGB &clr)
}
}
-void ConsolePainter::PrepareBackground(unsigned int cx, const WinPortRGB &clr)
+void ConsolePainter::PrepareBackground(unsigned int cx, const WinPortRGB &clr, unsigned int nx)
{
const bool cursor_here = (_cursor_props.visible && _cursor_props.blink_state
- && cx == (unsigned int)_cursor_props.pos.X - _cursor_props.combining_offset
+ && cx == (unsigned int)_cursor_props.pos.X
&& _start_cy == (unsigned int)_cursor_props.pos.Y);
if (!cursor_here && _start_back_cx != (unsigned int)-1 && _clr_back == clr)
return;
- FlushBackground(cx);
+ FlushBackground(cx + nx - 1);
if (!cursor_here) {
_clr_back = clr;
@@ -584,36 +549,48 @@ void ConsolePainter::PrepareBackground(unsigned int cx, const WinPortRGB &clr)
if (fill_height > _context->FontHeight()) fill_height = _context->FontHeight();
WinPortRGB clr_xored(clr.r ^ 0xff, clr.g ^ 0xff, clr.b ^ 0xff);
SetFillColor(clr_xored);
- _dc.DrawRectangle(x, _start_y + fill_height, _context->FontWidth(), h);
+ _dc.DrawRectangle(x, _start_y + fill_height, _context->FontWidth() * nx, h);
if (fill_height) {
SetFillColor(clr);
- _dc.DrawRectangle(x, _start_y, _context->FontWidth(), fill_height);
+ _dc.DrawRectangle(x, _start_y, _context->FontWidth() * nx, fill_height);
}
}
-void ConsolePainter::FlushBackground(unsigned int cx)
+void ConsolePainter::FlushBackground(unsigned int cx_end)
{
- if (_start_back_cx!= ((unsigned int)-1)) {
+ if (_start_back_cx != ((unsigned int)-1)) {
SetFillColor(_clr_back);
_dc.DrawRectangle(_start_back_cx * _context->FontWidth(), _start_y,
- (cx - _start_back_cx) * _context->FontWidth(), _context->FontHeight());
+ (cx_end - _start_back_cx) * _context->FontWidth(), _context->FontHeight());
_start_back_cx = ((unsigned int)-1);
}
}
-void ConsolePainter::FlushText()
+void ConsolePainter::FlushText(unsigned int cx_end)
{
if (!_buffer.empty()) {
_dc.SetTextForeground(wxColour(_clr_text.r, _clr_text.g, _clr_text.b));
_dc.DrawText(_buffer, _start_cx * _context->FontWidth(), _start_y);
_buffer.Empty();
}
+ FlushUnderline(cx_end);
_start_cx = (unsigned int)-1;
_prev_fit_font_index = 0;
}
+void ConsolePainter::FlushUnderline(unsigned int cx_end)
+{
+ if (_prev_underlined) {
+ _dc.SetPen(wxColour(_clr_text.r, _clr_text.g, _clr_text.b));
+ _dc.DrawLine(_start_cx * _context->FontWidth(), _start_y + _context->FontHeight() - 1,
+ cx_end * _context->FontWidth(), _start_y + _context->FontHeight() - 1);
+ _dc.SetPen(_context->GetTransparentPen());
+ _prev_underlined = false;
+ }
+}
+
static inline unsigned char CalcFadeColor(unsigned char bg, unsigned char fg)
{
unsigned short out = fg;
@@ -709,59 +686,58 @@ void WXCustomDrawChar::Painter::FillPixel(wxCoord left, wxCoord top)
}
-void ConsolePainter::NextChar(unsigned int cx, unsigned short attributes, wchar_t c)
+void ConsolePainter::NextChar(unsigned int cx, DWORD64 attributes, const wchar_t *wcz, unsigned int nx)
{
WXCustomDrawChar::DrawT custom_draw = nullptr;
- if (!c || c == L' ' || !WCHAR_IS_VALID(c) || (_context->IsCustomDrawEnabled()
- && (custom_draw = WXCustomDrawChar::Get(c)) != nullptr)) {
+ if (!wcz[0] || (!wcz[1] && (wcz[0] == L' ' || !WCHAR_IS_VALID(wcz[0]) || (_context->IsCustomDrawEnabled()
+ && (custom_draw = WXCustomDrawChar::Get(wcz[0])) != nullptr)))) {
if (!_buffer.empty())
- FlushBackground(cx);
- FlushText();
+ FlushBackground(cx + nx - 1);
+ FlushText(cx + nx - 1);
}
const WinPortRGB &clr_back = ConsoleBackground2RGB(attributes);
- PrepareBackground(cx, clr_back);
+ PrepareBackground(cx, clr_back, nx);
- // NB: combining characters must be printed over previous ones,
- // simulate this by shifting characters left until 1st space found (#826, #213)
-
- if (!c || c == L' ' || !WCHAR_IS_VALID(c)) {
+ if (!wcz[0] || (!wcz[1] && (wcz[0] == L' ' || !WCHAR_IS_VALID(wcz[0])))) {
return;
}
const WinPortRGB &clr_text = ConsoleForeground2RGB(attributes);
if (custom_draw) {
- FlushBackground(cx + 1);
-
+ FlushBackground(cx + nx);
WXCustomDrawCharPainter cdp(*this, clr_text, clr_back);
custom_draw(cdp, _start_y, cx);
+ FlushUnderline(cx);
_start_cx = (unsigned int)-1;
_prev_fit_font_index = 0;
+ return;
+ }
- } else {
- uint8_t fit_font_index = WCHAR_IS_COMBINING(c) ? // workaround for
- _prev_fit_font_index : _context->CharFitTest(_dc, c);
+ uint8_t fit_font_index = _context->CharFitTest(_dc, wcz);
+ const bool underlined = (attributes & COMMON_LVB_UNDERSCORE) != 0;
- if (fit_font_index == _prev_fit_font_index && _context->IsPaintBuffered()
- && _start_cx != (unsigned int) -1 && _clr_text == clr_text) {
- _buffer+= c;
- return;
- }
+ if (fit_font_index == _prev_fit_font_index && _prev_underlined == underlined
+ && _start_cx != (unsigned int)-1 && _clr_text == clr_text && _context->IsPaintBuffered()) {
+ _buffer+= wcz;
+ return;
+ }
- _prev_fit_font_index = fit_font_index;
+ FlushBackground(cx + nx);
+ FlushText(cx);
- FlushBackground(cx + 1);
- FlushText();
- _start_cx = cx;
- _buffer = c;
- _clr_text = clr_text;
+ _prev_fit_font_index = fit_font_index;
+ _prev_underlined = underlined;
- if (fit_font_index != 0 && fit_font_index != 0xff) {
- _context->ApplyFont(_dc, fit_font_index);
- FlushText();
- _context->ApplyFont(_dc);
- }
+ _start_cx = cx;
+ _buffer = wcz;
+ _clr_text = clr_text;
+
+ if (fit_font_index != 0 && fit_font_index != 0xff) {
+ _context->ApplyFont(_dc, fit_font_index);
+ FlushText(cx + nx);
+ _context->ApplyFont(_dc);
}
}
diff --git a/WinPort/src/Backend/WX/Paint.h b/WinPort/src/Backend/WX/Paint.h
index c9e6c86f..b61199be 100644
--- a/WinPort/src/Backend/WX/Paint.h
+++ b/WinPort/src/Backend/WX/Paint.h
@@ -23,11 +23,9 @@ struct CursorProps
class ConsolePaintContext
{
std::vector<wxFont> _fonts;
- std::vector<bool> _line_combinings_inspected;
wxWindow *_window;
- unsigned int _font_width, _font_height, _font_thickness;
+ unsigned int _font_width, _font_height, _font_descent, _font_thickness;
bool _custom_draw_enabled, _buffered_paint, _sharp;
- bool _noticed_combinings;
CursorProps _cursor_props;
struct {
std::vector<bool> checked;
@@ -47,7 +45,7 @@ public:
ConsolePaintContext(wxWindow *window);
void ShowFontDialog();
- uint8_t CharFitTest(wxPaintDC &dc, wchar_t c);
+ uint8_t CharFitTest(wxPaintDC &dc, const wchar_t *wcz);
void ApplyFont(wxPaintDC &dc, uint8_t index = 0);
void OnPaint(SMALL_RECT *qedit = NULL);
void RefreshArea( const SMALL_RECT &area );
@@ -100,20 +98,22 @@ class ConsolePainter
unsigned int _start_cx, _start_cy, _start_back_cx;
unsigned int _start_y;
uint8_t _prev_fit_font_index;
+ bool _prev_underlined;
std::map<WinPortRGB, wxPen *> _custom_draw_pens;
friend struct WXCustomDrawCharPainter;
void SetFillColor(const WinPortRGB &clr);
- void PrepareBackground(unsigned int cx, const WinPortRGB &clr);
- void FlushBackground(unsigned int cx);
- void FlushText();
+ void PrepareBackground(unsigned int cx, const WinPortRGB &clr, unsigned int nx);
+ void FlushBackground(unsigned int cx_end);
+ void FlushText(unsigned int cx_end);
+ void FlushUnderline(unsigned int cx_end);
public:
ConsolePainter(ConsolePaintContext *context, wxPaintDC &dc, wxString &_buffer, CursorProps &cursor_props);
- void NextChar(unsigned int cx, unsigned short attributes, wchar_t c);
+ void NextChar(unsigned int cx, DWORD64 attributes, const wchar_t *wcz, unsigned int nx);
inline void LineBegin(unsigned int cy)
{
@@ -124,7 +124,7 @@ public:
inline void LineFlush(unsigned int cx_end)
{
FlushBackground(cx_end);
- FlushText();
+ FlushText(cx_end);
}
};
diff --git a/WinPort/src/Backend/WX/wxMain.cpp b/WinPort/src/Backend/WX/wxMain.cpp
index 767a244f..f72d6365 100644
--- a/WinPort/src/Backend/WX/wxMain.cpp
+++ b/WinPort/src/Backend/WX/wxMain.cpp
@@ -473,6 +473,11 @@ bool WinPortPanel::OnConsoleSetFKeyTitles(const char **titles)
#endif
}
+BYTE WinPortPanel::OnConsoleGetColorPalette()
+{
+ return 24;
+}
+
void WinPortPanel::OnTouchbarKey(bool alternate, int index)
{
INPUT_RECORD ir = {};
@@ -1256,8 +1261,13 @@ void WinPortPanel::OnMouseQEdit( wxMouseEvent &event, COORD pos_char )
}
for (pos.X = x1; pos.X<=x2; ++pos.X) {
CHAR_INFO ch;
- if (g_winport_con_out->Read(ch, pos))
- _text2clip+= ch.Char.UnicodeChar ? ch.Char.UnicodeChar : L' ';
+ if (g_winport_con_out->Read(ch, pos)) {
+ if (CI_USING_COMPOSITE_CHAR(ch)) {
+ _text2clip+= WINPORT(CompositeCharLookup)(ch.Char.UnicodeChar);
+ } else if (ch.Char.UnicodeChar) {
+ _text2clip+= ch.Char.UnicodeChar;
+ }
+ }
}
if (y2 > y1) {
while (!_text2clip.empty() && _text2clip[_text2clip.size() - 1] == ' ') {
diff --git a/WinPort/src/Backend/WX/wxMain.h b/WinPort/src/Backend/WX/wxMain.h
index 009d6763..899f5100 100644
--- a/WinPort/src/Backend/WX/wxMain.h
+++ b/WinPort/src/Backend/WX/wxMain.h
@@ -147,6 +147,7 @@ class WinPortPanel: public wxPanel, protected IConsoleOutputBackend
virtual void OnConsoleDisplayNotification(const wchar_t *title, const wchar_t *text);
virtual bool OnConsoleBackgroundMode(bool TryEnterBackgroundMode);
virtual bool OnConsoleSetFKeyTitles(const char **titles);
+ virtual BYTE OnConsoleGetColorPalette();
public:
WinPortPanel(WinPortFrame *frame, const wxPoint& pos, const wxSize& size);
diff --git a/WinPort/src/Backend/WX/wxWinTranslations.cpp b/WinPort/src/Backend/WX/wxWinTranslations.cpp
index a5be93ec..eafcaba7 100644
--- a/WinPort/src/Backend/WX/wxWinTranslations.cpp
+++ b/WinPort/src/Backend/WX/wxWinTranslations.cpp
@@ -168,18 +168,34 @@ static const WinPortRGB &InternalConsoleBackground2RGB(USHORT attributes)
return g_palette_background[(attributes & 0xf0) >> 4];
}
-WinPortRGB ConsoleForeground2RGB(USHORT attributes)
+WinPortRGB ConsoleForeground2RGB(DWORD64 attributes)
{
- return (attributes & COMMON_LVB_REVERSE_VIDEO) ?
- InternalConsoleBackground2RGB(attributes) :
- InternalConsoleForeground2RGB(attributes);
+ if ( (attributes & (FOREGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO)) == FOREGROUND_TRUECOLOR) {
+ return GET_RGB_FORE(attributes);
+ }
+
+ if ( (attributes & (BACKGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO)) == (BACKGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO)) {
+ return GET_RGB_BACK(attributes);
+ }
+
+ return (attributes & COMMON_LVB_REVERSE_VIDEO)
+ ? InternalConsoleBackground2RGB((USHORT)attributes)
+ : InternalConsoleForeground2RGB((USHORT)attributes);
}
-WinPortRGB ConsoleBackground2RGB(USHORT attributes)
+WinPortRGB ConsoleBackground2RGB(DWORD64 attributes)
{
- return (attributes & COMMON_LVB_REVERSE_VIDEO) ?
- InternalConsoleForeground2RGB(attributes) :
- InternalConsoleBackground2RGB(attributes);
+ if ( (attributes & (BACKGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO)) == BACKGROUND_TRUECOLOR) {
+ return GET_RGB_BACK(attributes);
+ }
+
+ if ( (attributes & (FOREGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO)) == (FOREGROUND_TRUECOLOR | COMMON_LVB_REVERSE_VIDEO)) {
+ return GET_RGB_FORE(attributes);
+ }
+
+ return (attributes & COMMON_LVB_REVERSE_VIDEO)
+ ? InternalConsoleForeground2RGB((USHORT)attributes)
+ : InternalConsoleBackground2RGB((USHORT)attributes);
}
diff --git a/WinPort/src/Backend/WX/wxWinTranslations.h b/WinPort/src/Backend/WX/wxWinTranslations.h
index e1553d90..5c259aea 100644
--- a/WinPort/src/Backend/WX/wxWinTranslations.h
+++ b/WinPort/src/Backend/WX/wxWinTranslations.h
@@ -51,7 +51,8 @@ struct WinPortRGB
unsigned char g;
unsigned char b;
- inline WinPortRGB(unsigned char r_ = 0, unsigned char g_ = 0, unsigned char b_ = 0) : r(r_), g(g_), b(b_) {}
+ inline WinPortRGB(DWORD rgb = 0) : r(rgb & 0xff), g((rgb >> 8) & 0xff), b((rgb >> 16) & 0xff) {}
+ inline WinPortRGB(unsigned char r_, unsigned char g_, unsigned char b_) : r(r_), g(g_), b(b_) {}
inline bool operator == (const WinPortRGB &rgb) const
{
@@ -75,7 +76,7 @@ struct WinPortRGB
}
};
-WinPortRGB ConsoleForeground2RGB(USHORT attributes);
-WinPortRGB ConsoleBackground2RGB(USHORT attributes);
+WinPortRGB ConsoleForeground2RGB(DWORD64 attributes);
+WinPortRGB ConsoleBackground2RGB(DWORD64 attributes);
bool InitPalettes();
diff --git a/WinPort/src/ConsoleBuffer.cpp b/WinPort/src/ConsoleBuffer.cpp
index 26708f97..0dddb52a 100644
--- a/WinPort/src/ConsoleBuffer.cpp
+++ b/WinPort/src/ConsoleBuffer.cpp
@@ -5,7 +5,7 @@ ConsoleBuffer::ConsoleBuffer() : _width(0)
{
}
-void ConsoleBuffer::SetSize(unsigned int width, unsigned int height, unsigned short attributes)
+void ConsoleBuffer::SetSize(unsigned int width, unsigned int height, uint64_t attributes)
{
if (width==_width && (width*height)==_console_chars.size() )
return;
@@ -16,8 +16,7 @@ void ConsoleBuffer::SetSize(unsigned int width, unsigned int height, unsigned sh
_console_chars.swap(other_chars);
_width = width;
for (auto &i : _console_chars) {
- i.Attributes = attributes;
- i.Char.UnicodeChar = 0;
+ CI_SET_WCATTR(i, L' ', attributes);
}
if (!other_chars.empty() && !_console_chars.empty()) {
@@ -44,8 +43,12 @@ template <class T> T *OffsetMatrixPtr(T *p, size_t width, size_t x, size_t y)
CHAR_INFO *ConsoleBuffer::InspectCopyArea(const COORD &data_size, const COORD &data_pos, SMALL_RECT &screen_rect)
{
- if (data_pos.X >= data_size.X || data_pos.Y >= data_size.Y)
- {fprintf(stderr, "bad1\n"); return NULL;}
+ if (data_pos.X < 0 || data_pos.Y < 0 || data_size.X < 0 || data_size.Y < 0
+ || data_pos.X >= data_size.X || data_pos.Y >= data_size.Y) {
+ fprintf(stderr, "InspectCopyArea: bad coordinates, data_size:{%d, %d} data_pos:{%d, %d}\n",
+ data_size.X, data_size.Y, data_pos.X, data_pos.Y);
+ return nullptr;
+ }
unsigned int height = _console_chars.size() / _width;
if ((int)_width <= screen_rect.Right)
@@ -60,10 +63,16 @@ CHAR_INFO *ConsoleBuffer::InspectCopyArea(const COORD &data_size, const COORD &d
if (data_avail_height <= (screen_rect.Bottom - screen_rect.Top))
screen_rect.Bottom = screen_rect.Top + data_avail_height - 1;
- if ((int)_width <= screen_rect.Left || screen_rect.Right < screen_rect.Left)
- {fprintf(stderr, "bad2\n"); return NULL;}
- if ((int)height <= screen_rect.Top || screen_rect.Bottom < screen_rect.Top)
- {fprintf(stderr, "bad3\n"); return NULL;}
+ if ((int)_width <= screen_rect.Left || screen_rect.Right < screen_rect.Left || screen_rect.Left < 0) {
+ fprintf(stderr, "InspectCopyArea: bad X-metrics, _width:%d screen_rect:{%d..%d}\n",
+ _width, screen_rect.Left, screen_rect.Right);
+ return nullptr;
+ }
+ if ((int)height <= screen_rect.Top || screen_rect.Bottom < screen_rect.Top || screen_rect.Top < 0) {
+ fprintf(stderr, "InspectCopyArea: bad Y-metrics, height:%d screen_rect:{%d..%d}\n",
+ height, screen_rect.Top, screen_rect.Bottom);
+ return nullptr;
+ }
return OffsetMatrixPtr(&_console_chars[0], _width, screen_rect.Left, screen_rect.Top);
}
@@ -84,7 +93,7 @@ void ConsoleBuffer::Read(CHAR_INFO *data, COORD data_size, COORD data_pos, SMALL
static inline bool AreSameChars(const CHAR_INFO &one, const CHAR_INFO &another)
{
- return one.Char.UnicodeChar==another.Char.UnicodeChar && one.Attributes==another.Attributes;
+ return one.Char.UnicodeChar == another.Char.UnicodeChar && one.Attributes == another.Attributes;
}
void ConsoleBuffer::Write(const CHAR_INFO *data, COORD data_size, COORD data_pos, SMALL_RECT &screen_rect)
diff --git a/WinPort/src/ConsoleBuffer.h b/WinPort/src/ConsoleBuffer.h
index 339a963a..8d451024 100644
--- a/WinPort/src/ConsoleBuffer.h
+++ b/WinPort/src/ConsoleBuffer.h
@@ -19,7 +19,7 @@ public:
WR_MODIFIED = 2
};
- void SetSize(unsigned int width, unsigned int height, unsigned short attributes);
+ void SetSize(unsigned int width, unsigned int height, uint64_t attributes);
void GetSize(unsigned int &width, unsigned int &height);
inline unsigned int GetWidth() const { return _width; }
diff --git a/WinPort/src/ConsoleOutput.cpp b/WinPort/src/ConsoleOutput.cpp
index e209cf74..6a68da8d 100644
--- a/WinPort/src/ConsoleOutput.cpp
+++ b/WinPort/src/ConsoleOutput.cpp
@@ -1,4 +1,6 @@
#include "ConsoleOutput.h"
+#include "WinPort.h"
+#include <utils.h>
#define TAB_WIDTH 8
#define NO_AREA {MAXSHORT, MAXSHORT, 0, 0}
@@ -35,11 +37,12 @@ size_t utf8_char_len(const char *s, size_t bytes)
ConsoleOutput::ConsoleOutput() :
- _title(L"WinPort"), _backend(NULL),
+ _backend(NULL),
_mode(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT),
_attributes(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
{
memset(&_cursor.pos, 0, sizeof(_cursor.pos));
+ MB2Wide(APP_BASENAME, _title);
_scroll_callback.pfn = NULL;
_cursor.height = 15;
_cursor.visible = true;
@@ -54,18 +57,32 @@ void ConsoleOutput::SetBackend(IConsoleOutputBackend *backend)
}
-void ConsoleOutput::SetAttributes(USHORT attributes)
+void ConsoleOutput::SetAttributes(DWORD64 attributes)
{
std::lock_guard<std::mutex> lock(_mutex);
_attributes = attributes;
}
-USHORT ConsoleOutput::GetAttributes()
+DWORD64 ConsoleOutput::GetAttributes()
{
std::lock_guard<std::mutex> lock(_mutex);
return _attributes;
}
+void ConsoleOutput::SetUpdateCellArea(SMALL_RECT &area, COORD pos)
+{
+ area.Left = area.Right = pos.X;
+ area.Top = area.Bottom = pos.Y;
+ CHAR_INFO ci{};
+ if (_buf.Read(ci, pos)) {
+ if (!ci.Char.UnicodeChar && area.Left > 0) {
+ --area.Left;
+ } else if (CI_FULL_WIDTH_CHAR(ci)) {
+ ++area.Right;
+ }
+ }
+}
+
void ConsoleOutput::SetCursor(COORD pos)
{
SMALL_RECT area[2];
@@ -74,11 +91,9 @@ void ConsoleOutput::SetCursor(COORD pos)
if (_cursor.pos.X == pos.X && _cursor.pos.Y == pos.Y)
return;
- area[0].Left = area[0].Right = _cursor.pos.X;
- area[0].Top = area[0].Bottom = _cursor.pos.Y;
+ SetUpdateCellArea(area[0], _cursor.pos);
_cursor.pos = pos;
- area[1].Left = area[1].Right = _cursor.pos.X;
- area[1].Top = area[1].Bottom = _cursor.pos.Y;
+ SetUpdateCellArea(area[1], _cursor.pos);
}
if (_backend) {
_backend->OnConsoleOutputUpdated(&area[0], 2);
@@ -92,8 +107,7 @@ void ConsoleOutput::SetCursor(UCHAR height, bool visible)
std::lock_guard<std::mutex> lock(_mutex);
_cursor.height = height;
_cursor.visible = visible;
- area.Left = area.Right = _cursor.pos.X;
- area.Top = area.Bottom = _cursor.pos.Y;
+ SetUpdateCellArea(area, _cursor.pos);
}
if (_backend)
_backend->OnConsoleOutputUpdated(&area, 1);
@@ -222,7 +236,8 @@ bool ConsoleOutput::Write(const CHAR_INFO &data, COORD screen_pos)
}
if (_backend) {
- SMALL_RECT area = {screen_pos.X, screen_pos.Y, screen_pos.X, screen_pos.Y};
+ SMALL_RECT area;
+ SetUpdateCellArea(area, screen_pos);
_backend->OnConsoleOutputUpdated(&area, 1);
}
return true;
@@ -288,42 +303,82 @@ void ConsoleOutput::ScrollOutputOnOverflow(SMALL_RECT &area)
scr_rect.Top = scr_rect.Bottom = height - 1;
tmp_size.Y = 1;
for (unsigned int i = 0; i < width; ++i) {
- CHAR_INFO &ci = _temp_chars[i];
- ci.Char.UnicodeChar = ' ';
- ci.Attributes = _attributes;
+ CI_SET_WCATTR(_temp_chars[i], L' ', _attributes);
}
_buf.Write(&_temp_chars[0], tmp_size, tmp_pos, scr_rect);
AffectArea(area, scr_rect);
}
-bool ConsoleOutput::ModifySequenceEntityAt(SequenceModifier &sm, COORD pos)
+SHORT ConsoleOutput::ModifySequenceEntityAt(SequenceModifier &sm, COORD pos, SMALL_RECT &area)
{
CHAR_INFO ch;
+ SHORT out = 1;
switch (sm.kind) {
case SequenceModifier::SM_WRITE_STR:
- ch.Char.UnicodeChar = *sm.str;
- ch.Attributes = _attributes;
- if ((_mode&ENABLE_PROCESSED_OUTPUT)!=0 && ch.Char.UnicodeChar==L'\t')
- ch.Char.UnicodeChar = L' ';
+ if (IsCharPrefix(*sm.str)) {
+ out = 0;
+ CI_SET_WCHAR(ch, *sm.str);
+ // surrogate pairs not used for UTF32, so dont need to do special tricks to keep it,
+ // so let following normal character to overwrite abnormal surrogate pair prefixx
+
+ } else if (IsCharSuffix(*sm.str) && _prev_pos.X >= 0) {
+ out = 0;
+ if (!_buf.Read(ch, _prev_pos)) {
+ return false;
+ }
+ pos = _prev_pos;
+ std::wstring tmp;
+ if (CI_USING_COMPOSITE_CHAR(ch)) {
+ tmp = WINPORT(CompositeCharLookup)(ch.Char.UnicodeChar);
+ } else {
+ tmp = ch.Char.UnicodeChar;
+ }
+ tmp+= *sm.str;
+ CI_SET_COMPOSITE(ch, tmp.c_str());
+
+ } else {
+ CI_SET_WCHAR(ch, *sm.str);
+ if ((_mode&ENABLE_PROCESSED_OUTPUT)!=0 && ch.Char.UnicodeChar==L'\t') {
+ CI_SET_WCHAR(ch, L' ');
+ }
+ if (IsCharFullWidth(ch.Char.UnicodeChar)) {
+// fprintf(stderr, "IsCharFullWidth: %lc [0x%llx]\n",
+// (WCHAR)ch.Char.UnicodeChar, (unsigned long long)ch.Char.UnicodeChar);
+ out = 2;
+ }
+ }
+ CI_SET_ATTR(ch, _attributes);
+ _prev_pos = pos;
break;
case SequenceModifier::SM_FILL_CHAR:
if (!_buf.Read(ch, pos))
- return false;
+ return out;
- ch.Char.UnicodeChar = sm.chr;
+ CI_SET_WCHAR(ch, sm.chr);
break;
case SequenceModifier::SM_FILL_ATTR:
if (!_buf.Read(ch, pos))
- return false;
+ return out;
- ch.Attributes = sm.attr;
+ CI_SET_ATTR(ch, sm.attr);
break;
}
- return (_buf.Write(ch, pos) == ConsoleBuffer::WR_MODIFIED);
+ if (_buf.Write(ch, pos) == ConsoleBuffer::WR_MODIFIED) {
+ AffectArea(area, pos.X, pos.Y);
+ if (out == 2) {
+ CI_SET_WCHAR(ch, 0);
+ pos.X++;
+ if (_buf.Write(ch, pos) == ConsoleBuffer::WR_MODIFIED) {
+ AffectArea(area, pos.X, pos.Y);
+ }
+ }
+ }
+
+ return out;
}
size_t ConsoleOutput::ModifySequenceAt(SequenceModifier &sm, COORD &pos)
@@ -333,9 +388,7 @@ size_t ConsoleOutput::ModifySequenceAt(SequenceModifier &sm, COORD &pos)
bool refresh_pos_areas = false;
{
std::lock_guard<std::mutex> lock(_mutex);
- areas[0].Left = areas[0].Right = pos.X;
- areas[0].Top = areas[0].Bottom = pos.Y;
-
+ SetUpdateCellArea(areas[0], pos);
unsigned int width, height;
_buf.GetSize(width, height);
unsigned int scroll_edge = std::min(height, ((unsigned int)_scroll_region.bottom) + 1);
@@ -378,9 +431,7 @@ size_t ConsoleOutput::ModifySequenceAt(SequenceModifier &sm, COORD &pos)
ScrollOutputOnOverflow(areas[2]);
}
} else {
- if (ModifySequenceEntityAt(sm, pos))
- AffectArea(areas[2], pos.X, pos.Y);
- pos.X++;
+ pos.X+= ModifySequenceEntityAt(sm, pos, areas[2]);
}
if (sm.kind==SequenceModifier::SM_WRITE_STR) {
if (*sm.str!=L'\t' || (pos.X%TAB_WIDTH)==0 || (_mode&ENABLE_PROCESSED_OUTPUT)==0) {
@@ -437,10 +488,10 @@ size_t ConsoleOutput::FillCharacterAt(WCHAR cCharacter, size_t count, COORD &pos
}
-size_t ConsoleOutput::FillAttributeAt(WORD wAttribute, size_t count, COORD &pos)
+size_t ConsoleOutput::FillAttributeAt(DWORD64 qAttributes, size_t count, COORD &pos)
{
SequenceModifier sm = {SequenceModifier::SM_FILL_ATTR, count };
- sm.attr = wAttribute;
+ sm.attr = qAttributes;
return ModifySequenceAt(sm, pos);
}
@@ -448,15 +499,23 @@ size_t ConsoleOutput::FillAttributeAt(WORD wAttribute, size_t count, COORD &pos)
static void ClipRect(SMALL_RECT &rect, const SMALL_RECT &clip, COORD *offset = NULL)
{
if (rect.Left < clip.Left) {
- if (offset) offset->X+= clip.Left - rect.Left;
+ if (offset) {
+ offset->X+= clip.Left - rect.Left;
+ }
rect.Left = clip.Left;
}
if (rect.Top < clip.Top) {
- if (offset) offset->Y+= clip.Top - rect.Top;
+ if (offset) {
+ offset->Y+= clip.Top - rect.Top;
+ }
rect.Top = clip.Top;
}
- if (rect.Right > clip.Right) rect.Right = clip.Right;
- if (rect.Bottom > clip.Bottom) rect.Bottom = clip.Bottom;
+ if (rect.Right > clip.Right) {
+ rect.Right = clip.Right;
+ }
+ if (rect.Bottom > clip.Bottom) {
+ rect.Bottom = clip.Bottom;
+ }
}
bool ConsoleOutput::Scroll(const SMALL_RECT *lpScrollRectangle,
@@ -479,11 +538,11 @@ bool ConsoleOutput::Scroll(const SMALL_RECT *lpScrollRectangle,
total_chars*= data_size.Y;
COORD data_pos = {0, 0};
- _temp_chars.resize(total_chars);
areas.n.dst = {dwDestinationOrigin.X, dwDestinationOrigin.Y,
(SHORT)(dwDestinationOrigin.X + data_size.X - 1), (SHORT)(dwDestinationOrigin.Y + data_size.Y - 1)};
{
std::lock_guard<std::mutex> lock(_mutex);
+ _temp_chars.resize(total_chars);
_buf.Read(&_temp_chars[0], data_size, data_pos, areas.n.src);
fprintf(stderr, "!!!!SCROLL:[%i %i %i %i] -> [%i %i %i %i]",
@@ -501,9 +560,10 @@ bool ConsoleOutput::Scroll(const SMALL_RECT *lpScrollRectangle,
areas.n.dst.Left, areas.n.dst.Top, areas.n.dst.Right, areas.n.dst.Bottom,
data_pos.X, data_pos.Y);
}
- fprintf(stderr, "\n");
if (lpFill) {
+ fprintf(stderr, " FILL:[%i %i %i %i]",
+ areas.n.src.Left, areas.n.src.Top, areas.n.src.Right, areas.n.src.Bottom);
COORD fill_pos;
for (fill_pos.Y = areas.n.src.Top; fill_pos.Y <= areas.n.src.Bottom; fill_pos.Y++ )
for (fill_pos.X = areas.n.src.Left; fill_pos.X <= areas.n.src.Right; fill_pos.X++ ) {
@@ -511,6 +571,10 @@ bool ConsoleOutput::Scroll(const SMALL_RECT *lpScrollRectangle,
}
}
+
+ fprintf(stderr, " WRITE:[%i %i %i %i]",
+ areas.n.dst.Left, areas.n.dst.Top, areas.n.dst.Right, areas.n.dst.Bottom);
+ fprintf(stderr, "\n");
_buf.Write(&_temp_chars[0], data_size, data_pos, areas.n.dst);
}
@@ -588,6 +652,11 @@ bool ConsoleOutput::SetFKeyTitles(const CHAR **titles)
return (_backend && _backend->OnConsoleSetFKeyTitles(titles));
}
+BYTE ConsoleOutput::GetColorPalette()
+{
+ return _backend ? _backend->OnConsoleGetColorPalette() : 4;
+}
+
const WCHAR *ConsoleOutput::LockedGetTitle()
{
_mutex.lock();
diff --git a/WinPort/src/ConsoleOutput.h b/WinPort/src/ConsoleOutput.h
index 5825b2e0..c25fdddf 100644
--- a/WinPort/src/ConsoleOutput.h
+++ b/WinPort/src/ConsoleOutput.h
@@ -14,7 +14,8 @@ class ConsoleOutput : public IConsoleOutput
std::wstring _title;
IConsoleOutputBackend *_backend;
DWORD _mode;
- USHORT _attributes;
+ DWORD64 _attributes;
+ COORD _prev_pos{-1, -1};
struct {
COORD pos;
@@ -43,24 +44,25 @@ class ConsoleOutput : public IConsoleOutput
union {
const WCHAR *str;
TCHAR chr;
- WORD attr;
+ DWORD64 attr;
};
};
- bool ModifySequenceEntityAt(SequenceModifier &sm, COORD pos);
+ SHORT ModifySequenceEntityAt(SequenceModifier &sm, COORD pos, SMALL_RECT &area);
size_t ModifySequenceAt(SequenceModifier &sm, COORD &pos);
void ScrollOutputOnOverflow(SMALL_RECT &area);
virtual const WCHAR *LockedGetTitle();
virtual CHAR_INFO *LockedDirectLineAccess(size_t line_index, unsigned int &width);
virtual void Unlock();
+ void SetUpdateCellArea(SMALL_RECT &area, COORD pos);
public:
ConsoleOutput();
virtual void SetBackend(IConsoleOutputBackend *listener);
- virtual void SetAttributes(USHORT attributes);
- virtual USHORT GetAttributes();
+ virtual void SetAttributes(DWORD64 attributes);
+ virtual DWORD64 GetAttributes();
virtual void SetCursor(COORD pos);
virtual void SetCursor(UCHAR height, bool visible);
virtual COORD GetCursor();
@@ -86,7 +88,7 @@ public:
virtual size_t WriteString(const WCHAR *data, size_t count);
virtual size_t WriteStringAt(const WCHAR *data, size_t count, COORD &pos);
virtual size_t FillCharacterAt(WCHAR cCharacter, size_t count, COORD &pos);
- virtual size_t FillAttributeAt(WORD wAttribute, size_t count, COORD &pos);
+ virtual size_t FillAttributeAt(DWORD64 qAttribute, size_t count, COORD &pos);
virtual bool Scroll(const SMALL_RECT *lpScrollRectangle, const SMALL_RECT *lpClipRectangle,
COORD dwDestinationOrigin, const CHAR_INFO *lpFill);
@@ -102,4 +104,5 @@ public:
virtual void ConsoleDisplayNotification(const WCHAR *title, const WCHAR *text);
virtual bool ConsoleBackgroundMode(bool TryEnterBackgroundMode);
virtual bool SetFKeyTitles(const CHAR **titles);
+ virtual BYTE GetColorPalette();
};
diff --git a/far2l/CMakeLists.txt b/far2l/CMakeLists.txt
index 145007e0..220ecb15 100644
--- a/far2l/CMakeLists.txt
+++ b/far2l/CMakeLists.txt
@@ -151,6 +151,7 @@ src/mix/processname.cpp
src/mix/RegExp.cpp
src/mix/strmix.cpp
src/mix/FSFileFlags.cpp
+src/mix/StrCells.cpp
)
# Set target names for the executables
diff --git a/far2l/far2sdk/farplug-mb.h b/far2l/far2sdk/farplug-mb.h
index 7bd8581c..5adb2399 100644
--- a/far2l/far2sdk/farplug-mb.h
+++ b/far2l/far2sdk/farplug-mb.h
@@ -1457,8 +1457,9 @@ namespace oldfar
typedef char *(WINAPI *FARSTDLTRIM)(char *Str);
typedef char *(WINAPI *FARSTDRTRIM)(char *Str);
typedef char *(WINAPI *FARSTDTRIM)(char *Str);
- typedef char *(WINAPI *FARSTDTRUNCSTR)(char *Str,int MaxLength);
- typedef char *(WINAPI *FARSTDTRUNCPATHSTR)(char *Str,int MaxLength);
+ // truncation functions below uses console cells count as limiting unit
+ typedef char *(WINAPI *FARSTDTRUNCSTR)(char *Str,int MaxCells);
+ typedef char *(WINAPI *FARSTDTRUNCPATHSTR)(char *Str,int MaxCells);
typedef char *(WINAPI *FARSTDQUOTESPACEONLY)(char *Str);
typedef char*(WINAPI *FARSTDPOINTTONAME)(char *Path);
typedef void (WINAPI *FARSTDGETPATHROOT)(const char *Path,char *Root);
@@ -1552,11 +1553,25 @@ namespace oldfar
};
- typedef int (WINAPI *FAREXECUTE)(const char *CmdStr, unsigned int ExecFlags);
+ typedef int (WINAPI *FAREXECUTE)(const char *CmdStr, unsigned int ExecFlags);
typedef int (WINAPI *FAREXECUTE_LIBRARY)(const char *Library, const char *Symbol, const char *CmdStr, unsigned int ExecFlags);
typedef void (WINAPI *FARDISPLAYNOTIFICATION)(const char *action, const char *object);
typedef int (WINAPI *FARDISPATCHNTRTHRDCALLS)();
+ // If plugin implements tasks running in background it may invoke this function to indicate about
+ // pending task in left-top corner. Info is a short description of task or just its owner and must
+ // be same string when invoked with Started TRUE or FALSE.
typedef void (WINAPI *FARBACKGROUNDTASK)(const char *Info, BOOL Started);
+ // Returns count of console cells which will be used to display given string of CharsCount characters.
+ typedef size_t (WINAPI *FARSTRCELLSCOUNT)(const char *Str, size_t CharsCount);
+ // Returns count of characters which will be used for fill up to *CellsCount cells from given string
+ // of CharsCount characters.
+ // RoundUp argument tells what to do with full-width characters that crossed by *CellsCount.
+ // On return *CellsCount contains cells count that will be filled by returned characters count, that:
+ // Can be smaller than initial value if string has too few characters to fill all *CellsCount cells
+ // or if RoundUp was set to FALSE and last character would then overflow wanted amount.
+ // Can be larger by one than initial value if RoundUp was set to TRUE and last full-width character
+ // crossed initial value specified in *CellsCount.
+ typedef size_t (WINAPI *FARSTRSIZEOFCELLS)(const char *Str, size_t CharsCount, size_t *CellsCount, BOOL RoundUp);
typedef struct FarStandardFunctions
{
@@ -1611,6 +1626,8 @@ namespace oldfar
FARDISPLAYNOTIFICATION DisplayNotification;
FARDISPATCHNTRTHRDCALLS DispatchInterThreadCalls;
FARBACKGROUNDTASK BackgroundTask;
+ FARSTRCELLSCOUNT StrCellsCount;
+ FARSTRSIZEOFCELLS StrSizeOfCells;
} FARSTANDARDFUNCTIONS;
struct PluginStartupInfo
diff --git a/far2l/far2sdk/farplug-wide.h b/far2l/far2sdk/farplug-wide.h
index fed3fb2f..09bc01ac 100644
--- a/far2l/far2sdk/farplug-wide.h
+++ b/far2l/far2sdk/farplug-wide.h
@@ -1836,8 +1836,9 @@ typedef wchar_t *(WINAPI *FARSTDITOA)(int value, wchar_t *string, int radix);
typedef wchar_t *(WINAPI *FARSTDLTRIM)(wchar_t *Str);
typedef wchar_t *(WINAPI *FARSTDRTRIM)(wchar_t *Str);
typedef wchar_t *(WINAPI *FARSTDTRIM)(wchar_t *Str);
-typedef wchar_t *(WINAPI *FARSTDTRUNCSTR)(wchar_t *Str,int MaxLength);
-typedef wchar_t *(WINAPI *FARSTDTRUNCPATHSTR)(wchar_t *Str,int MaxLength);
+// truncation functions below uses console cells count as limiting unit
+typedef wchar_t *(WINAPI *FARSTDTRUNCSTR)(wchar_t *Str,int MaxCells);
+typedef wchar_t *(WINAPI *FARSTDTRUNCPATHSTR)(wchar_t *Str,int MaxCells);
typedef wchar_t *(WINAPI *FARSTDQUOTESPACEONLY)(wchar_t *Str);
typedef const wchar_t*(WINAPI *FARSTDPOINTTONAME)(const wchar_t *Path);
typedef int (WINAPI *FARSTDGETPATHROOT)(const wchar_t *Path,wchar_t *Root, int DestSize);
@@ -1941,7 +1942,21 @@ typedef int (WINAPI *FAREXECUTE)(const wchar_t *CmdStr, unsigned int ExecFlags);
typedef int (WINAPI *FAREXECUTE_LIBRARY)(const wchar_t *Library, const wchar_t *Symbol, const wchar_t *CmdStr, unsigned int ExecFlags);
typedef void (WINAPI *FARDISPLAYNOTIFICATION)(const wchar_t *action, const wchar_t *object);
typedef int (WINAPI *FARDISPATCHNTRTHRDCALLS)();
+// If plugin implements tasks running in background it may invoke this function to indicate about
+// pending task in left-top corner. Info is a short description of task or just its owner and must
+// be same string when invoked with Started TRUE or FALSE.
typedef void (WINAPI *FARBACKGROUNDTASK)(const wchar_t *Info, BOOL Started);
+// Returns count of console cells which will be used to display given string of CharsCount characters.
+typedef size_t (WINAPI *FARSTRCELLSCOUNT)(const wchar_t *Str, size_t CharsCount);
+// Returns count of characters which will be used for fill up to *CellsCount cells from given string
+// of CharsCount characters.
+// RoundUp argument tells what to do with full-width characters that crossed by *CellsCount.
+// On return *CellsCount contains cells count that will be filled by returned characters count, that:
+// Can be smaller than initial value if string has too few characters to fill all *CellsCount cells
+// or if RoundUp was set to FALSE and last character would then overflow wanted amount.
+// Can be larger by one than initial value if RoundUp was set to TRUE and last full-width character
+// crossed initial value specified in *CellsCount.
+typedef size_t (WINAPI *FARSTRSIZEOFCELLS)(const wchar_t *Str, size_t CharsCount, size_t *CellsCount, BOOL RoundUp);
enum BOX_DEF_SYMBOLS
{
@@ -2061,6 +2076,8 @@ typedef struct FarStandardFunctions
FARDISPLAYNOTIFICATION DisplayNotification;
FARDISPATCHNTRTHRDCALLS DispatchInterThreadCalls;
FARBACKGROUNDTASK BackgroundTask;
+ FARSTRCELLSCOUNT StrCellsCount;
+ FARSTRSIZEOFCELLS StrSizeOfCells;
} FARSTANDARDFUNCTIONS;
struct PluginStartupInfo
diff --git a/far2l/src/Mounts.cpp b/far2l/src/Mounts.cpp
index f8c49ee8..febcb2b8 100644
--- a/far2l/src/Mounts.cpp
+++ b/far2l/src/Mounts.cpp
@@ -80,12 +80,12 @@ namespace Mounts
ConfigReader cfg_reader(HOTKEYS_SECTION);
for (auto &m : *this) {
- if (max_path < m.path.GetLength())
- max_path = m.path.GetLength();
- if (max_col3 < m.col3.GetLength())
- max_col3 = m.col3.GetLength();
- if (max_col2 < m.col2.GetLength())
- max_col2 = m.col2.GetLength();
+ if (max_path < m.path.CellsCount())
+ max_path = m.path.CellsCount();
+ if (max_col3 < m.col3.CellsCount())
+ max_col3 = m.col3.CellsCount();
+ if (max_col2 < m.col2.CellsCount())
+ max_col2 = m.col2.CellsCount();
wchar_t def_hk[] = {DefaultHotKey(m.id, m.path), 0};
auto hk = cfg_reader.GetString(SettingsKey(m.id), def_hk);
m.hotkey = hk.IsEmpty() ? 0 : *hk.CPtr();
diff --git a/far2l/src/ViewerPrinter.cpp b/far2l/src/ViewerPrinter.cpp
index 36eea048..cacf746e 100644
--- a/far2l/src/ViewerPrinter.cpp
+++ b/far2l/src/ViewerPrinter.cpp
@@ -50,7 +50,10 @@ int PlainViewerPrinter::Length(const wchar_t *str, int limit)
int out;
for (out = 0; *str && limit != 0; ++str, --limit) {
if (!ShouldSkip(*str)) {
- ++out;
+ if (IsCharFullWidth(*str))
+ out+= 2;
+ else if (!IsCharXxxfix(*str))
+ ++out;
}
}
return out;
@@ -59,30 +62,37 @@ int PlainViewerPrinter::Length(const wchar_t *str, int limit)
void PlainViewerPrinter::Print(int skip_len, int print_len, const wchar_t *str)
{
SetColor(_selection ? COL_VIEWERSELECTEDTEXT : _color);
- while (*str && skip_len) {
- --skip_len;
- ++str;
+
+ for(; skip_len > 0 && *str; ++str) {
+ if (ShouldSkip(*str))
+ ;
+ else if (IsCharFullWidth(*str))
+ skip_len-= 2;
+ else if (!IsCharXxxfix(*str))
+ skip_len--;
}
- int str_print_len;
- for (int i = str_print_len = 0;; ) {
- if (!str[i] || str_print_len + i >= print_len || ShouldSkip(str[i])) {
- if (i) {
- Text(str, i);
- str_print_len+= i;
- }
- if (!str[i] || str_print_len + i >= print_len) {
- break;
+ for (;;) {
+ size_t piece = 0;
+ while (str[piece] && !ShouldSkip(str[piece])) {
+ ++piece;
+ }
+ if (piece) {
+ size_t cells = print_len;
+ piece = StrSizeOfCells(str, piece, cells, false);
+ if (piece) {
+ Text(str, piece);
+ print_len-= (int)cells;
+ str+= piece;
}
- str+= i + 1;
- i = 0;
-
- } else {
- ++i;
}
+ if (!str[piece]) {
+ break;
+ }
+ str+= piece + 1;
}
- if (print_len > str_print_len) {
- PrintSpaces(print_len - str_print_len);
+ if (print_len > 0) {
+ PrintSpaces(print_len);
}
}
diff --git a/far2l/src/base/FARString.cpp b/far2l/src/base/FARString.cpp
index d087ccb0..4a40327d 100644
--- a/far2l/src/base/FARString.cpp
+++ b/far2l/src/base/FARString.cpp
@@ -290,6 +290,16 @@ FARString& FARString::Append(const char *lpszAdd, UINT CodePage)
return *this;
}
+FARString& FARString::Append(wchar_t Ch, size_t Count)
+{
+ size_t nNewLength = m_pContent->GetLength() + Count;
+ PrepareForModify(nNewLength);
+ wmemset(m_pContent->GetData() + m_pContent->GetLength(), Ch, Count);
+ m_pContent->SetLength(nNewLength);
+
+ return *this;
+}
+
FARString& FARString::Copy(const FARString &Str)
{
auto prev_pContent = m_pContent;
@@ -549,3 +559,19 @@ std::string FARString::GetMB() const
Wide2MB(CPtr(), GetLength(), out);
return out;
}
+
+size_t FARString::CellsCount() const
+{
+ return StrCellsCount(CPtr(), GetLength());
+}
+
+size_t FARString::TruncateByCells(size_t nCount)
+{
+ size_t ng = CellsCount();
+ if (ng > nCount) {
+ size_t ng = nCount;
+ auto sz = StrSizeOfCells(CPtr(), GetLength(), ng, false);
+ Truncate(sz);
+ }
+ return ng;
+}
diff --git a/far2l/src/base/FARString.hpp b/far2l/src/base/FARString.hpp
index 93a26dd1..b19aabfd 100644
--- a/far2l/src/base/FARString.hpp
+++ b/far2l/src/base/FARString.hpp
@@ -141,6 +141,9 @@ public:
inline size_t GetLength() const { return m_pContent->GetLength(); }
size_t Truncate(size_t nLength);
+ size_t CellsCount() const;
+ size_t TruncateByCells(size_t nCount);
+
inline wchar_t At(size_t nIndex) const { return m_pContent->GetData()[nIndex]; }
inline bool IsEmpty() const { return !(m_pContent->GetLength() && *m_pContent->GetData()); }
@@ -160,7 +163,8 @@ public:
FARString& Append(const wchar_t* Str, size_t StrLen) { return Replace(GetLength(), 0, Str, StrLen); }
FARString& Append(const FARString& Str) { return Append(Str.CPtr(), Str.GetLength()); }
FARString& Append(const wchar_t* Str) { return Append(Str, StrLength(NullToEmpty(Str))); }
- FARString& Append(wchar_t Ch) { return Append(&Ch, 1); }
+ FARString& Append(wchar_t Ch, size_t Count);
+ FARString& Append(wchar_t Ch) { return Append(Ch, 1); }
FARString& Append(const char *lpszAdd, UINT CodePage=CP_UTF8);
FARString& Insert(size_t Pos, const wchar_t* Str, size_t StrLen) { return Replace(Pos, 0, Str, StrLen); }
diff --git a/far2l/src/cmdline.cpp b/far2l/src/cmdline.cpp
index 9037bf91..c042c20c 100644
--- a/far2l/src/cmdline.cpp
+++ b/far2l/src/cmdline.cpp
@@ -116,8 +116,7 @@ void CommandLine::DisplayObject()
SetColor(COL_COMMANDLINEPREFIX);
Text(strTruncDir);
CmdStr.SetObjectColor(COL_COMMANDLINE,COL_COMMANDLINESELECTED);
-
- CmdStr.SetPosition(X1+(int)strTruncDir.GetLength(),Y1,X2,Y2);
+ CmdStr.SetPosition(X1+(int)strTruncDir.CellsCount(),Y1,X2,Y2);
CmdStr.Show();
@@ -667,9 +666,7 @@ void CommandLine::GetPrompt(FARString &strDestStr)
{
if (PushDirStackSize)
{
- wchar_t * p = strDestStr.GetBuffer(strDestStr.GetLength()+PushDirStackSize+1);
- wmemset(p + strDestStr.GetLength(),L'+',PushDirStackSize);
- strDestStr.ReleaseBuffer(strDestStr.GetLength()+PushDirStackSize);
+ strDestStr.Append(L'+', PushDirStackSize);
}
break;
diff --git a/far2l/src/console/AnsiEsc.cpp b/far2l/src/console/AnsiEsc.cpp
index 0bcf536b..3dc43aa0 100644
--- a/far2l/src/console/AnsiEsc.cpp
+++ b/far2l/src/console/AnsiEsc.cpp
@@ -2,6 +2,7 @@
#include "AnsiEsc.hpp"
#include "interf.hpp"
#include "colors.hpp"
+#include "VT256ColorTable.h"
namespace AnsiEsc
{
@@ -54,7 +55,7 @@ static const BYTE BackgroundColor[16] = {
};
-static const BYTE Attr2Ansi[8] = { // map console attribute to ANSI number
+const BYTE Attr2Ansi[8] = { // map console attribute to ANSI number
0, // black
4, // blue
2, // green
@@ -65,6 +66,12 @@ static const BYTE Attr2Ansi[8] = { // map console attribute to ANSI number
7 // white
};
+BYTE ConsoleColorToAnsi(BYTE clr)
+{
+ return Attr2Ansi[clr & 7] | (clr & 8);
+}
+
+
/////////////////
void FontState::ParseSuffixM(const int *args, int argc)
{
@@ -78,15 +85,19 @@ void FontState::ParseSuffixM(const int *args, int argc)
const int a = args[i];
if (30 <= a && a <= 37) {
foreground = a - 30;
+ use_rgb_foreground = false;
} else if (90 <= a && a <= 97) {
foreground = (a - 90) + 8;
+ use_rgb_foreground = false;
} else if (40 <= a && a <= 47) {
background = a - 40;
+ use_rgb_background = false;
} else if (100 <= a && a <= 107) {
background = (a - 100) + 8;
+ use_rgb_background = false;
} else if (a == 38 || a == 48) {
// This is technically incorrect, but it's what xterm does, so
@@ -94,11 +105,41 @@ void FontState::ParseSuffixM(const int *args, int argc)
// only one parameter, which is divided into elements. So where
// xterm does "38;2;R;G;B" it should really be "38;2:I:R:G:B" (I is
// a colour space identifier).
- if (i + 1 < argc) {
- if (args[i + 1] == 2) // rgb
- i += 4;
- else if (args[i + 1] == 5) // index
- i += 2;
+ DWORD rgb = (DWORD)-1;
+ if (i + 4 < argc && args[i + 1] == 2) {
+ rgb = args[i + 2] | (args[i + 3] << 8) | (args[i + 4] << 16);
+ i+= 4;
+
+ } else if (i + 2 < argc && args[i + 1] == 5) {
+ unsigned int color_index = args[i + 2];
+ if (color_index < 16) {
+ if (a == 38) {
+ foreground = (BYTE)color_index;
+ use_rgb_foreground = false;
+ } else {
+ background = (BYTE)color_index;
+ use_rgb_background = false;
+ }
+
+ } else if (color_index - 16 < VT_256COLOR_TABLE_COUNT) {
+ rgb = g_VT256ColorTable[color_index - 16];
+ }
+ i+= 2;
+
+ } else {
+ fprintf(stderr, "ParseSuffixM: bad RGB color\n");
+ }
+
+ if (rgb == (DWORD)-1) {
+ ;// nothing
+
+ } else if (a == 38) {
+ use_rgb_foreground = true;
+ rgb_foreground = rgb;
+
+ } else {
+ use_rgb_background = true;
+ rgb_background = rgb;
}
} else switch (a) {
@@ -110,13 +151,16 @@ void FontState::ParseSuffixM(const int *args, int argc)
case 39:
case 49: {
- const BYTE def_attr = 7;//FOREGROUND_WHITE;
- reverse = false;
+ rvideo = false;
if (a != 49) {
- foreground = Attr2Ansi[def_attr & 15];
+ foreground = 7; // white
+ use_rgb_foreground = false;
+ rgb_foreground = 0;
}
if (a != 39) {
- background = Attr2Ansi[(def_attr >> 4) & 15];
+ background = 0; // black
+ use_rgb_background = false;
+ rgb_background = 0;
}
} break;
@@ -126,7 +170,7 @@ void FontState::ParseSuffixM(const int *args, int argc)
case 5: // blink
case 4:
underline = true;
- break;
+ break;
case 7:
rvideo = 1;
break;
@@ -152,50 +196,60 @@ void FontState::ParseSuffixM(const int *args, int argc)
}
}
-void FontState::FromConsoleAttributes(WORD wAttributes)
+void FontState::FromConsoleAttributes(DWORD64 qAttributes)
{
- bold = (wAttributes & FOREGROUND_INTENSITY) != 0;
- underline = (wAttributes & BACKGROUND_INTENSITY) != 0;
- foreground = Attr2Ansi[wAttributes & 7];
- background = Attr2Ansi[(wAttributes >> 4) & 7];
+ bold = (qAttributes & FOREGROUND_INTENSITY) != 0;
+ underline = (qAttributes & COMMON_LVB_UNDERSCORE) != 0;
+ rvideo = (qAttributes & COMMON_LVB_REVERSE_VIDEO) != 0;
+ foreground = Attr2Ansi[qAttributes & 7];
+ background = Attr2Ansi[(qAttributes >> 4) & 7];
+
+ use_rgb_foreground = (qAttributes & FOREGROUND_TRUECOLOR) != 0;
+ if (use_rgb_foreground) {
+ rgb_foreground = GET_RGB_FORE(qAttributes);
+ }
+
+ use_rgb_background = (qAttributes & BACKGROUND_TRUECOLOR) != 0;
+ if (use_rgb_background) {
+ rgb_background = GET_RGB_BACK(qAttributes);
+ }
}
-WORD FontState::ToConsoleAttributes()
+DWORD64 FontState::ToConsoleAttributes()
{
- WORD attribut = 0;
+ DWORD64 attribut = 0;
if (concealed) {
- if (rvideo) {
- attribut = ForegroundColor[foreground] | BackgroundColor[foreground];
- if (bold) {
- attribut|= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
- }
- } else {
- attribut = ForegroundColor[background] | BackgroundColor[background];
- if (underline) {
- attribut|= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
- }
- }
- } else if (rvideo) {
- attribut = ForegroundColor[background] | BackgroundColor[foreground];
- if (bold) {
- attribut|= BACKGROUND_INTENSITY;
- }
- if (underline) {
- attribut|= FOREGROUND_INTENSITY;
+ attribut = ForegroundColor[background] | BackgroundColor[background];
+
+ if (use_rgb_background) {
+ SET_RGB_BOTH(attribut, rgb_background, rgb_background);
}
+
} else {
attribut = ForegroundColor[foreground] | BackgroundColor[background];
- if (bold) {
- attribut|= FOREGROUND_INTENSITY;
+
+ if (use_rgb_foreground) {
+ SET_RGB_FORE(attribut, rgb_foreground);
}
- if (underline) {
- attribut|= BACKGROUND_INTENSITY;
+
+ if (use_rgb_background) {
+ SET_RGB_BACK(attribut, rgb_background);
}
}
- if (reverse) {
- attribut = ((attribut >> 4) & 15) | ((attribut & 15) << 4);
+
+ if (bold) {
+ attribut|= FOREGROUND_INTENSITY;
+ }
+
+ if (rvideo) {
+ attribut|= COMMON_LVB_REVERSE_VIDEO;
+ }
+
+ if (underline) {
+ attribut|= COMMON_LVB_UNDERSCORE;
}
+
return attribut;
}
diff --git a/far2l/src/console/AnsiEsc.hpp b/far2l/src/console/AnsiEsc.hpp
index 7dba73c6..084a002d 100644
--- a/far2l/src/console/AnsiEsc.hpp
+++ b/far2l/src/console/AnsiEsc.hpp
@@ -6,19 +6,26 @@
namespace AnsiEsc
{
+ BYTE ConsoleColorToAnsi(BYTE clr);
+
struct FontState
{
- BYTE foreground = false; // ANSI base color (0 to 7; add 30)
- BYTE background = false; // ANSI base color (0 to 7; add 40)
+ BYTE foreground = 0; // ANSI base color (0 to 7; add 30)
+ BYTE background = 0; // ANSI base color (0 to 7; add 40)
bool bold = false; //
bool underline = false; //
- bool rvideo = false; // swap foreground/bold & background/underline
+ bool rvideo = false; // swap console foreground & background attributes
bool concealed = false; // set foreground/bold to background/underline
- bool reverse = false; // swap console foreground & background attributes
+
+ bool use_rgb_foreground = false;
+ bool use_rgb_background = false;
+
+ DWORD rgb_foreground = 0;
+ DWORD rgb_background = 0;
void ParseSuffixM(const int *args, int argc);
- void FromConsoleAttributes(WORD wAttributes);
- WORD ToConsoleAttributes();
+ void FromConsoleAttributes(DWORD64 qAttributes);
+ DWORD64 ToConsoleAttributes();
};
struct Parser
diff --git a/far2l/src/console/interf.cpp b/far2l/src/console/interf.cpp
index d4f83422..2cd2503c 100644
--- a/far2l/src/console/interf.cpp
+++ b/far2l/src/console/interf.cpp
@@ -572,24 +572,37 @@ void Text(const WCHAR *Str, size_t Length)
PCHAR_INFO HeapBuffer=nullptr;
PCHAR_INFO BufPtr=StackBuffer;
- if (Length >= StackBufferSize)
+ if (Length * 2 >= StackBufferSize)
{
- HeapBuffer=new CHAR_INFO[Length+1];
+ HeapBuffer=new CHAR_INFO[Length * 2 + 1];
BufPtr=HeapBuffer;
}
- for (size_t i=0; i < Length; i++)
+ int nCells = 0;
+ std::wstring wstr;
+ for (size_t i = 0; i < Length; ++nCells)
{
- BufPtr[i].Char.UnicodeChar=Str[i];
- BufPtr[i].Attributes=CurColor;
+ const size_t nG = StrSizeOfCell(&Str[i], Length - i);
+ if (nG > 1) {
+ wstr.assign(&Str[i], nG);
+ CI_SET_COMPOSITE(BufPtr[nCells], wstr.c_str());
+ } else {
+ CI_SET_WCHAR(BufPtr[nCells], Str[i]);
+ }
+ CI_SET_ATTR(BufPtr[nCells], CurColor);
+ if (IsCharFullWidth(Str[i])) {
+ ++nCells;
+ CI_SET_WCATTR(BufPtr[nCells], 0, CurColor);
+ }
+ i+= nG;
}
- ScrBuf.Write(CurX, CurY, BufPtr, static_cast<int>(Length));
+ ScrBuf.Write(CurX, CurY, BufPtr, nCells);
if(HeapBuffer)
{
delete[] HeapBuffer;
}
- CurX+=static_cast<int>(Length);
+ CurX+= nCells;
}
@@ -1082,7 +1095,7 @@ FARString& HiText2Str(FARString& strDest, const wchar_t *Str)
return strDest;
}
-int HiStrlen(const wchar_t *Str)
+int HiStrCellsCount(const wchar_t *Str)
{
/*
&& = '&'
@@ -1123,8 +1136,11 @@ int HiStrlen(const wchar_t *Str)
}
else
{
+ if (IsCharFullWidth(*Str))
+ Length+= 2;
+ else if (!IsCharXxxfix(*Str))
+ Length+= 1;
Str++;
- Length++;
}
}
}
@@ -1169,8 +1185,11 @@ int HiFindRealPos(const wchar_t *Str, int Pos, BOOL ShowAmp)
}
}
+ if (IsCharFullWidth(*Str))
+ VisPos+= 2;
+ else if (!IsCharXxxfix(*Str))
+ VisPos+= 1;
Str++;
- VisPos++;
RealPos++;
}
}
@@ -1207,6 +1226,9 @@ int HiFindNextVisualPos(const wchar_t *Str, int Pos, int Direct)
return Pos-2;
}
+ if (IsCharFullWidth(Str[Pos - 1]) && Pos > 1)
+ return Pos-2;
+
return Pos-1;
}
else
@@ -1231,7 +1253,7 @@ int HiFindNextVisualPos(const wchar_t *Str, int Pos, int Direct)
}
else
{
- return Pos+1;
+ return IsCharFullWidth(*Str) ? Pos + 2 : Pos + 1;
}
}
}
diff --git a/far2l/src/console/interf.hpp b/far2l/src/console/interf.hpp
index fb16c6f6..35e05e64 100644
--- a/far2l/src/console/interf.hpp
+++ b/far2l/src/console/interf.hpp
@@ -119,12 +119,12 @@ void InitRecodeOutTable();
int WINAPI TextToCharInfo(const char *Text,WORD Attr, CHAR_INFO *CharInfo, int Length, DWORD Reserved);
-inline void SetVidChar(CHAR_INFO& CI,wchar_t Chr)
+inline void SetVidChar(CHAR_INFO& CI, COMP_CHAR Chr)
{
CI.Char.UnicodeChar = (Chr >= 0 && (Chr < L'\x20' || Chr == L'\x7f')) ? Oem2Unicode[Chr] : Chr;
}
-int HiStrlen(const wchar_t *Str);
+int HiStrCellsCount(const wchar_t *Str);
int HiFindRealPos(const wchar_t *Str, int Pos, BOOL ShowAmp);
int HiFindNextVisualPos(const wchar_t *Str, int Pos, int Direct);
FARString& HiText2Str(FARString& strDest, const wchar_t *Str);
diff --git a/far2l/src/copy.cpp b/far2l/src/copy.cpp
index 1015ace8..57f274e9 100644
--- a/far2l/src/copy.cpp
+++ b/far2l/src/copy.cpp
@@ -284,7 +284,7 @@ void CopyProgress::SetScanName(const wchar_t *Name)
}
GotoXY(Rect.Left+5,Rect.Top+3);
- FS<<fmt::LeftAlign()<<fmt::Width(Rect.Right-Rect.Left-9)<<fmt::Precision(Rect.Right-Rect.Left-9)<<Name;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(Rect.Right - Rect.Left - 9) << Name;
Flush();
}
@@ -369,10 +369,10 @@ void CopyProgress::SetNames(const wchar_t *Src,const wchar_t *Dst)
}
FormatString FString;
- FString<<fmt::LeftAlign()<<fmt::Width(Rect.Right-Rect.Left-9)<<fmt::Precision(Rect.Right-Rect.Left-9)<<Src;
+ FString << fmt::Cells() << fmt::LeftAlign() << fmt::Size(Rect.Right - Rect.Left - 9) << Src;
strSrc=std::move(FString.strValue());
FString.Clear();
- FString<<fmt::LeftAlign()<<fmt::Width(Rect.Right-Rect.Left-9)<<fmt::Precision(Rect.Right-Rect.Left-9)<<Dst;
+ FString << fmt::Cells() << fmt::LeftAlign() << fmt::Size(Rect.Right - Rect.Left - 9) << Dst;
strDst=std::move(FString.strValue());
if (Total)
@@ -424,7 +424,7 @@ void CopyProgress::SetProgress(bool TotalProgress,UINT64 CompletedSize,UINT64 To
Bar[BarLength]=0;
Percents=ToPercent64(CompletedSize,TotalSize);
FormatString strPercents;
- strPercents<<fmt::Width(4)<<Percents<<L"%";
+ strPercents<<fmt::Expand(4)<<Percents<<L"%";
Text(BarCoord.X,BarCoord.Y,Color,Bar);
Text(static_cast<int>(BarCoord.X+BarLength),BarCoord.Y,Color,strPercents);
@@ -3289,9 +3289,11 @@ int ShellCopy::AskOverwrite(const FAR_FIND_DATA_EX &SrcData,
strDestSizeText<<DestSize;
FARString strDateText, strTimeText;
ConvertDate(SrcLastWriteTime,strDateText,strTimeText,8,FALSE,FALSE,TRUE,TRUE);
- strSrcFileStr<<fmt::LeftAlign()<<fmt::Width(17)<<Msg::CopySource<<L" "<<fmt::Width(25)<<fmt::Precision(25)<<strSrcSizeText<<L" "<<strDateText<<L" "<<strTimeText;
+ strSrcFileStr << fmt::Cells() << fmt::LeftAlign() << fmt::Expand(17) << Msg::CopySource
+ << L" " << fmt::Size(25) << strSrcSizeText << L" " << strDateText << L" " << strTimeText;
ConvertDate(DestData.ftLastWriteTime,strDateText,strTimeText,8,FALSE,FALSE,TRUE,TRUE);
- strDestFileStr<<fmt::LeftAlign()<<fmt::Width(17)<<Msg::CopyDest<<L" "<<fmt::Width(25)<<fmt::Precision(25)<<strDestSizeText<<L" "<<strDateText<<L" "<<strTimeText;
+ strDestFileStr << fmt::Cells() << fmt::LeftAlign() << fmt::Expand(17) << Msg::CopyDest
+ << L" " << fmt::Size(25) << strDestSizeText << L" " << strDateText << L" " << strTimeText;
WarnCopyDlgData[WDLG_SRCFILEBTN].Data=strSrcFileStr;
WarnCopyDlgData[WDLG_DSTFILEBTN].Data=strDestFileStr;
@@ -3389,9 +3391,9 @@ int ShellCopy::AskOverwrite(const FAR_FIND_DATA_EX &SrcData,
FormatString strDestSizeText;
strDestSizeText<<DestSize;
ConvertDate(SrcData.ftLastWriteTime,strDateText,strTimeText,8,FALSE,FALSE,TRUE,TRUE);
- strSrcFileStr<<fmt::LeftAlign()<<fmt::Width(17)<<Msg::CopySource<<L" "<<fmt::Width(25)<<fmt::Precision(25)<<strSrcSizeText<<L" "<<strDateText<<L" "<<strTimeText;
+ strSrcFileStr << fmt::Cells() << fmt::LeftAlign() << fmt::Expand(17) << Msg::CopySource << L" " << fmt::Size(25) << strSrcSizeText << L" " << strDateText << L" " << strTimeText;
ConvertDate(DestData.ftLastWriteTime,strDateText,strTimeText,8,FALSE,FALSE,TRUE,TRUE);
- strDestFileStr<<fmt::LeftAlign()<<fmt::Width(17)<<Msg::CopyDest<<L" "<<fmt::Width(25)<<fmt::Precision(25)<<strDestSizeText<<L" "<<strDateText<<L" "<<strTimeText;
+ strDestFileStr << fmt::Cells() << fmt::LeftAlign() << fmt::Expand(17) << Msg::CopyDest << L" " << fmt::Size(25) << strDestSizeText << L" " << strDateText << L" " << strTimeText;
WarnCopyDlgData[WDLG_SRCFILEBTN].Data=strSrcFileStr;
WarnCopyDlgData[WDLG_DSTFILEBTN].Data=strDestFileStr;
WarnCopyDlgData[WDLG_TEXT].Data=Msg::CopyFileRO;
diff --git a/far2l/src/datetime.cpp b/far2l/src/datetime.cpp
index 939a69ff..93fd125d 100644
--- a/far2l/src/datetime.cpp
+++ b/far2l/src/datetime.cpp
@@ -788,7 +788,7 @@ void ConvertDate(const FILETIME &ft,FARString &strDateText, FARString &strTimeTe
break;
}
FormatString Fmt;
- Fmt<<fmt::FillChar(f1)<<fmt::Width(w1)<<p1<<DateSeparator<<fmt::FillChar(f2)<<fmt::Width(w2)<<p2<<DateSeparator<<fmt::FillChar(f3)<<fmt::Width(w3)<<p3;
+ Fmt<<fmt::FillChar(f1)<<fmt::Expand(w1)<<p1<<DateSeparator<<fmt::FillChar(f2)<<fmt::Expand(w2)<<p2<<DateSeparator<<fmt::FillChar(f3)<<fmt::Expand(w3)<<p3;
strDateText=std::move(Fmt.strValue());
}
}
@@ -817,6 +817,6 @@ void ConvertRelativeDate(const FILETIME &ft,FARString &strDaysText,FARString &st
strDaysText=std::move(DaysText.strValue());
FormatString TimeText;
- TimeText<<fmt::Width(2)<<fmt::FillChar(L'0')<<h<<GetTimeSeparator()<<fmt::Width(2)<<fmt::FillChar(L'0')<<m<<GetTimeSeparator()<<fmt::Width(2)<<fmt::FillChar(L'0')<<s<<GetDecimalSeparator()<<fmt::Width(3)<<fmt::FillChar(L'0')<<ms;
+ TimeText<<fmt::Expand(2)<<fmt::FillChar(L'0')<<h<<GetTimeSeparator()<<fmt::Expand(2)<<fmt::FillChar(L'0')<<m<<GetTimeSeparator()<<fmt::Expand(2)<<fmt::FillChar(L'0')<<s<<GetDecimalSeparator()<<fmt::Expand(3)<<fmt::FillChar(L'0')<<ms;
strTimeText=std::move(TimeText.strValue());
}
diff --git a/far2l/src/delete.cpp b/far2l/src/delete.cpp
index c9393fc5..391e6731 100644
--- a/far2l/src/delete.cpp
+++ b/far2l/src/delete.cpp
@@ -578,7 +578,7 @@ void ShellDeleteMsg(const wchar_t *Name,int Wipe,int Percent)
wmemset(Progress+(CurPos),BoxSymbols[BS_X_B0],Length-CurPos);
strProgress.ReleaseBuffer(Length);
FormatString strTmp;
- strTmp<<L" "<<fmt::Width(3)<<Percent<<L"%";
+ strTmp<<L" "<<fmt::Expand(3)<<Percent<<L"%";
strProgress+=strTmp;
DeleteTitle->Set(L"{%d%%} %ls", Percent, (Wipe ? Msg::DeleteWipeTitle : Msg::DeleteTitle).CPtr());
}
diff --git a/far2l/src/dialog.cpp b/far2l/src/dialog.cpp
index e98e4fe3..44c144c5 100644
--- a/far2l/src/dialog.cpp
+++ b/far2l/src/dialog.cpp
@@ -1207,7 +1207,7 @@ BOOL Dialog::GetItemRect(unsigned I,SMALL_RECT& Rect)
case DI_MEMOEDIT:
break;
default:
- Len=((ItemFlags & DIF_SHOWAMPERSAND)?(int)CurItem->strData.GetLength():HiStrlen(CurItem->strData));
+ Len=((ItemFlags & DIF_SHOWAMPERSAND)?(int)CurItem->strData.CellsCount():HiStrCellsCount(CurItem->strData));
break;
}
@@ -1884,7 +1884,7 @@ void Dialog::ShowDialog(unsigned ID)
if (CW < ObjWidth)
tmpCW=CW+1;
- strStr.Truncate(tmpCW-1);
+ strStr.TruncateByCells(tmpCW-1);
}
// нужно ЭТО
@@ -1899,10 +1899,10 @@ void Dialog::ShowDialog(unsigned ID)
if (X1+X+CntChr-1 > X2)
CntChr=X2-(X1+X)+1;
- FS<<fmt::Width(CntChr)<<L"";
+ FS << fmt::Cells() << fmt::Expand(CntChr) << L"";
if (CntChr < LenText)
- strStr.Truncate(CntChr);
+ strStr.TruncateByCells(CntChr);
}
if (CurItem->Flags & (DIF_SEPARATORUSER|DIF_SEPARATOR|DIF_SEPARATOR2))
@@ -1956,7 +1956,7 @@ void Dialog::ShowDialog(unsigned ID)
if (CH < ObjHeight)
tmpCH=CH+1;
- strStr.Truncate(tmpCH-1);
+ strStr.TruncateByCells(tmpCH-1);
}
// нужно ЭТО
@@ -2035,7 +2035,7 @@ void Dialog::ShowDialog(unsigned ID)
LenText=LenStrItem(I, strStr);
if (X1+CX1+LenText > X2)
- strStr.Truncate(ObjWidth-1);
+ strStr.TruncateByCells(ObjWidth-1);
if (CurItem->Flags & DIF_SHOWAMPERSAND)
Text(strStr);
@@ -2228,7 +2228,7 @@ int Dialog::LenStrItem(int ID, const wchar_t *lpwszStr)
if (!lpwszStr)
lpwszStr = Item[ID]->strData;
- return (Item[ID]->Flags & DIF_SHOWAMPERSAND)?StrLength(lpwszStr):HiStrlen(lpwszStr);
+ return (Item[ID]->Flags & DIF_SHOWAMPERSAND)?StrZCellsCount(lpwszStr):HiStrCellsCount(lpwszStr);
}
@@ -3479,7 +3479,7 @@ int Dialog::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
/* ********************************************************** */
if (Type==DI_BUTTON &&
MsY==Y1+Item[I]->Y1 &&
- MsX < X1+Item[I]->X1+HiStrlen(Item[I]->strData))
+ MsX < X1+Item[I]->X1+HiStrCellsCount(Item[I]->strData))
{
ChangeFocus2(I);
ShowDialog();
@@ -3487,7 +3487,7 @@ int Dialog::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
while (IsMouseButtonPressed());
if (MouseX < X1 ||
- MouseX > X1+Item[I]->X1+HiStrlen(Item[I]->strData)+4 ||
+ MouseX > X1+Item[I]->X1+HiStrCellsCount(Item[I]->strData)+4 ||
MouseY != Y1+Item[I]->Y1)
{
ChangeFocus2(I);
@@ -3504,7 +3504,7 @@ int Dialog::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
if ((Type == DI_CHECKBOX ||
Type == DI_RADIOBUTTON) &&
MsY==Y1+Item[I]->Y1 &&
- MsX < (X1+Item[I]->X1+HiStrlen(Item[I]->strData)+4-((Item[I]->Flags & DIF_MOVESELECT)!=0)))
+ MsX < (X1+Item[I]->X1+HiStrCellsCount(Item[I]->strData)+4-((Item[I]->Flags & DIF_MOVESELECT)!=0)))
{
ChangeFocus2(I);
ProcessKey(KEY_SPACE, I);
@@ -5520,7 +5520,7 @@ LONG_PTR SendDlgMessageSynched(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2)
DlgEdit *EditPtr=(DlgEdit *)(CurItem->ObjPtr);
esp->CurLine=0;
esp->CurPos=EditPtr->GetCurPos();
- esp->CurTabPos=EditPtr->GetTabCurPos();
+ esp->CurTabPos=EditPtr->GetCellCurPos();
esp->TopScreenLine=0;
esp->LeftPos=EditPtr->GetLeftPos();
esp->Overtype=EditPtr->GetOvertypeMode();
@@ -5545,7 +5545,7 @@ LONG_PTR SendDlgMessageSynched(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2)
EditorSetPosition *esp=(EditorSetPosition *)Param2;
DlgEdit *EditPtr=(DlgEdit *)(CurItem->ObjPtr);
EditPtr->SetCurPos(esp->CurPos);
- EditPtr->SetTabCurPos(esp->CurTabPos);
+ EditPtr->SetCellCurPos(esp->CurTabPos);
EditPtr->SetLeftPos(esp->LeftPos);
EditPtr->SetOvertypeMode(esp->Overtype);
Dlg->ShowDialog(Param1);
diff --git a/far2l/src/dizlist.cpp b/far2l/src/dizlist.cpp
index ec4bb07c..013263d7 100644
--- a/far2l/src/dizlist.cpp
+++ b/far2l/src/dizlist.cpp
@@ -581,7 +581,7 @@ bool DizList::AddDizText(const wchar_t *Name,const wchar_t *DizText)
FARString strQuotedName = Name;
QuoteSpaceOnly(strQuotedName);
FormatString FString;
- FString<<fmt::LeftAlign()<<fmt::Width(Opt.Diz.StartPos>1?Opt.Diz.StartPos-2:0)<<strQuotedName<<L" "<<DizText;
+ FString<<fmt::LeftAlign()<<fmt::Expand(Opt.Diz.StartPos>1?Opt.Diz.StartPos-2:0)<<strQuotedName<<L" "<<DizText;
return AddRecord(FString);
}
diff --git a/far2l/src/dlgedit.cpp b/far2l/src/dlgedit.cpp
index 8881d951..0366f646 100644
--- a/far2l/src/dlgedit.cpp
+++ b/far2l/src/dlgedit.cpp
@@ -390,7 +390,7 @@ int DlgEdit::GetCurRow()
return 0;
}
-int DlgEdit::GetTabCurPos()
+int DlgEdit::GetCellCurPos()
{
#if defined(PROJECT_DI_MEMOEDIT)
@@ -398,10 +398,10 @@ int DlgEdit::GetTabCurPos()
return multiEdit->GetCurPos(); // GetCurCol???
else
#endif
- return lineEdit->GetTabCurPos();
+ return lineEdit->GetCellCurPos();
}
-void DlgEdit::SetTabCurPos(int NewPos)
+void DlgEdit::SetCellCurPos(int NewPos)
{
#if defined(PROJECT_DI_MEMOEDIT)
@@ -409,7 +409,7 @@ void DlgEdit::SetTabCurPos(int NewPos)
multiEdit->SetCurPos(NewPos,multiEdit->GetCurRow()); //???
else
#endif
- lineEdit->SetTabCurPos(NewPos);
+ lineEdit->SetCellCurPos(NewPos);
}
diff --git a/far2l/src/dlgedit.hpp b/far2l/src/dlgedit.hpp
index fc21a2bf..b694f426 100644
--- a/far2l/src/dlgedit.hpp
+++ b/far2l/src/dlgedit.hpp
@@ -110,8 +110,8 @@ class DlgEdit: public ScreenObject
int GetCurPos();
int GetCurRow();
- int GetTabCurPos();
- void SetTabCurPos(int NewPos);
+ int GetCellCurPos();
+ void SetCellCurPos(int NewPos);
void SetPersistentBlocks(int Mode);
int GetPersistentBlocks();
diff --git a/far2l/src/edit.cpp b/far2l/src/edit.cpp
index 3b1c60a2..e58c26ee 100644
--- a/far2l/src/edit.cpp
+++ b/far2l/src/edit.cpp
@@ -245,7 +245,7 @@ void Edit::DisplayObject()
::SetCursorType(1,CursorSize==-1?NewCursorSize:CursorSize);
}
else
-{
+ {
int NewCursorSize=IsFullscreen()?
(Opt.CursorSize[1]?Opt.CursorSize[1]:10):
(Opt.CursorSize[0]?Opt.CursorSize[0]:10);
@@ -338,24 +338,42 @@ void Edit::FastShow()
CurPos=MaxLength>0 ? (MaxLength-1):0;
}
- int TabCurPos=GetTabCurPos();
+ int CellCurPos=GetCellCurPos();
/* $ 31.07.2001 KM
! Для комбобокса сделаем отображение строки
с первой позиции.
*/
+ int RealLeftPos = -1;
if (!Flags.Check(FEDITLINE_DROPDOWNBOX))
{
- if (TabCurPos-LeftPos>EditLength-1)
- LeftPos=TabCurPos-EditLength+1;
+ if (CellCurPos - LeftPos > EditLength - 1)
+ {
+ // tricky left pos shifting to
+ // - avoid LeftPos pointing into middle of full-width char cells pair
+ // - ensure RealLeftPos really shifted in case string starts by some long character
+ for (int ShiftBy = 1; ShiftBy <= std::max(TabSize, 2); ++ShiftBy)
+ {
+ RealLeftPos = CellPosToReal(CellCurPos - EditLength + ShiftBy);
+ int NewLeftPos = RealPosToCell(RealLeftPos);
+ if (LeftPos != NewLeftPos)
+ {
+ LeftPos = NewLeftPos;
+ break;
+ }
+ }
+ }
- if (TabCurPos<LeftPos)
- LeftPos=TabCurPos;
+ if (CellCurPos < LeftPos)
+ LeftPos = CellCurPos;
}
+ if (RealLeftPos == -1)
+ RealLeftPos = CellPosToReal(LeftPos);
+
GotoXY(X1,Y1);
- int TabSelStart=(SelStart==-1) ? -1:RealPosToTab(SelStart);
- int TabSelEnd=(SelEnd<0) ? -1:RealPosToTab(SelEnd);
+ int CellSelStart=(SelStart==-1) ? -1:RealPosToCell(SelStart);
+ int CellSelEnd=(SelEnd<0) ? -1:RealPosToCell(SelEnd);
/* $ 17.08.2000 KM
Если есть маска, сделаем подготовку строки, то есть
@@ -365,152 +383,140 @@ void Edit::FastShow()
if (Mask && *Mask)
RefreshStrByMask();
- wchar_t *OutStrTmp=(wchar_t *)malloc((EditLength+1)*sizeof(wchar_t));
-
- if (!OutStrTmp)
- return;
-
- wchar_t *OutStr=(wchar_t *)malloc((EditLength+1)*sizeof(wchar_t));
-
- if (!OutStr)
- {
- free(OutStrTmp);
- return;
- }
-
- CursorPos=TabCurPos;
- int RealLeftPos=TabPosToReal(LeftPos);
- int OutStrLength=Min(EditLength,StrSize-RealLeftPos);
+ CursorPos = CellCurPos;
- if (OutStrLength < 0)
+ OutStr.clear();
+ size_t OutStrCells = 0;
+ for (int i = RealLeftPos; i < StrSize && int(OutStrCells) < EditLength; ++i)
{
- OutStrLength=0;
- }
- else
- {
- wmemcpy(OutStrTmp,Str+RealLeftPos,OutStrLength);
- }
-
- {
- wchar_t *p=OutStrTmp;
- wchar_t *e=OutStrTmp+OutStrLength;
+ auto wc = Str[i];
+ if (wc == L' ' && Flags.Check(FEDITLINE_SHOWWHITESPACE) && Flags.Check(FEDITLINE_EDITORMODE))
+ {
+ wc = L'\xB7';
+ }
- for (OutStrLength=0; OutStrLength<EditLength && p<e; p++)
+ if (wc == L'\t')
{
- if (Flags.Check(FEDITLINE_SHOWWHITESPACE) && Flags.Check(FEDITLINE_EDITORMODE))
+ for (int j = 0, S = TabSize - ((LeftPos + OutStrCells) % TabSize);
+ j < S && int(OutStrCells) < EditLength;
+ ++j, ++OutStrCells)
{
- if (*p==L' ')
- {
- *p=L'\xB7';
- }
+ OutStr.emplace_back(
+ (Flags.Check(FEDITLINE_SHOWWHITESPACE) && Flags.Check(FEDITLINE_EDITORMODE) && !j)
+ ? L'\x2192' : L' ');
}
-
- if (*p == L'\t')
+ }
+ else
+ {
+ if (IsCharFullWidth(wc))
{
- int S=TabSize-((LeftPos+OutStrLength) % TabSize);
-
- for (int i=0; i<S && OutStrLength<EditLength; i++,OutStrLength++)
+ if (int(OutStrCells + 2) > EditLength)
{
- OutStr[OutStrLength]=(Flags.Check(FEDITLINE_SHOWWHITESPACE) && Flags.Check(FEDITLINE_EDITORMODE) && !i)?L'\x2192':L' ';
+ OutStr.emplace_back(L' ');
+ OutStrCells++;
+ break;
}
+ OutStrCells+= 2;
}
- else
- {
- if (!*p)
- OutStr[OutStrLength]=L' ';
- else
- OutStr[OutStrLength]=*p;
+ else if (!IsCharXxxfix(wc) || i == RealLeftPos)
+ OutStrCells++;
- OutStrLength++;
- }
+ OutStr.emplace_back(wc ? wc : L' ');
}
+ }
- if (Flags.Check(FEDITLINE_PASSWORDMODE))
- wmemset(OutStr,L'*',OutStrLength);
+ if (Flags.Check(FEDITLINE_PASSWORDMODE))
+ {
+ OutStr.resize(OutStrCells);
+ std::fill(OutStr.begin(), OutStr.end(), L'*');
}
- OutStr[OutStrLength]=0;
+ OutStr.emplace_back(0);
SetColor(Color);
- if (TabSelStart==-1)
+ if (CellSelStart==-1)
{
if (Flags.Check(FEDITLINE_CLEARFLAG))
{
SetColor(ColorUnChanged);
if (Mask && *Mask)
- OutStrLength=StrLength(RemoveTrailingSpaces(OutStr));
+ {
+ RemoveTrailingSpaces(OutStr.data());
+ OutStr.resize(wcslen(OutStr.data()));
+ OutStrCells = StrCellsCount(OutStr.data(), OutStr.size());
+ OutStr.emplace_back(0);
+ }
- FS<<fmt::LeftAlign()<<fmt::Width(OutStrLength)<<fmt::Precision(OutStrLength)<<OutStr;
+ FS << fmt::Cells() << fmt::LeftAlign() << OutStr.data();
SetColor(Color);
- int BlankLength=EditLength-OutStrLength;
+ int BlankLength = EditLength - (int)OutStrCells;
if (BlankLength > 0)
{
- FS<<fmt::Width(BlankLength)<<L"";
+ FS << fmt::Cells() << fmt::Expand(BlankLength) << L"";
}
}
else
{
- FS<<fmt::LeftAlign()<<fmt::Width(EditLength)<<fmt::Precision(EditLength)<<OutStr;
+ FS << fmt::LeftAlign() << fmt::Cells() << fmt::Size(EditLength) << OutStr.data();
}
}
else
{
- if ((TabSelStart-=LeftPos)<0)
- TabSelStart=0;
+ if ((CellSelStart-=LeftPos)<0)
+ CellSelStart=0;
- int AllString=(TabSelEnd==-1);
+ int AllString = (CellSelEnd==-1);
if (AllString)
- TabSelEnd=EditLength;
- else if ((TabSelEnd-=LeftPos)<0)
- TabSelEnd=0;
+ CellSelEnd = EditLength;
+ else if ((CellSelEnd-=LeftPos)<0)
+ CellSelEnd=0;
- wmemset(OutStr+OutStrLength,L' ',EditLength-OutStrLength);
- OutStr[EditLength]=0;
+ for (;int(OutStrCells) < EditLength; ++OutStrCells)
+ {
+ OutStr.emplace(OutStr.begin() + OutStr.size() - 1, L' ');
+ }
/* $ 24.08.2000 SVS
! У DropDowList`а выделение по полной программе - на всю видимую длину
ДАЖЕ ЕСЛИ ПУСТАЯ СТРОКА
*/
- if (TabSelStart>=EditLength /*|| !AllString && TabSelStart>=StrSize*/ ||
- TabSelEnd<TabSelStart)
+ if (CellSelStart>=EditLength /*|| !AllString && CellSelStart>=StrSize*/ ||
+ CellSelEnd<CellSelStart)
{
if (Flags.Check(FEDITLINE_DROPDOWNBOX))
{
SetColor(SelColor);
- FS<<fmt::Width(X2-X1+1)<<OutStr;
+ FS << fmt::Cells() << fmt::Expand(X2 - X1 + 1) << OutStr.data();
}
else
- Text(OutStr);
+ Text(OutStr.data());
}
else
{
- FS<<fmt::Precision(TabSelStart)<<OutStr;
+ FS << fmt::Cells() << fmt::Truncate(CellSelStart) << OutStr.data();
SetColor(SelColor);
if (!Flags.Check(FEDITLINE_DROPDOWNBOX))
{
- FS<<fmt::Precision(TabSelEnd-TabSelStart)<<OutStr+TabSelStart;
+ FS << fmt::Cells() << fmt::Skip(CellSelStart) << fmt::Truncate(CellSelEnd - CellSelStart) << OutStr.data();
- if (TabSelEnd<EditLength)
+ if (CellSelEnd < EditLength)
{
//SetColor(Flags.Check(FEDITLINE_CLEARFLAG) ? SelColor:Color);
SetColor(Color);
- Text(OutStr+TabSelEnd);
+ FS << fmt::Cells() << fmt::Skip(CellSelEnd) << OutStr.data();
}
}
else
{
- FS<<fmt::Width(X2-X1+1)<<OutStr;
+ FS << fmt::Cells() << fmt::Expand(X2 - X1 + 1) << OutStr.data();
}
}
}
- free(OutStr);
- free(OutStrTmp);
-
/* $ 26.07.2000 tran
при дроп-даун цвета нам не нужны */
if (!Flags.Check(FEDITLINE_DROPDOWNBOX))
@@ -619,7 +625,7 @@ int64_t Edit::VMProcess(int OpCode,void *vParam,int64_t iParam)
case 0: // begin block (FirstLine & FirstPos)
case 1: // end block (LastLine & LastPos)
{
- SetTabCurPos(iParam?SelEnd:SelStart);
+ SetCellCurPos(iParam?SelEnd:SelStart);
Show();
return 1;
}
@@ -674,6 +680,46 @@ int64_t Edit::VMProcess(int OpCode,void *vParam,int64_t iParam)
return 0;
}
+int Edit::CalcRTrimmedStrSize() const
+{
+ int TrimmedStrSize = StrSize;
+ while (TrimmedStrSize > 0 && (IsSpace(Str[TrimmedStrSize - 1]) || IsEol(Str[TrimmedStrSize - 1])))
+ {
+ --TrimmedStrSize;
+ }
+ return TrimmedStrSize;
+}
+
+int Edit::CalcPosFwdTo(int Pos, int LimitPos) const
+{
+ if (LimitPos != -1)
+ {
+ if (Pos < LimitPos) do
+ {
+ Pos++;
+ } while (Pos < LimitPos && Pos < StrSize && IsCharXxxfix(Str[Pos]));
+ }
+ else do
+ {
+ Pos++;
+ } while (Pos < StrSize && IsCharXxxfix(Str[Pos]));
+
+ return Pos;
+}
+
+int Edit::CalcPosBwdTo(int Pos) const
+{
+ if (Pos <= 0)
+ return 0;
+
+ do
+ {
+ --Pos;
+ } while (Pos > 0 && IsCharXxxfix(Str[Pos]));
+
+ return Pos;
+}
+
int Edit::ProcessKey(int Key)
{
switch (Key)
@@ -819,7 +865,7 @@ int Edit::ProcessKey(int Key)
Select(SelStart,CurPos);
else
{
- int EndPos=CurPos+1;
+ int EndPos = CalcPosFwd((Mask && *Mask) ? CalcRTrimmedStrSize() : -1);
int NewStartPos=CurPos;
if (EndPos>StrSize)
@@ -846,13 +892,13 @@ int Edit::ProcessKey(int Key)
if ((SelStart!=-1 && SelEnd==-1) || SelEnd>CurPos)
{
- if (CurPos+1==SelEnd)
+ if (CalcPosFwd() == SelEnd)
Select(-1,0);
else
- Select(CurPos+1,SelEnd);
+ Select(CalcPosFwd(), SelEnd);
}
else
- AddSelect(CurPos,CurPos+1);
+ AddSelect(CurPos, CalcPosFwd());
RecurseProcessKey(KEY_RIGHT);
return TRUE;
@@ -917,21 +963,7 @@ int Edit::ProcessKey(int Key)
case KEY_SHIFTEND: case KEY_SHIFTNUMPAD1:
{
Lock();
- int Len;
-
- if (Mask && *Mask)
- {
- wchar_t *ShortStr=new(std::nothrow) wchar_t[StrSize+1];
-
- if (!ShortStr)
- return FALSE;
-
- far_wcsncpy(ShortStr,Str,StrSize+1);
- Len=StrLength(RemoveTrailingSpaces(ShortStr));
- delete[] ShortStr;
- }
- else
- Len=StrSize;
+ int Len = (Mask && *Mask) ? CalcRTrimmedStrSize() : StrSize;
int LastCurPos=CurPos;
@@ -953,15 +985,16 @@ int Edit::ProcessKey(int Key)
if (CurPos<=0)
return FALSE;
- PrevCurPos=CurPos;
- CurPos--;
+ PrevCurPos = CurPos;
+ CurPos = CalcPosBwd();
- if (CurPos<=LeftPos)
+ while (LeftPos > 0 && RealPosToCell(CurPos) <= LeftPos)
{
- LeftPos-=15;
-
- if (LeftPos<0)
- LeftPos=0;
+ LeftPos-= 15;
+ if (LeftPos > 0)
+ LeftPos = RealPosToCell(CellPosToReal(LeftPos));
+ else
+ LeftPos = 0;
}
if (!RecurseProcessKey(KEY_DEL))
@@ -1177,22 +1210,8 @@ int Edit::ProcessKey(int Key)
case KEY_CTRLEND: case KEY_CTRLNUMPAD1:
case KEY_CTRLSHIFTEND: case KEY_CTRLSHIFTNUMPAD1:
{
- PrevCurPos=CurPos;
-
- if (Mask && *Mask)
- {
- wchar_t *ShortStr=new(std::nothrow) wchar_t[StrSize+1];
-
- if (!ShortStr)
- return FALSE;
-
- far_wcsncpy(ShortStr,Str,StrSize+1);
- CurPos=StrLength(RemoveTrailingSpaces(ShortStr));
- delete[] ShortStr;
- }
- else
- CurPos=StrSize;
-
+ PrevCurPos = CurPos;
+ CurPos = (Mask && *Mask) ? CalcRTrimmedStrSize() : StrSize;
Show();
return TRUE;
}
@@ -1201,8 +1220,8 @@ int Edit::ProcessKey(int Key)
{
if (CurPos>0)
{
- PrevCurPos=CurPos;
- CurPos--;
+ PrevCurPos = CurPos;
+ CurPos = CalcPosBwd();
Show();
}
@@ -1211,25 +1230,8 @@ int Edit::ProcessKey(int Key)
case KEY_RIGHT: case KEY_NUMPAD6: case KEY_MSWHEEL_RIGHT:
case KEY_CTRLD:
{
- PrevCurPos=CurPos;
-
- if (Mask && *Mask)
- {
- wchar_t *ShortStr=new(std::nothrow) wchar_t[StrSize+1];
-
- if (!ShortStr)
- return FALSE;
-
- far_wcsncpy(ShortStr,Str,StrSize+1);
- int Len=StrLength(RemoveTrailingSpaces(ShortStr));
- delete[] ShortStr;
-
- if (Len>CurPos)
- CurPos++;
- }
- else
- CurPos++;
-
+ PrevCurPos = CurPos;
+ CurPos = CalcPosFwd((Mask && *Mask) ? CalcRTrimmedStrSize() : -1);
Show();
return TRUE;
}
@@ -1269,9 +1271,15 @@ int Edit::ProcessKey(int Key)
}
else
{
- wmemmove(Str+CurPos,Str+CurPos+1,StrSize-CurPos);
- StrSize--;
- Str=(wchar_t *)realloc(Str,(StrSize+1)*sizeof(wchar_t));
+ auto NextPos = CalcPosFwd();
+ if (NextPos > CurPos) {
+ wmemmove(Str + CurPos, Str + NextPos, (StrSize - NextPos) + 1);
+ StrSize-= (NextPos - CurPos);
+ wchar_t *NewStr = (wchar_t *)realloc(Str, (StrSize + 1) * sizeof(wchar_t));
+ if (NewStr) {
+ Str = NewStr;
+ }
+ }
}
Changed(true);
@@ -1285,8 +1293,7 @@ int Edit::ProcessKey(int Key)
if (CurPos>StrSize)
CurPos=StrSize;
- if (CurPos>0)
- CurPos--;
+ CurPos = CalcPosBwd();
while (CurPos>0 && !(!IsWordDiv(WordDiv(), Str[CurPos]) &&
IsWordDiv(WordDiv(), Str[CurPos-1]) && !IsSpace(Str[CurPos])))
@@ -1310,22 +1317,13 @@ int Edit::ProcessKey(int Key)
if (Mask && *Mask)
{
- wchar_t *ShortStr=new(std::nothrow) wchar_t[StrSize+1];
-
- if (!ShortStr)
- return FALSE;
-
- far_wcsncpy(ShortStr,Str,StrSize+1);
- Len=StrLength(RemoveTrailingSpaces(ShortStr));
- delete[] ShortStr;
-
- if (Len>CurPos)
- CurPos++;
+ Len = CalcRTrimmedStrSize();
+ CurPos = CalcPosFwd(Len);
}
else
{
- Len=StrSize;
- CurPos++;
+ Len = StrSize;
+ CurPos = CalcPosFwd();
}
while (CurPos<Len/*StrSize*/ && !(IsWordDiv(WordDiv(),Str[CurPos]) &&
@@ -1360,15 +1358,8 @@ int Edit::ProcessKey(int Key)
{
if (Mask && *Mask)
{
- wchar_t *ShortStr=new(std::nothrow) wchar_t[StrSize+1];
-
- if (!ShortStr)
- return FALSE;
-
- far_wcsncpy(ShortStr,Str,StrSize+1);
- RemoveTrailingSpaces(ShortStr);
- CopyToClipboard(ShortStr);
- delete[] ShortStr;
+ std::wstring TrimmedStr(Str, CalcRTrimmedStrSize());
+ CopyToClipboard(TrimmedStr.c_str());
}
else
{
@@ -1440,7 +1431,7 @@ int Edit::ProcessKey(int Key)
if (CursorPos<0) CursorPos=0; //CursorPos=0,TabSize=1 case
- SetTabCurPos(CursorPos);
+ SetCellCurPos(CursorPos);
Show();
return TRUE;
}
@@ -1531,7 +1522,7 @@ int Edit::InsertKey(int Key)
{
PrevCurPos=CurPos;
CursorPos+=TabSize - (CursorPos % TabSize);
- SetTabCurPos(CursorPos);
+ SetCellCurPos(CursorPos);
return TRUE;
}
@@ -1825,7 +1816,7 @@ void Edit::SetBinaryString(const wchar_t *Str,int Length)
this->Str[Length]=0;
if (TabExpandMode == EXPAND_ALLTABS)
- ReplaceTabs();
+ ExpandTabs();
PrevCurPos=CurPos;
CurPos=StrSize;
@@ -2001,7 +1992,7 @@ void Edit::InsertBinaryString(const wchar_t *Str,int Length)
delete[] TmpStr;
if (TabExpandMode == EXPAND_ALLTABS)
- ReplaceTabs();
+ ExpandTabs();
Changed();
}
@@ -2080,7 +2071,7 @@ int Edit::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
return FALSE;
//SetClearFlag(0); // пусть едитор сам заботится о снятии клеар-текста?
- SetTabCurPos(MouseEvent->dwMousePosition.X - X1 + LeftPos);
+ SetCellCurPos(MouseEvent->dwMousePosition.X - X1 + LeftPos);
if (!Flags.Check(FEDITLINE_PERSISTENTBLOCKS))
Select(-1,0);
@@ -2163,7 +2154,7 @@ void Edit::InsertTab()
}
-void Edit::ReplaceTabs()
+void Edit::ExpandTabs()
{
wchar_t *TabPtr;
int Pos=0,S;
@@ -2209,42 +2200,32 @@ void Edit::ReplaceTabs()
}
-int Edit::GetTabCurPos()
+int Edit::GetCellCurPos()
{
- return(RealPosToTab(CurPos));
+ return(RealPosToCell(CurPos));
}
-void Edit::SetTabCurPos(int NewPos)
+void Edit::SetCellCurPos(int NewPos)
{
- int Pos;
-
if (Mask && *Mask)
{
- wchar_t *ShortStr=new(std::nothrow) wchar_t[StrSize+1];
-
- if (!ShortStr)
- return;
-
- far_wcsncpy(ShortStr,Str,StrSize+1);
- Pos=StrLength(RemoveTrailingSpaces(ShortStr));
- delete[] ShortStr;
-
- if (NewPos>Pos)
- NewPos=Pos;
+ int NewPosLimit = CalcRTrimmedStrSize();
+ if (NewPos > NewPosLimit)
+ NewPos = NewPosLimit;
}
- CurPos=TabPosToReal(NewPos);
+ CurPos = CellPosToReal(NewPos);
}
-int Edit::RealPosToTab(int Pos)
+int Edit::RealPosToCell(int Pos)
{
- return RealPosToTab(0, 0, Pos, nullptr);
+ return RealPosToCell(0, 0, Pos, nullptr);
}
-int Edit::RealPosToTab(int PrevLength, int PrevPos, int Pos, int* CorrectPos)
+int Edit::RealPosToCell(int PrevLength, int PrevPos, int Pos, int* CorrectPos)
{
// Корректировка табов
bool bCorrectPos = CorrectPos && *CorrectPos;
@@ -2252,10 +2233,6 @@ int Edit::RealPosToTab(int PrevLength, int PrevPos, int Pos, int* CorrectPos)
if (CorrectPos)
*CorrectPos = 0;
- // Если у нас все табы преобразуются в пробелы, то просто вычисляем расстояние
- if (TabExpandMode == EXPAND_ALLTABS)
- return PrevLength+Pos-PrevPos;
-
// Инциализируем результирующую длину предыдущим значением
int TabPos = PrevLength;
@@ -2273,7 +2250,7 @@ int Edit::RealPosToTab(int PrevLength, int PrevPos, int Pos, int* CorrectPos)
for (; Index < Min(Pos, StrSize); Index++)
// Обрабатываем табы
- if (Str[Index] == L'\t')
+ if (Str[Index] == L'\t' && TabExpandMode != EXPAND_ALLTABS)
{
// Если есть необходимость делать корректировку табов и эта коректировка
// ещё не проводилась, то увеличиваем длину обрабатываемой строки на еденицу
@@ -2287,9 +2264,15 @@ int Edit::RealPosToTab(int PrevLength, int PrevPos, int Pos, int* CorrectPos)
// Расчитываем длину таба с учётом настроек и текущей позиции в строке
TabPos += TabSize-(TabPos%TabSize);
}
- // Обрабатываем все отсальные символы
- else
+ // Обрабатываем все остальные символы
+ else if (IsCharFullWidth(Str[Index]))
+ {
+ TabPos+= 2;
+ }
+ else if (!IsCharXxxfix(Str[Index]))
+ {
TabPos++;
+ }
// Если позиция находится за пределами строки, то там точно нет табов и всё просто
if (Pos >= StrSize)
@@ -2300,81 +2283,87 @@ int Edit::RealPosToTab(int PrevLength, int PrevPos, int Pos, int* CorrectPos)
}
-int Edit::TabPosToReal(int Pos)
+int Edit::CellPosToReal(int Pos)
{
- if (TabExpandMode == EXPAND_ALLTABS)
- return Pos;
-
int Index = 0;
-
- for (int TabPos = 0; TabPos < Pos; Index++)
+ for (int CellPos = 0; CellPos < Pos; Index++)
{
- if (Index > StrSize)
+ if (Index >= StrSize)
{
- Index += Pos-TabPos;
+ Index += Pos-CellPos;
break;
}
- if (Str[Index] == L'\t')
+ if (Str[Index] == L'\t' && TabExpandMode != EXPAND_ALLTABS)
{
- int NewTabPos = TabPos+TabSize-(TabPos%TabSize);
+ int NewCellPos = CellPos + TabSize - (CellPos%TabSize);
- if (NewTabPos > Pos)
+ if (NewCellPos > Pos)
break;
- TabPos = NewTabPos;
+ CellPos = NewCellPos;
}
else
{
- TabPos++;
+ CellPos+= IsCharFullWidth(Str[Index]) ? 2 : 1;
+ while (Index + 1 < StrSize && IsCharXxxfix(Str[Index + 1]))
+ {
+ Index++;
+ }
}
}
return Index;
}
-
-void Edit::Select(int Start,int End)
+void Edit::SanitizeSelectionRange()
{
- SelStart=Start;
- SelEnd=End;
+ if (SelEnd >= SelStart && SelStart >= 0)
+ {
+ while (SelStart > 0 && IsCharXxxfix(Str[SelStart]))
+ --SelStart;
+
+ while (SelEnd < StrSize && IsCharXxxfix(Str[SelEnd]))
+ ++SelEnd;
+ }
/* $ 24.06.2002 SKV
Если начало выделения за концом строки, надо выделение снять.
17.09.2002 возвращаю обратно. Глюкодром.
*/
- if (SelEnd<SelStart && SelEnd!=-1)
+ if (SelEnd < SelStart && SelEnd != -1)
{
- SelStart=-1;
- SelEnd=0;
+ SelStart = -1;
+ SelEnd = 0;
}
- if (SelStart==-1 && SelEnd==-1)
+ if (SelStart == -1 && SelEnd == -1)
{
- SelStart=-1;
- SelEnd=0;
+ SelStart = -1;
+ SelEnd = 0;
}
+}
+
+void Edit::Select(int Start,int End)
+{
+ SelStart = Start;
+ SelEnd = End;
-// if (SelEnd>StrSize)
-// SelEnd=StrSize;
+ SanitizeSelectionRange();
}
void Edit::AddSelect(int Start,int End)
{
- if (Start<SelStart || SelStart==-1)
- SelStart=Start;
+ if (Start < SelStart || SelStart == -1)
+ SelStart = Start;
- if (End==-1 || (End>SelEnd && SelEnd!=-1))
- SelEnd=End;
+ if (End == -1 || (End > SelEnd && SelEnd != -1))
+ SelEnd = End;
- if (SelEnd>StrSize)
- SelEnd=StrSize;
+ if (SelEnd > StrSize)
+ SelEnd = StrSize;
- if (SelEnd<SelStart && SelEnd!=-1)
- {
- SelStart=-1;
- SelEnd=0;
- }
+ SanitizeSelectionRange();
}
@@ -2552,13 +2541,13 @@ void Edit::ApplyColor()
// то производим вычисление с начала строки
else if (Pos == INT_MIN || CurItem->StartPos < Pos)
{
- RealStart = RealPosToTab(CurItem->StartPos);
+ RealStart = RealPosToCell(CurItem->StartPos);
Start = RealStart-LeftPos;
}
// Для отптимизации делаем вычисление относительно предыдущей позиции
else
{
- RealStart = RealPosToTab(TabPos, Pos, CurItem->StartPos, nullptr);
+ RealStart = RealPosToCell(TabPos, Pos, CurItem->StartPos, nullptr);
Start = RealStart-LeftPos;
}
@@ -2590,7 +2579,7 @@ void Edit::ApplyColor()
// иначе ничего не вычисялем и берём старые значения
if (CorrectPos && EndPos < StrSize && Str[EndPos] == L'\t')
{
- RealEnd = RealPosToTab(TabPos, Pos, ++EndPos, nullptr);
+ RealEnd = RealPosToCell(TabPos, Pos, ++EndPos, nullptr);
End = RealEnd-LeftPos;
}
else
@@ -2604,7 +2593,7 @@ void Edit::ApplyColor()
// с начала строки (с учётом корректировки относительно табов)
else if (EndPos < Pos)
{
- RealEnd = RealPosToTab(0, 0, EndPos, &CorrectPos);
+ RealEnd = RealPosToCell(0, 0, EndPos, &CorrectPos);
EndPos += CorrectPos;
End = RealEnd-LeftPos;
}
@@ -2612,7 +2601,7 @@ void Edit::ApplyColor()
// корректировки относительно табов)
else
{
- RealEnd = RealPosToTab(TabPos, Pos, EndPos, &CorrectPos);
+ RealEnd = RealPosToCell(TabPos, Pos, EndPos, &CorrectPos);
EndPos += CorrectPos;
End = RealEnd-LeftPos;
}
@@ -3214,7 +3203,7 @@ int EditControl::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
while(IsMouseButtonPressed()==FROM_LEFT_1ST_BUTTON_PRESSED)
{
Flags.Clear(FEDITLINE_CLEARFLAG);
- SetTabCurPos(MouseX - X1 + LeftPos);
+ SetCellCurPos(MouseX - X1 + LeftPos);
if(MouseEventFlags&MOUSE_MOVED)
{
if(!Selection)
diff --git a/far2l/src/edit.hpp b/far2l/src/edit.hpp
index bd2aea06..ec531f16 100644
--- a/far2l/src/edit.hpp
+++ b/far2l/src/edit.hpp
@@ -136,6 +136,7 @@ class Edit:public ScreenObject
Edit *m_prev;
private:
+ std::vector<wchar_t> OutStr;
wchar_t *Str;
int StrSize;
@@ -191,9 +192,19 @@ class Edit:public ScreenObject
int CheckCharMask(wchar_t Chr);
int ProcessInsPath(int Key,int PrevSelStart=-1,int PrevSelEnd=0);
- int RealPosToTab(int PrevLength, int PrevPos, int Pos, int* CorrectPos);
+ int RealPosToCell(int PrevLength, int PrevPos, int Pos, int* CorrectPos);
+ void SanitizeSelectionRange();
+ inline const wchar_t* WordDiv() {return strWordDiv->CPtr();};
+
+ protected:
+ int CalcRTrimmedStrSize() const;
+
+ int CalcPosFwdTo(int Pos, int LimitPos = -1) const;
+ int CalcPosBwdTo(int Pos) const;
+
+ inline int CalcPosFwd(int LimitPos = -1) const { return CalcPosFwdTo(CurPos, LimitPos); }
+ inline int CalcPosBwd() const { return CalcPosBwdTo(CurPos); }
- inline const wchar_t* WordDiv(void) {return strWordDiv->CPtr();};
public:
Edit(ScreenObject *pOwner = nullptr, Callback* aCallback = nullptr, bool bAllocateData = true);
virtual ~Edit();
@@ -254,8 +265,8 @@ class Edit:public ScreenObject
int GetClearFlag() {return Flags.Check(FEDITLINE_CLEARFLAG);}
void SetCurPos(int NewPos) {CurPos=NewPos; PrevCurPos=NewPos;}
int GetCurPos() {return(CurPos);}
- int GetTabCurPos();
- void SetTabCurPos(int NewPos);
+ int GetCellCurPos();
+ void SetCellCurPos(int NewPos);
int GetLeftPos() {return(LeftPos);}
void SetLeftPos(int NewPos) {LeftPos=NewPos;}
void SetPasswordMode(int Mode) {Flags.Change(FEDITLINE_PASSWORDMODE,Mode);};
@@ -273,8 +284,8 @@ class Edit:public ScreenObject
void SetConvertTabs(int Mode) { TabExpandMode = Mode;};
int GetConvertTabs() {return TabExpandMode;};
- int RealPosToTab(int Pos);
- int TabPosToReal(int Pos);
+ int RealPosToCell(int Pos);
+ int CellPosToReal(int Pos);
void Select(int Start,int End);
void AddSelect(int Start,int End);
void GetSelection(int &Start,int &End);
@@ -282,7 +293,7 @@ class Edit:public ScreenObject
void GetRealSelection(int &Start,int &End);
void SetEditBeyondEnd(int Mode) {Flags.Change(FEDITLINE_EDITBEYONDEND,Mode);};
void SetEditorMode(int Mode) {Flags.Change(FEDITLINE_EDITORMODE,Mode);};
- void ReplaceTabs();
+ void ExpandTabs();
void InsertTab();
diff --git a/far2l/src/editor.cpp b/far2l/src/editor.cpp
index ecca4527..b7ed7eba 100644
--- a/far2l/src/editor.cpp
+++ b/far2l/src/editor.cpp
@@ -315,7 +315,7 @@ void Editor::ShowEditor(int CurLineOnly)
//DisableOut=FALSE;
}
- CurPos=CurLine->GetTabCurPos();
+ CurPos=CurLine->GetCellCurPos();
if (!EdOpt.CursorBeyondEOL)
{
@@ -327,7 +327,7 @@ void Editor::ShowEditor(int CurLineOnly)
{
CurLine->SetCurPos(Length);
CurLine->SetLeftPos(0);
- CurPos=CurLine->GetTabCurPos();
+ CurPos=CurLine->GetCellCurPos();
}
}
@@ -393,7 +393,7 @@ void Editor::ShowEditor(int CurLineOnly)
//CurPtr->SetTables(UseDecodeTable ? &TableSet:nullptr);
//_D(SysLog(L"Setleftpos 3 to %i",LeftPos));
CurPtr->SetLeftPos(LeftPos);
- CurPtr->SetTabCurPos(CurPos);
+ CurPtr->SetCellCurPos(CurPos);
CurPtr->FastShow();
CurPtr->SetEditBeyondEnd(EdOpt.CursorBeyondEOL);
CurPtr=CurPtr->m_next;
@@ -482,9 +482,9 @@ int Editor::BlockStart2NumLine(int *Pos)
if (Pos)
{
if (VBlockStart)
- *Pos=eBlock->RealPosToTab(eBlock->TabPosToReal(VBlockX));
+ *Pos=eBlock->RealPosToCell(eBlock->CellPosToReal(VBlockX));
else
- *Pos=eBlock->RealPosToTab(eBlock->SelStart);
+ *Pos=eBlock->RealPosToCell(eBlock->SelStart);
}
return CalcDistance(TopList,eBlock,-1);
@@ -508,7 +508,7 @@ int Editor::BlockEnd2NumLine(int *Pos)
{
for (int Line=VBlockSizeY; eLine && Line > 0; Line--, eLine=eLine->m_next)
{
- iPos=eLine->RealPosToTab(eLine->TabPosToReal(VBlockX+VBlockSizeX));
+ iPos=eLine->RealPosToCell(eLine->CellPosToReal(VBlockX+VBlockSizeX));
iLine++;
}
@@ -543,7 +543,7 @@ int Editor::BlockEnd2NumLine(int *Pos)
}
else
{
- iPos=eLine->RealPosToTab(EndSel);
+ iPos=eLine->RealPosToCell(EndSel);
iLine++;
}
@@ -576,7 +576,7 @@ int64_t Editor::VMProcess(int OpCode,void *vParam,int64_t iParam)
case MCODE_C_SELECTED:
return (int64_t)(BlockStart || VBlockStart?TRUE:FALSE);
case MCODE_V_EDITORCURPOS:
- return (int64_t)(CurLine->GetTabCurPos()+1);
+ return (int64_t)(CurLine->GetCellCurPos()+1);
case MCODE_V_EDITORREALPOS:
return (int64_t)(CurLine->GetCurPos()+1);
case MCODE_V_EDITORCURLINE:
@@ -693,7 +693,7 @@ int64_t Editor::VMProcess(int OpCode,void *vParam,int64_t iParam)
if (iLine > -1 && iPos > -1)
{
GoToLine(iLine);
- CurLine->SetCurPos(CurLine->TabPosToReal(iPos));
+ CurLine->SetCurPos(CurLine->CellPosToReal(iPos));
return 1;
}
@@ -1160,11 +1160,11 @@ int Editor::ProcessKey(int Key)
{
if (SelAtBeginning || SelFirst)
{
- CurLine->Select(SelStart-1,SelEnd);
+ CurLine->Select(CurLine->CalcPosBwdTo(SelStart), SelEnd);
}
else
{
- CurLine->Select(SelStart,SelEnd-1);
+ CurLine->Select(SelStart, CurLine->CalcPosBwdTo(SelEnd));
}
}
@@ -1194,11 +1194,11 @@ int Editor::ProcessKey(int Key)
if (SelAtBeginning)
{
- CurLine->Select(SelStart+1,SelEnd);
+ CurLine->Select(CurLine->CalcPosFwdTo(SelStart), SelEnd);
}
else
{
- CurLine->Select(SelStart,SelEnd+1);
+ CurLine->Select(SelStart, CurLine->CalcPosFwdTo(SelEnd));
}
Edit *OldCur=CurLine;
@@ -1330,7 +1330,7 @@ int Editor::ProcessKey(int Key)
{
if (!CurLine->m_next)return TRUE;
- CurPos=CurLine->RealPosToTab(CurPos);
+ CurPos=CurLine->RealPosToCell(CurPos);
if (SelAtBeginning)//Снимаем выделение
{
@@ -1347,9 +1347,9 @@ int Editor::ProcessKey(int Key)
CurLine->m_next->GetRealSelection(SelStart,SelEnd);
- if (SelStart!=-1)SelStart=CurLine->m_next->RealPosToTab(SelStart);
+ if (SelStart!=-1)SelStart=CurLine->m_next->RealPosToCell(SelStart);
- if (SelEnd!=-1)SelEnd=CurLine->m_next->RealPosToTab(SelEnd);
+ if (SelEnd!=-1)SelEnd=CurLine->m_next->RealPosToCell(SelEnd);
if (SelStart==-1)
{
@@ -1369,9 +1369,9 @@ int Editor::ProcessKey(int Key)
}
}
- if (SelStart!=-1)SelStart=CurLine->m_next->TabPosToReal(SelStart);
+ if (SelStart!=-1)SelStart=CurLine->m_next->CellPosToReal(SelStart);
- if (SelEnd!=-1)SelEnd=CurLine->m_next->TabPosToReal(SelEnd);
+ if (SelEnd!=-1)SelEnd=CurLine->m_next->CellPosToReal(SelEnd);
/*if(!EdOpt.CursorBeyondEOL && SelEnd>CurLine->m_next->GetLength())
{
@@ -1385,8 +1385,8 @@ int Editor::ProcessKey(int Key)
else //расширяем выделение
{
CurLine->Select(SelStart,-1);
- SelStart=CurLine->m_next->TabPosToReal(0);
- SelEnd=CurLine->m_next->TabPosToReal(CurPos);
+ SelStart=CurLine->m_next->CellPosToReal(0);
+ SelEnd=CurLine->m_next->CellPosToReal(CurPos);
}
if (!EdOpt.CursorBeyondEOL && SelEnd > CurLine->m_next->GetLength())
@@ -1414,22 +1414,22 @@ int Editor::ProcessKey(int Key)
if (SelAtBeginning || SelFirst) // расширяем выделение
{
CurLine->Select(0,SelEnd);
- SelStart=CurLine->RealPosToTab(CurPos);
+ SelStart=CurLine->RealPosToCell(CurPos);
if (!EdOpt.CursorBeyondEOL &&
- CurLine->m_prev->TabPosToReal(SelStart)>CurLine->m_prev->GetLength())
+ CurLine->m_prev->CellPosToReal(SelStart)>CurLine->m_prev->GetLength())
{
- SelStart=CurLine->m_prev->RealPosToTab(CurLine->m_prev->GetLength());
+ SelStart=CurLine->m_prev->RealPosToCell(CurLine->m_prev->GetLength());
}
- SelStart=CurLine->m_prev->TabPosToReal(SelStart);
+ SelStart=CurLine->m_prev->CellPosToReal(SelStart);
CurLine->m_prev->Select(SelStart,-1);
BlockStart=CurLine->m_prev;
BlockStartLine=NumLine-1;
}
else // снимаем выделение
{
- CurPos=CurLine->RealPosToTab(CurPos);
+ CurPos=CurLine->RealPosToCell(CurPos);
if (!SelStart)
{
@@ -1442,15 +1442,15 @@ int Editor::ProcessKey(int Key)
CurLine->m_prev->GetRealSelection(SelStart,SelEnd);
- if (SelStart!=-1)SelStart=CurLine->m_prev->RealPosToTab(SelStart);
+ if (SelStart!=-1)SelStart=CurLine->m_prev->RealPosToCell(SelStart);
- if (SelStart!=-1)SelEnd=CurLine->m_prev->RealPosToTab(SelEnd);
+ if (SelStart!=-1)SelEnd=CurLine->m_prev->RealPosToCell(SelEnd);
if (SelStart==-1)
{
BlockStart=CurLine->m_prev;
BlockStartLine=NumLine-1;
- SelStart=CurLine->m_prev->TabPosToReal(CurPos);
+ SelStart=CurLine->m_prev->CellPosToReal(CurPos);
SelEnd=-1;
}
else
@@ -1465,8 +1465,8 @@ int Editor::ProcessKey(int Key)
SelEnd=CurPos;
}
- SelStart=CurLine->m_prev->TabPosToReal(SelStart);
- SelEnd=CurLine->m_prev->TabPosToReal(SelEnd);
+ SelStart=CurLine->m_prev->CellPosToReal(SelStart);
+ SelEnd=CurLine->m_prev->CellPosToReal(SelEnd);
if (!EdOpt.CursorBeyondEOL && SelEnd>CurLine->m_prev->GetLength())
{
@@ -1754,11 +1754,11 @@ int Editor::ProcessKey(int Key)
else
Show();
- if (PrevMaxPos>CurLine->GetTabCurPos())
+ if (PrevMaxPos>CurLine->GetCellCurPos())
{
- CurLine->SetTabCurPos(PrevMaxPos);
+ CurLine->SetCellCurPos(PrevMaxPos);
CurLine->FastShow();
- CurLine->SetTabCurPos(PrevMaxPos);
+ CurLine->SetCellCurPos(PrevMaxPos);
Show();
}
}
@@ -1777,11 +1777,11 @@ int Editor::ProcessKey(int Key)
else
Show();
- if (PrevMaxPos>CurLine->GetTabCurPos())
+ if (PrevMaxPos>CurLine->GetCellCurPos())
{
- CurLine->SetTabCurPos(PrevMaxPos);
+ CurLine->SetCellCurPos(PrevMaxPos);
CurLine->FastShow();
- CurLine->SetTabCurPos(PrevMaxPos);
+ CurLine->SetCellCurPos(PrevMaxPos);
Show();
}
}
@@ -1866,14 +1866,14 @@ int Editor::ProcessKey(int Key)
{
{
Flags.Set(FEDITOR_NEWUNDO);
- int StartPos=CurLine->GetTabCurPos();
+ int StartPos=CurLine->GetCellCurPos();
NumLine=0;
TopScreen=CurLine=TopList;
if (Key == KEY_CTRLHOME || Key == KEY_CTRLNUMPAD7)
CurLine->SetCurPos(0);
else
- CurLine->SetTabCurPos(StartPos);
+ CurLine->SetCellCurPos(StartPos);
Show();
}
@@ -1884,7 +1884,7 @@ int Editor::ProcessKey(int Key)
{
{
Flags.Set(FEDITOR_NEWUNDO);
- int StartPos=CurLine->GetTabCurPos();
+ int StartPos=CurLine->GetCellCurPos();
NumLine=NumLastLine-1;
CurLine=EndList;
@@ -1902,7 +1902,7 @@ int Editor::ProcessKey(int Key)
CurLine->FastShow();
}
else
- CurLine->SetTabCurPos(StartPos);
+ CurLine->SetCellCurPos(StartPos);
Show();
}
@@ -2138,9 +2138,9 @@ int Editor::ProcessKey(int Key)
Pasting++;
{
- int Delta=CurLine->GetTabCurPos()-CurLine->RealPosToTab(CurPos-1);
+ int Delta=CurLine->GetCellCurPos()-CurLine->RealPosToCell(CurPos-1);
- if (CurLine->GetTabCurPos()>VBlockX)
+ if (CurLine->GetCellCurPos()>VBlockX)
VBlockSizeX-=Delta;
else
{
@@ -2168,7 +2168,7 @@ int Editor::ProcessKey(int Key)
case KEY_ALTRIGHT:
{
/* $ 23.10.2000 tran
- вместо GetTabCurPos надо вызывать GetCurPos -
+ вместо GetCellCurPos надо вызывать GetCurPos -
сравнивать реальную позицию с реальной длиной
а было сравнение видимой позицией с реальной длиной*/
if (!EdOpt.CursorBeyondEOL && CurLine->GetCurPos()>=CurLine->GetLength())
@@ -2186,14 +2186,14 @@ int Editor::ProcessKey(int Key)
выделится блок шириной в 1 колонку, нажми еще alt-right
выделение сбросится
*/
- int VisPos=CurLine->RealPosToTab(CurPos),
- NextVisPos=CurLine->RealPosToTab(CurPos+1);
+ int VisPos=CurLine->RealPosToCell(CurPos),
+ NextVisPos=CurLine->RealPosToCell(CurPos+1);
//_D(SysLog(L"CurPos=%i, VisPos=%i, NextVisPos=%i",
- // CurPos,VisPos, NextVisPos); //,CurLine->GetTabCurPos()));
+ // CurPos,VisPos, NextVisPos); //,CurLine->GetCellCurPos()));
Delta=NextVisPos-VisPos;
//_D(SysLog(L"Delta=%i",Delta));
- if (CurLine->GetTabCurPos()>=VBlockX+VBlockSizeX)
+ if (CurLine->GetCellCurPos()>=VBlockX+VBlockSizeX)
VBlockSizeX+=Delta;
else
{
@@ -2692,7 +2692,7 @@ int Editor::ProcessKey(int Key)
if (PrevLine)
{
- int TabPos=CurLine->GetTabCurPos();
+ int TabPos=CurLine->GetCellCurPos();
CurLine->SetCurPos(0);
const wchar_t *PrevStr=nullptr;
int PrevLength=0;
@@ -2700,7 +2700,7 @@ int Editor::ProcessKey(int Key)
for (int I=0; I<PrevLength && IsSpace(PrevStr[I]); I++)
{
- int NewTabPos=CurLine->GetTabCurPos();
+ int NewTabPos=CurLine->GetCellCurPos();
if (NewTabPos==TabPos)
break;
@@ -2709,7 +2709,7 @@ int Editor::ProcessKey(int Key)
{
CurLine->ProcessKey(KEY_BS);
- while (CurLine->GetTabCurPos()<TabPos)
+ while (CurLine->GetCellCurPos()<TabPos)
CurLine->ProcessKey(' ');
break;
@@ -2719,7 +2719,7 @@ int Editor::ProcessKey(int Key)
CurLine->ProcessKey(PrevStr[I]);
}
- CurLine->SetTabCurPos(TabPos);
+ CurLine->SetCellCurPos(TabPos);
}
}
@@ -3110,7 +3110,7 @@ void Editor::DeleteString(Edit *DelPtr, int LineNumber, int DeleteLast,int UndoL
if (CurLine==DelPtr)
{
int LeftPos,CurPos;
- CurPos=DelPtr->GetTabCurPos();
+ CurPos=DelPtr->GetCellCurPos();
LeftPos=DelPtr->GetLeftPos();
if (DelPtr->m_next)
@@ -3125,7 +3125,7 @@ void Editor::DeleteString(Edit *DelPtr, int LineNumber, int DeleteLast,int UndoL
}
CurLine->SetLeftPos(LeftPos);
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
}
if (DelPtr->m_prev)
@@ -3244,7 +3244,7 @@ void Editor::InsertString()
if (!IsSpace(Str[I]))
{
PrevLine->SetCurPos(I);
- IndentPos=PrevLine->GetTabCurPos();
+ IndentPos=PrevLine->GetCellCurPos();
SrcIndent=PrevLine;
Found=TRUE;
break;
@@ -3366,7 +3366,7 @@ void Editor::InsertString()
Decrement++;
else
{
- int TabPos=CurLine->RealPosToTab(I);
+ int TabPos=CurLine->RealPosToCell(I);
Decrement+=EdOpt.TabSize - (TabPos % EdOpt.TabSize);
}
}
@@ -3389,7 +3389,7 @@ void Editor::InsertString()
SrcIndent->GetBinaryString(&PrevStr,nullptr,PrevLength);
}
- for (int I=0; CurLine->GetTabCurPos()<IndentPos; I++)
+ for (int I=0; CurLine->GetCellCurPos()<IndentPos; I++)
{
if (SrcIndent && I<PrevLength && IsSpace(PrevStr[I]))
{
@@ -3401,13 +3401,13 @@ void Editor::InsertString()
}
}
- while (CurLine->GetTabCurPos()>IndentPos)
+ while (CurLine->GetCellCurPos()>IndentPos)
CurLine->ProcessKey(KEY_BS);
CurLine->SetOvertypeMode(SaveOvertypeMode);
}
- CurLine->SetTabCurPos(IndentPos);
+ CurLine->SetCellCurPos(IndentPos);
}
CurLine->GetBinaryString(&CurLineStr,nullptr,Length);
@@ -3453,12 +3453,12 @@ void Editor::Down()
if (Y>=Y2-Y1)
TopScreen=TopScreen->m_next;
- CurPos=CurLine->GetTabCurPos();
+ CurPos=CurLine->GetCellCurPos();
LeftPos=CurLine->GetLeftPos();
CurLine=CurLine->m_next;
NumLine++;
CurLine->SetLeftPos(LeftPos);
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
}
@@ -3477,12 +3477,12 @@ void Editor::ScrollDown()
}
TopScreen=TopScreen->m_next;
- CurPos=CurLine->GetTabCurPos();
+ CurPos=CurLine->GetCellCurPos();
LeftPos=CurLine->GetLeftPos();
CurLine=CurLine->m_next;
NumLine++;
CurLine->SetLeftPos(LeftPos);
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
}
@@ -3497,12 +3497,12 @@ void Editor::Up()
if (CurLine==TopScreen)
TopScreen=TopScreen->m_prev;
- CurPos=CurLine->GetTabCurPos();
+ CurPos=CurLine->GetCellCurPos();
LeftPos=CurLine->GetLeftPos();
CurLine=CurLine->m_prev;
NumLine--;
CurLine->SetLeftPos(LeftPos);
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
}
@@ -3521,12 +3521,12 @@ void Editor::ScrollUp()
}
TopScreen=TopScreen->m_prev;
- CurPos=CurLine->GetTabCurPos();
+ CurPos=CurLine->GetCellCurPos();
LeftPos=CurLine->GetLeftPos();
CurLine=CurLine->m_prev;
NumLine--;
CurLine->SetLeftPos(LeftPos);
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
}
/* $ 21.01.2001 SVS
@@ -3698,10 +3698,10 @@ BOOL Editor::Search(int Next)
TopScreen=TmpPtr;
NumLine=NewNumLine;
int LeftPos=CurPtr->GetLeftPos();
- int TabCurPos=CurPtr->GetTabCurPos();
+ int CellCurPos=CurPtr->GetCellCurPos();
- if (ObjWidth>8 && TabCurPos-LeftPos+SearchLength>ObjWidth-8)
- CurPtr->SetLeftPos(TabCurPos+SearchLength-ObjWidth+8);
+ if (ObjWidth>8 && CellCurPos-LeftPos+SearchLength>ObjWidth-8)
+ CurPtr->SetLeftPos(CellCurPos+SearchLength-ObjWidth+8);
if (ReplaceMode)
{
@@ -3712,7 +3712,7 @@ BOOL Editor::Search(int Next)
Show();
SHORT CurX,CurY;
GetCursorPos(CurX,CurY);
- ScrBuf.ApplyColor(CurX,CurY,CurPtr->RealPosToTab(CurPtr->TabPosToReal(CurX)+SearchLength)-1,CurY,FarColorToReal(COL_EDITORSELECTEDTEXT));
+ ScrBuf.ApplyColor(CurX,CurY,CurPtr->RealPosToCell(CurPtr->CellPosToReal(CurX)+SearchLength)-1,CurY,FarColorToReal(COL_EDITORSELECTEDTEXT));
FARString strQSearchStr(CurPtr->GetStringAddr()+CurPtr->GetCurPos(),SearchLength), strQReplaceStr=strReplaceStrCurrent;
InsertQuote(strQSearchStr);
InsertQuote(strQReplaceStr);
@@ -4371,7 +4371,7 @@ void Editor::GoToLine(int Line)
bool bReverse = false;
int LastNumLine=NumLine;
int CurScrLine=CalcDistance(TopScreen,CurLine,-1);
- int CurPos=CurLine->GetTabCurPos();
+ int CurPos=CurLine->GetCellCurPos();
int LeftPos=CurLine->GetLeftPos();
if (Line < NumLine)
@@ -4413,7 +4413,7 @@ void Editor::GoToLine(int Line)
TopScreen=CurLine;
CurLine->SetLeftPos(LeftPos);
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
}
// <GOTO_UNMARK:2>
@@ -4433,7 +4433,7 @@ void Editor::GoToPosition()
Builder.ShowDialog();
if(!strData.IsEmpty())
{
- int LeftPos=CurLine->GetTabCurPos()+1;
+ int LeftPos=CurLine->GetCellCurPos()+1;
int CurPos=CurLine->GetCurPos();
int NewLine=0, NewCol=0;
@@ -4442,12 +4442,12 @@ void Editor::GoToPosition()
if (NewCol == -1)
{
- CurLine->SetTabCurPos(CurPos);
+ CurLine->SetCellCurPos(CurPos);
CurLine->SetLeftPos(LeftPos);
}
else
{
- CurLine->SetTabCurPos(NewCol);
+ CurLine->SetCellCurPos(NewCol);
}
Show();
}
@@ -4458,7 +4458,7 @@ void Editor::GetRowCol(const wchar_t *_argv,int *row,int *col)
int x=0xffff,y;
int l;
wchar_t *argvx=0;
- int LeftPos=CurLine->GetTabCurPos() + 1;
+ int LeftPos=CurLine->GetCellCurPos() + 1;
FARString strArg = _argv;
// что бы не оставить "врагу" выбора - только то, что мы хотим ;-)
// "прибьем" все внешние пробелы.
@@ -4931,7 +4931,7 @@ void Editor::DeleteVBlock()
{
TopScreen=NewTopScreen;
CurLine=CurPtr;
- CurPtr->SetTabCurPos(VBlockX);
+ CurPtr->SetCellCurPos(VBlockX);
break;
}
@@ -4949,9 +4949,9 @@ void Editor::DeleteVBlock()
for (int Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
{
TextChanged(1);
- int TBlockX=CurPtr->TabPosToReal(VBlockX);
- int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
- CurPtr->TabPosToReal(VBlockX);
+ int TBlockX=CurPtr->CellPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->CellPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->CellPosToReal(VBlockX);
const wchar_t *CurStr,*EndSeq;
int Length;
CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
@@ -5048,8 +5048,8 @@ wchar_t *Editor::VBlock2Text(wchar_t *ptrInitData)
for (int Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
{
- int TBlockX=CurPtr->TabPosToReal(VBlockX);
- int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-TBlockX;
+ int TBlockX=CurPtr->CellPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->CellPosToReal(VBlockX+VBlockSizeX)-TBlockX;
const wchar_t *CurStr,*EndSeq;
int Length;
CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
@@ -5104,7 +5104,7 @@ void Editor::VPaste(wchar_t *ClipText)
VBlockStart=CurLine;
BlockStartLine=NumLine;
- int StartPos=CurLine->GetTabCurPos();
+ int StartPos=CurLine->GetCellCurPos();
VBlockX=StartPos;
VBlockSizeX=0;
VBlockY=NumLine;
@@ -5120,7 +5120,7 @@ void Editor::VPaste(wchar_t *ClipText)
{
const size_t EolLength = (ClipText[I] == '\r' || ClipText[I + 1] == '\n') ? 2 : 1;
- int CurWidth=CurLine->GetTabCurPos()-StartPos;
+ int CurWidth=CurLine->GetCellCurPos()-StartPos;
if (CurWidth>VBlockSizeX)
VBlockSizeX=CurWidth;
@@ -5147,7 +5147,7 @@ void Editor::VPaste(wchar_t *ClipText)
else
{
ProcessKey(KEY_DOWN);
- CurLine->SetTabCurPos(StartPos);
+ CurLine->SetCellCurPos(StartPos);
CurLine->SetOvertypeMode(FALSE);
}
@@ -5155,7 +5155,7 @@ void Editor::VPaste(wchar_t *ClipText)
continue;
}
- int CurWidth=CurLine->GetTabCurPos()-StartPos;
+ int CurWidth=CurLine->GetCellCurPos()-StartPos;
if (CurWidth>VBlockSizeX)
VBlockSizeX=CurWidth;
@@ -5172,7 +5172,7 @@ void Editor::VPaste(wchar_t *ClipText)
TopScreen=SavedTopScreen;
CurLine=VBlockStart;
NumLine=BlockStartLine;
- CurLine->SetTabCurPos(StartPos);
+ CurLine->SetCellCurPos(StartPos);
Pasting--;
Unlock();
AddUndoData(UNDO_END);
@@ -5193,9 +5193,9 @@ void Editor::VBlockShift(int Left)
for (int Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
{
TextChanged(1);
- int TBlockX=CurPtr->TabPosToReal(VBlockX);
- int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
- CurPtr->TabPosToReal(VBlockX);
+ int TBlockX=CurPtr->CellPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->CellPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->CellPosToReal(VBlockX);
const wchar_t *CurStr,*EndSeq;
int Length;
CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
@@ -5206,11 +5206,11 @@ void Editor::VBlockShift(int Left)
if ((Left && CurStr[TBlockX-1]==L'\t') ||
(!Left && TBlockX+TBlockSizeX<Length && CurStr[TBlockX+TBlockSizeX]==L'\t'))
{
- CurPtr->ReplaceTabs();
+ CurPtr->ExpandTabs();
CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
- TBlockX=CurPtr->TabPosToReal(VBlockX);
- TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
- CurPtr->TabPosToReal(VBlockX);
+ TBlockX=CurPtr->CellPosToReal(VBlockX);
+ TBlockSizeX=CurPtr->CellPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->CellPosToReal(VBlockX);
}
AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),BlockStartLine+Line,CurPtr->GetCurPos(),CurPtr->GetLength());
@@ -5249,7 +5249,7 @@ void Editor::VBlockShift(int Left)
}
VBlockX+=Left ? -1:1;
- CurLine->SetTabCurPos(Left ? VBlockX:VBlockX+VBlockSizeX);
+ CurLine->SetCellCurPos(Left ? VBlockX:VBlockX+VBlockSizeX);
AddUndoData(UNDO_END);
}
@@ -5291,10 +5291,10 @@ int Editor::EditorControl(int Command,void *Param)
}
else if (VBlockStart && DestLine>=VBlockY && DestLine<VBlockY+VBlockSizeY)
{
- GetString->SelStart=CurPtr->TabPosToReal(VBlockX);
+ GetString->SelStart=CurPtr->CellPosToReal(VBlockX);
GetString->SelEnd=GetString->SelStart+
- CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
- CurPtr->TabPosToReal(VBlockX);
+ CurPtr->CellPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->CellPosToReal(VBlockX);
}
_ECTLLOG(SysLog(L"EditorGetString{"));
@@ -5467,7 +5467,7 @@ int Editor::EditorControl(int Command,void *Param)
Info->TotalLines=NumLastLine;
Info->CurLine=NumLine;
Info->CurPos=CurLine->GetCurPos();
- Info->CurTabPos=CurLine->GetTabCurPos();
+ Info->CurTabPos=CurLine->GetCellCurPos();
Info->TopScreenLine=NumLine-CalcDistance(TopScreen,CurLine,-1);
Info->LeftPos=CurLine->GetLeftPos();
Info->Overtype=Flags.Check(FEDITOR_OVERTYPE);
@@ -5559,7 +5559,7 @@ int Editor::EditorControl(int Command,void *Param)
CurLine->SetCurPos(Pos->CurPos);
if (Pos->CurTabPos >= 0)
- CurLine->SetTabCurPos(Pos->CurTabPos);
+ CurLine->SetCellCurPos(Pos->CurTabPos);
if (Pos->LeftPos >= 0)
CurLine->SetLeftPos(Pos->LeftPos);
@@ -5687,7 +5687,7 @@ int Editor::EditorControl(int Command,void *Param)
return FALSE;
}
- ecp->DestPos=CurPtr->TabPosToReal(ecp->SrcPos);
+ ecp->DestPos=CurPtr->CellPosToReal(ecp->SrcPos);
_ECTLLOG(SysLog(L"EditorConvertPos{"));
_ECTLLOG(SysLog(L" StringNumber =%d",ecp->StringNumber));
_ECTLLOG(SysLog(L" SrcPos =%d",ecp->SrcPos));
@@ -5711,7 +5711,7 @@ int Editor::EditorControl(int Command,void *Param)
return FALSE;
}
- ecp->DestPos=CurPtr->RealPosToTab(ecp->SrcPos);
+ ecp->DestPos=CurPtr->RealPosToCell(ecp->SrcPos);
_ECTLLOG(SysLog(L"EditorConvertPos{"));
_ECTLLOG(SysLog(L" StringNumber =%d",ecp->StringNumber));
_ECTLLOG(SysLog(L" SrcPos =%d",ecp->SrcPos));
@@ -5741,7 +5741,7 @@ int Editor::EditorControl(int Command,void *Param)
}
AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),StringNumber,CurPtr->GetCurPos(),CurPtr->GetLength());
- CurPtr->ReplaceTabs();
+ CurPtr->ExpandTabs();
}
return TRUE;
@@ -6381,14 +6381,14 @@ void Editor::SetReplaceMode(int Mode)
int Editor::GetLineCurPos()
{
- return CurLine->GetTabCurPos();
+ return CurLine->GetCellCurPos();
}
void Editor::BeginVBlockMarking()
{
UnmarkBlock();
VBlockStart=CurLine;
- VBlockX=CurLine->GetTabCurPos();
+ VBlockX=CurLine->GetCellCurPos();
VBlockSizeX=0;
VBlockY=NumLine;
VBlockSizeY=1;
@@ -6454,9 +6454,9 @@ void Editor::Xlat()
for (Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
{
- int TBlockX=CurPtr->TabPosToReal(VBlockX);
- int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
- CurPtr->TabPosToReal(VBlockX);
+ int TBlockX=CurPtr->CellPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->CellPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->CellPosToReal(VBlockX);
const wchar_t *CurStr,*EndSeq;
int Length;
CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
@@ -6580,7 +6580,7 @@ void Editor::SetConvertTabs(int NewMode)
CurPtr->SetConvertTabs(NewMode);
if (NewMode == EXPAND_ALLTABS)
- CurPtr->ReplaceTabs();
+ CurPtr->ExpandTabs();
CurPtr=CurPtr->m_next;
}
@@ -6693,7 +6693,7 @@ void Editor::EditorShowMsg(const wchar_t *Title,const wchar_t *Msg, const wchar_
wmemset(Progress+(CurPos),BoxSymbols[BS_X_B0],Length-CurPos);
strProgress.ReleaseBuffer(Length);
FormatString strTmp;
- strTmp<<L" "<<fmt::Width(PercentLength)<<strPercent<<L"%";
+ strTmp<<L" "<<fmt::Expand(PercentLength)<<strPercent<<L"%";
strProgress+=strTmp;
}
@@ -6840,7 +6840,7 @@ void Editor::SetCacheParams(EditorCacheParams *pp)
for (DWORD I=0; I < (DWORD)pp->ScreenLine; I++)
ProcessKey(KEY_DOWN);
- CurLine->SetTabCurPos(pp->LinePos);
+ CurLine->SetCellCurPos(pp->LinePos);
Unlock();
}
@@ -6877,7 +6877,7 @@ void Editor::SetCacheParams(EditorCacheParams *pp)
ProcessKey(KEY_DOWN);
if(translateTabs) CurLine->SetCurPos(pp->LinePos);
- else CurLine->SetTabCurPos(pp->LinePos);
+ else CurLine->SetCellCurPos(pp->LinePos);
CurLine->SetLeftPos(pp->LeftPos);
Unlock();
}
@@ -6890,7 +6890,7 @@ void Editor::GetCacheParams(EditorCacheParams *pp)
memset(&pp->SavePos,0xff,sizeof(InternalEditorBookMark));
pp->Line = NumLine;
pp->ScreenLine = CalcDistance(TopScreen, CurLine,-1);
- pp->LinePos = CurLine->GetTabCurPos();
+ pp->LinePos = CurLine->GetCellCurPos();
pp->LeftPos = CurLine->GetLeftPos();
pp->CodePage = m_codepage;
@@ -6963,7 +6963,7 @@ void Editor::SetCurPos(int NewCol, int NewRow)
{
Lock();
GoToLine(NewRow);
- CurLine->SetTabCurPos(NewCol);
+ CurLine->SetCellCurPos(NewCol);
//CurLine->SetLeftPos(LeftPos); ???
Unlock();
}
diff --git a/far2l/src/execute.cpp b/far2l/src/execute.cpp
index af56b175..9dd96fbd 100644
--- a/far2l/src/execute.cpp
+++ b/far2l/src/execute.cpp
@@ -388,7 +388,7 @@ int CommandLine::CmdExecute(const wchar_t *CmdLine, bool SeparateWindow, bool Di
{
//CmdStr.SetString(L"");
GotoXY(X1,Y1);
- FS<<fmt::Width(X2-X1+1)<<L"";
+ FS << fmt::Cells() << fmt::Expand(X2 - X1 + 1) << L"";
Show();
ScrBuf.Flush();
}
diff --git a/far2l/src/execute_oscmd.cpp b/far2l/src/execute_oscmd.cpp
index 6e25044c..fa4b7027 100644
--- a/far2l/src/execute_oscmd.cpp
+++ b/far2l/src/execute_oscmd.cpp
@@ -165,7 +165,7 @@ BOOL CommandLine::IntChDir(const wchar_t *CmdLine,int ClosePlugin,bool Silent)
{
//CmdStr.SetString(L"");
GotoXY(X1,Y1);
- FS<<fmt::Width(X2-X1+1)<<L"";
+ FS<<fmt::Expand(X2-X1+1)<<L"";
Show();
return TRUE;
}
diff --git a/far2l/src/fileedit.cpp b/far2l/src/fileedit.cpp
index 13a40bda..7f85a1b9 100644
--- a/far2l/src/fileedit.cpp
+++ b/far2l/src/fileedit.cpp
@@ -780,7 +780,7 @@ int64_t FileEditor::VMProcess(int OpCode,void *vParam,int64_t iParam)
}
if (OpCode == MCODE_V_EDITORCURPOS)
- return (int64_t)(m_editor->CurLine->GetTabCurPos()+1);
+ return (int64_t)(m_editor->CurLine->GetCellCurPos()+1);
if (OpCode == MCODE_V_EDITORCURLINE)
return (int64_t)(m_editor->NumLine+1);
@@ -2286,22 +2286,22 @@ void FileEditor::ShowStatus()
strLineStr.Format(L"%d/%d", m_editor->NumLine+1, m_editor->NumLastLine);
FARString strAttr(AttrStr);
FormatString FString;
- FString<<fmt::LeftAlign()<<fmt::Width(NameLength)<<strLocalTitle<<L' '<<
+ FString<<fmt::LeftAlign()<<fmt::Expand(NameLength)<<strLocalTitle<<L' '<<
(m_editor->Flags.Check(FEDITOR_MODIFIED) ? L'*':L' ')<<
(m_editor->Flags.Check(FEDITOR_LOCKMODE) ? L'-':L' ')<<
(m_editor->Flags.Check(FEDITOR_PROCESSCTRLQ) ? L'"':L' ')<<
- fmt::Width(5)<<EOLName(m_editor->GlobalEOL)<<L' '<<
- fmt::Width(5)<<m_codepage<<L' '<<fmt::Width(7)<<Msg::EditStatusLine<<L' '<<
- fmt::Width(SizeLineStr)<<fmt::Precision(SizeLineStr)<<strLineStr<<L' '<<
- fmt::Width(5)<<Msg::EditStatusCol<<L' '<<
- fmt::LeftAlign()<<fmt::Width(4)<<m_editor->CurLine->GetTabCurPos()+1<<L' '<<
- fmt::Width(3)<<strAttr;
+ fmt::Expand(5)<<EOLName(m_editor->GlobalEOL)<<L' '<<
+ fmt::Expand(5)<<m_codepage<<L' '<<fmt::Expand(7)<<Msg::EditStatusLine<<L' '<<
+ fmt::Expand(SizeLineStr)<<fmt::Truncate(SizeLineStr)<<strLineStr<<L' '<<
+ fmt::Expand(5)<<Msg::EditStatusCol<<L' '<<
+ fmt::LeftAlign()<<fmt::Expand(4)<<m_editor->CurLine->GetCellCurPos()+1<<L' '<<
+ fmt::Expand(3)<<strAttr;
int StatusWidth=ObjWidth - (Opt.ViewerEditorClock && Flags.Check(FFILEEDIT_FULLSCREEN)?5:0);
if (StatusWidth<0)
StatusWidth=0;
- FS<<fmt::LeftAlign()<<fmt::Width(StatusWidth)<<fmt::Precision(StatusWidth)<<FString.strValue();
+ FS<<fmt::LeftAlign()<<fmt::Size(StatusWidth)<<FString.strValue();
{
const wchar_t *Str;
int Length;
diff --git a/far2l/src/filetype.cpp b/far2l/src/filetype.cpp
index 9dbc58b4..bdea190c 100644
--- a/far2l/src/filetype.cpp
+++ b/far2l/src/filetype.cpp
@@ -96,7 +96,7 @@ static int GetDescriptionWidth(ConfigReader &cfg_reader, const wchar_t *Name=nul
if (!Name)
{
- CurWidth = HiStrlen(strDescription);
+ CurWidth = HiStrCellsCount(strDescription);
}
else
{
@@ -105,7 +105,7 @@ static int GetDescriptionWidth(ConfigReader &cfg_reader, const wchar_t *Name=nul
FARString strExpandedDesc = strDescription;
SubstFileName(strExpandedDesc,Name,nullptr,nullptr,TRUE);
- CurWidth = HiStrlen(strExpandedDesc);
+ CurWidth = HiStrCellsCount(strExpandedDesc);
}
if (CurWidth>Width)
diff --git a/far2l/src/fileview.cpp b/far2l/src/fileview.cpp
index a328771b..84eb28b1 100644
--- a/far2l/src/fileview.cpp
+++ b/far2l/src/fileview.cpp
@@ -503,7 +503,7 @@ void FileViewer::ShowStatus()
);
SetColor(COL_VIEWERSTATUS);
GotoXY(X1,Y1);
- FS<<fmt::LeftAlign()<<fmt::Width(View.Width+(View.ViOpt.ShowScrollbar?1:0))<<fmt::Precision(View.Width+(View.ViOpt.ShowScrollbar?1:0))<<strStatus;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(View.Width+(View.ViOpt.ShowScrollbar?1:0)) << strStatus;
if (Opt.ViewerEditorClock && IsFullScreen())
ShowTime(FALSE);
diff --git a/far2l/src/flshow.cpp b/far2l/src/flshow.cpp
index fcb179bf..a0358518 100644
--- a/far2l/src/flshow.cpp
+++ b/far2l/src/flshow.cpp
@@ -97,7 +97,7 @@ void FileList::ShowFileList(int Fast)
FARString strTitle;
FARString strInfoCurDir;
- int Length;
+ int Cells;
OpenPluginInfo Info;
if (PanelMode==PLUGIN_PANEL)
@@ -127,7 +127,7 @@ void FileList::ShowFileList(int Fast)
// SetScreen(X1+1,Y1+1,X2-1,Y1+1,' ',COL_PANELTEXT);
SetColor(COL_PANELTEXT); //???
//GotoXY(X1+1,Y1+1);
- //FS<<fmt::Width(X2-X1-1)<<L"";
+ //FS<<fmt::Expand(X2-X1-1)<<L"";
}
for (int I=0,ColumnPos=X1+1; I<ViewSettings.ColumnCount; I++)
@@ -203,7 +203,7 @@ void FileList::ShowFileList(int Fast)
CenterStr(strTitle,strTitleMsg,ViewSettings.ColumnWidth[I]);
SetColor(COL_PANELCOLUMNTITLE);
GotoXY(ColumnPos,Y1+1);
- FS<<fmt::Precision(ViewSettings.ColumnWidth[I])<<strTitleMsg;
+ FS << fmt::Cells() << fmt::Truncate(ViewSettings.ColumnWidth[I]) << strTitleMsg;
}
if (I>=ViewSettings.ColumnCount-1)
@@ -343,7 +343,7 @@ void FileList::ShowFileList(int Fast)
TruncSize-=2;
GetTitle(strTitle,TruncSize,2);//,(PanelMode==PLUGIN_PANEL?0:2));
- Length=(int)strTitle.GetLength();
+ Cells=(int)strTitle.CellsCount();
int ClockCorrection=FALSE;
if ((Opt.Clock && !Opt.ShowMenuBar) && TitleX2==ScrX-4)
@@ -352,11 +352,11 @@ void FileList::ShowFileList(int Fast)
TitleX2+=4;
}
- int TitleX=X1+(TitleX2-X1+1-Length)/2;
+ int TitleX=X1+(TitleX2-X1+1-Cells)/2;
if (ClockCorrection)
{
- int Overlap=TitleX+Length-TitleX2+5;
+ int Overlap=TitleX+Cells-TitleX2+5;
if (Overlap > 0)
TitleX-=Overlap;
@@ -374,7 +374,7 @@ void FileList::ShowFileList(int Fast)
SetScreen(X1+1,Y2-1,X2-1,Y2-1,L' ',COL_PANELTEXT);
SetColor(COL_PANELTEXT); //???
//GotoXY(X1+1,Y2-1);
- //FS<<fmt::Width(X2-X1-1)<<L"";
+ //FS<<fmt::Expand(X2-X1-1)<<L"";
}
if (PanelMode==PLUGIN_PANEL && FileCount>0 && (Info.Flags & OPIF_REALNAMES))
@@ -559,9 +559,9 @@ void FileList::ShowTotalSize(OpenPluginInfo &Info)
Text(strTotalStr);
else
{
- FS<<fmt::Precision(BoxPos)<<strTotalStr;
+ FS << fmt::Cells() << fmt::Truncate(BoxPos) << strTotalStr;
SetColor(COL_PANELBOX);
- FS<<fmt::Precision(BoxLength)<<strTotalStr.CPtr()+BoxPos;
+ FS << fmt::Cells() << fmt::Truncate(BoxLength) << strTotalStr.CPtr() + BoxPos;
SetColor(COL_PANELTOTALINFO);
Text(strTotalStr.CPtr()+BoxPos+BoxLength);
}
@@ -589,14 +589,14 @@ int FileList::ConvertName(const wchar_t *SrcName,FARString &strDest,int MaxLengt
}
}
- wchar_t *lpwszDest = strDest.GetBuffer(MaxLength+1);
- wmemset(lpwszDest,L' ',MaxLength);
- int SrcLength=StrLength(SrcName);
+ int SrcLength = StrLength(SrcName);
+ int SrcVisualLength = StrCellsCount(SrcName, SrcLength);
- if (RightAlign && SrcLength>MaxLength)
+ if (RightAlign && SrcVisualLength > MaxLength)
{
- wmemcpy(lpwszDest,SrcName+SrcLength-MaxLength,MaxLength);
- strDest.ReleaseBuffer(MaxLength);
+ size_t SkipCells = SrcVisualLength - MaxLength;
+ size_t SkipOfs = StrSizeOfCells(SrcName, SrcLength, SkipCells, true);
+ strDest.Copy(SrcName + SkipOfs, SrcLength - SkipOfs);
return TRUE;
}
@@ -604,7 +604,7 @@ int FileList::ConvertName(const wchar_t *SrcName,FARString &strDest,int MaxLengt
if (!ShowStatus &&
((!(FileAttr&FILE_ATTRIBUTE_DIRECTORY) && ViewSettings.AlignExtensions) || ((FileAttr&FILE_ATTRIBUTE_DIRECTORY) && ViewSettings.FolderAlignExtensions))
- && SrcLength<=MaxLength &&
+ && SrcVisualLength<=MaxLength &&
(DotPtr=wcsrchr(SrcName,L'.')) && DotPtr!=SrcName &&
(SrcName[0]!=L'.' || SrcName[2]) && !wcschr(DotPtr+1,L' '))
{
@@ -615,20 +615,23 @@ int FileList::ConvertName(const wchar_t *SrcName,FARString &strDest,int MaxLengt
if (DotPos<=NameLength)
DotPos=NameLength+1;
- if (DotPos>0 && NameLength>0 && SrcName[NameLength-1]==L' ')
- lpwszDest[NameLength]=L'.';
-
- wmemcpy(lpwszDest,SrcName,NameLength);
- wmemcpy(lpwszDest+DotPos,DotPtr+1,DotLength);
+ strDest.Copy(SrcName, NameLength);
+ strDest.Append(L'.');
+ strDest.Append(DotPtr+1,DotLength);
}
else
{
- wmemcpy(lpwszDest,SrcName,Min(SrcLength, MaxLength));
+ size_t CellsCount = MaxLength;
+ size_t CopyLen = StrSizeOfCells(SrcName, SrcLength, CellsCount, false);
+ strDest.Copy(SrcName, CopyLen);
}
- strDest.ReleaseBuffer(MaxLength);
-
- return(SrcLength>MaxLength);
+ const size_t CopiedCellsCount = strDest.CellsCount();
+ if (CopiedCellsCount < size_t(MaxLength)) {
+ strDest.Append(L' ', size_t(MaxLength - CopiedCellsCount));
+ }
+
+ return (SrcVisualLength > MaxLength);
}
@@ -884,6 +887,24 @@ int FileList::PrepareColumnWidths(unsigned int *ColumnTypes,int *ColumnWidths,
extern void GetColor(int PaletteIndex);
+static int MakeCurLeftPos(int ColumnWidth, const wchar_t *Str, int LeftPos, int &MaxLeftPos)
+{
+ int Cells = Str ? StrZCellsCount(Str) : 0;
+ if (Cells < ColumnWidth || !Cells)
+ return 0;
+
+ if (LeftPos > Cells - ColumnWidth)
+ LeftPos = Cells - ColumnWidth;
+
+ size_t ng = LeftPos;
+ int out = StrSizeOfCells(Str, wcslen(Str), ng, false);
+
+ if (MaxLeftPos < (int)ng)
+ MaxLeftPos = (int)ng;
+
+ return out;
+}
+
void FileList::ShowList(int ShowStatus,int StartColumn)
{
int StatusShown=FALSE;
@@ -971,21 +992,10 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (!ShowStatus && LeftPos>0)
{
- int Length=StrLength(ColumnData);
-
- if (Length>ColumnWidth)
- {
- CurLeftPos=LeftPos;
-
- if (CurLeftPos>Length-ColumnWidth)
- CurLeftPos=Length-ColumnWidth;
-
- if (CurLeftPos>MaxLeftPos)
- MaxLeftPos=CurLeftPos;
- }
+ CurLeftPos = MakeCurLeftPos(ColumnWidth, ColumnData, LeftPos, MaxLeftPos);
}
- FS<<fmt::LeftAlign()<<fmt::Width(ColumnWidth)<<fmt::Precision(ColumnWidth)<<ColumnData+CurLeftPos;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(ColumnWidth) << ColumnData + CurLeftPos;
}
else
{
@@ -1033,39 +1043,28 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (!ShowStatus && LeftPos)
{
- int Length = (int)wcslen(NamePtr);
-
- if (Length>Width)
+ if (LeftPos > 0 && !RightAlign)
{
- if (LeftPos>0)
- {
- if (!RightAlign)
- {
- CurLeftPos=LeftPos;
-
- if (Length-CurLeftPos<Width)
- CurLeftPos=Length-Width;
-
- NamePtr += CurLeftPos;
-
- if (CurLeftPos>MaxLeftPos)
- MaxLeftPos=CurLeftPos;
- }
- }
- else if (RightAlign)
+ CurLeftPos = MakeCurLeftPos(Width, NamePtr, LeftPos, MaxLeftPos);
+ NamePtr += CurLeftPos;
+ }
+ else if (RightAlign)
+ {
+ int Cells = (int)StrZCellsCount(NamePtr);
+ if (Cells > Width)
{
- int CurRightPos=LeftPos;
-
- if (Length+CurRightPos<Width)
- CurRightPos=Width-Length;
+ int CurRightPos = LeftPos;
+ if (Cells + CurRightPos < Width)
+ CurRightPos = Width - Cells;
else
- RightBracket=TRUE;
+ RightBracket = TRUE;
- NamePtr += Length+CurRightPos-Width;
- RightAlign=FALSE;
+ size_t ng = Cells + CurRightPos - Width;
+ NamePtr += StrSizeOfCells(NamePtr, wcslen(NamePtr), ng, false);
+ RightAlign = FALSE;
- if (CurRightPos<MinLeftPos)
- MinLeftPos=CurRightPos;
+ if (MinLeftPos > CurRightPos)
+ MinLeftPos = CurRightPos;
}
}
}
@@ -1080,7 +1079,7 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (RightAlign)
LeftBracket=TRUE;
- if (!RightAlign && StrLength(NamePtr)>Width)
+ if (!RightAlign && StrZCellsCount(NamePtr) > size_t(Width))
RightBracket=TRUE;
}
@@ -1173,13 +1172,13 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
break;
}
- FS<<FormatStr_DateTime(FileTime,ColumnType,ColumnTypes[K],ColumnWidth);
+ FS << FormatStr_DateTime(FileTime,ColumnType,ColumnTypes[K],ColumnWidth);
break;
}
case ATTR_COLUMN:
{
- FS<<FormatStr_Attribute(ListData[ListPos]->FileAttr,ListData[ListPos]->FileMode,ColumnWidth);
+ FS << FormatStr_Attribute(ListData[ListPos]->FileAttr,ListData[ListPos]->FileMode,ColumnWidth);
break;
}
@@ -1189,18 +1188,7 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (!ShowStatus && LeftPos>0)
{
- int Length=ListData[ListPos]->DizText ? StrLength(ListData[ListPos]->DizText):0;
-
- if (Length>ColumnWidth)
- {
- CurLeftPos=LeftPos;
-
- if (CurLeftPos>Length-ColumnWidth)
- CurLeftPos=Length-ColumnWidth;
-
- if (CurLeftPos>MaxLeftPos)
- MaxLeftPos=CurLeftPos;
- }
+ CurLeftPos = MakeCurLeftPos(ColumnWidth, ListData[ListPos]->DizText, LeftPos, MaxLeftPos);
}
FARString strDizText=ListData[ListPos]->DizText ? ListData[ListPos]->DizText+CurLeftPos:L"";
@@ -1209,7 +1197,7 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (strDizText.Pos(pos,L'\4'))
strDizText.Truncate(pos);
- FS<<fmt::LeftAlign()<<fmt::Width(ColumnWidth)<<fmt::Precision(ColumnWidth)<<strDizText;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(ColumnWidth) << strDizText;
break;
}
@@ -1233,21 +1221,21 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (!ShowStatus && LeftPos>0)
{
- int Length=StrLength(Owner);
+ int Cells=StrZCellsCount(Owner);
- if (Length>ColumnWidth)
+ if (Cells>ColumnWidth)
{
CurLeftPos=LeftPos;
- if (CurLeftPos>Length-ColumnWidth)
- CurLeftPos=Length-ColumnWidth;
+ if (CurLeftPos>Cells-ColumnWidth)
+ CurLeftPos=Cells-ColumnWidth;
if (CurLeftPos>MaxLeftPos)
MaxLeftPos=CurLeftPos;
}
}
- FS<<fmt::LeftAlign()<<fmt::Width(ColumnWidth)<<fmt::Precision(ColumnWidth)<<Owner+CurLeftPos;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(ColumnWidth) << Owner+CurLeftPos;
break;
}
@@ -1259,28 +1247,28 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if (!ShowStatus && LeftPos>0)
{
- int Length=StrLength(Group);
+ int Cells=StrZCellsCount(Group);
- if (Length>ColumnWidth)
+ if (Cells>ColumnWidth)
{
CurLeftPos=LeftPos;
- if (CurLeftPos>Length-ColumnWidth)
- CurLeftPos=Length-ColumnWidth;
+ if (CurLeftPos>Cells-ColumnWidth)
+ CurLeftPos=Cells-ColumnWidth;
if (CurLeftPos>MaxLeftPos)
MaxLeftPos=CurLeftPos;
}
}
- FS<<fmt::LeftAlign()<<fmt::Width(ColumnWidth)<<fmt::Precision(ColumnWidth)<<Group+CurLeftPos;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(ColumnWidth) << Group + CurLeftPos;
break;
}
case NUMLINK_COLUMN:
{
- FS<<fmt::Width(ColumnWidth)<<fmt::Precision(ColumnWidth)<<ListData[ListPos]->NumberOfLinks;
+ FS << fmt::Cells() << fmt::Size(ColumnWidth) << ListData[ListPos]->NumberOfLinks;
break;
}
}
@@ -1288,7 +1276,7 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
}
else
{
- FS<<fmt::Width(ColumnWidth)<<L"";
+ FS << fmt::Cells() << fmt::Expand(ColumnWidth) << L"";
}
if (ShowDivider==FALSE)
@@ -1332,7 +1320,7 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
if ((!ShowStatus || StatusLine) && WhereX()<X2)
{
SetColor(COL_PANELTEXT);
- FS<<fmt::Width(X2-WhereX())<<L"";
+ FS << fmt::Cells() << fmt::Expand(X2 - WhereX()) << L"";
}
}
@@ -1341,7 +1329,7 @@ void FileList::ShowList(int ShowStatus,int StartColumn)
SetScreen(X1+1,Y2-1,X2-1,Y2-1,L' ',COL_PANELTEXT);
SetColor(COL_PANELTEXT); //???
//GotoXY(X1+1,Y2-1);
- //FS<<fmt::Width(X2-X1-1)<<L"";
+ //FS<<fmt::Expand(X2-X1-1)<<L"";
}
if (!ShowStatus)
diff --git a/far2l/src/foldtree.cpp b/far2l/src/foldtree.cpp
index 8209b42e..0c62b345 100644
--- a/far2l/src/foldtree.cpp
+++ b/far2l/src/foldtree.cpp
@@ -356,7 +356,7 @@ void FolderTree::DrawEdit()
if (WhereX()<X2)
{
SetColor(COL_PANELTEXT);
- FS<<fmt::Width(X2-WhereX())<<L"";
+ FS << fmt::Cells() << fmt::Expand(X2 - WhereX()) << L"";
}
}
diff --git a/far2l/src/headers.hpp b/far2l/src/headers.hpp
index 733c7d8c..5ff0f2e2 100644
--- a/far2l/src/headers.hpp
+++ b/far2l/src/headers.hpp
@@ -156,6 +156,7 @@ inline const T Round(const T &a, const T &b) { return a/b+(a%b*2>b?1:0); }
#include "format.hpp"
#include "global.hpp"
#include "locale.hpp"
+#include "StrCells.h"
#include <farplug-wide.h>
#include "farwinapi.hpp"
#include "cvtname.hpp"
diff --git a/far2l/src/help.cpp b/far2l/src/help.cpp
index fb93ad1d..96e5b7fe 100644
--- a/far2l/src/help.cpp
+++ b/far2l/src/help.cpp
@@ -986,7 +986,7 @@ void Help::OutString(const wchar_t *Str)
if (!Locked() && WhereX()<X2)
{
SetColor(CurColor);
- FS<<fmt::Width(X2-WhereX())<<L"";
+ FS << fmt::Cells() << fmt::Expand(X2 - WhereX()) << L"";
}
}
diff --git a/far2l/src/infolist.cpp b/far2l/src/infolist.cpp
index df9bef30..94a86f63 100644
--- a/far2l/src/infolist.cpp
+++ b/far2l/src/infolist.cpp
@@ -481,7 +481,7 @@ void InfoList::PrintText(const wchar_t *Str)
{
if (WhereY()<=Y2-1)
{
- FS<<fmt::Precision(X2-WhereX())<<Str;
+ FS << fmt::Cells() << fmt::Truncate(X2 - WhereX()) << Str;
}
}
@@ -617,7 +617,7 @@ void InfoList::ShowPluginDescription()
SetColor(COL_PANELBOX);
Text(VertcalLine);
SetColor(COL_PANELTEXT);
- FS<<fmt::Width(X2-X1-1)<<L"";
+ FS << fmt::Cells() << fmt::Expand(X2 - X1 - 1) << L"";
SetColor(COL_PANELBOX);
Text(VertcalLine);
GotoXY(X1+2,Y);
diff --git a/far2l/src/keybar.cpp b/far2l/src/keybar.cpp
index 9a0c60b6..d4fbdc6d 100644
--- a/far2l/src/keybar.cpp
+++ b/far2l/src/keybar.cpp
@@ -180,9 +180,9 @@ void KeyBar::RefreshObject(bool Render)
if (Render && WhereX()+LabelWidth<X2)
{
SetColor(COL_KEYBARNUM);
- FS<<i+1;
+ FS << i + 1;
SetColor(COL_KEYBARTEXT);
- FS<<fmt::LeftAlign()<<fmt::Width(LabelWidth)<<fmt::Precision(LabelWidth)<<Label;
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(LabelWidth) << Label;
if (i<KEY_COUNT-1)
{
@@ -199,7 +199,7 @@ void KeyBar::RefreshObject(bool Render)
if (Width>0)
{
SetColor(COL_KEYBARTEXT);
- FS<<fmt::Width(Width)<<L"";
+ FS << fmt::Cells() << fmt::Expand(Width) << L"";
}
}
diff --git a/far2l/src/locale/codepage.cpp b/far2l/src/locale/codepage.cpp
index 5a367b90..f8c5d314 100644
--- a/far2l/src/locale/codepage.cpp
+++ b/far2l/src/locale/codepage.cpp
@@ -188,7 +188,7 @@ static void FormatCodePageString(UINT CodePage, const wchar_t *CodePageName, For
{
if (CodePage!=CP_AUTODETECT)
{
- CodePageNameString<<fmt::Width(5)<<CodePage<<BoxSymbols[BS_V1]<<(!IsCodePageNameCustom||CallbackCallSource==CodePagesFill?L' ':L'*');
+ CodePageNameString<<fmt::Expand(5)<<CodePage<<BoxSymbols[BS_V1]<<(!IsCodePageNameCustom||CallbackCallSource==CodePagesFill?L' ':L'*');
}
CodePageNameString<<CodePageName;
}
diff --git a/far2l/src/locale/locale.hpp b/far2l/src/locale/locale.hpp
index 417e720f..866b5d26 100644
--- a/far2l/src/locale/locale.hpp
+++ b/far2l/src/locale/locale.hpp
@@ -40,11 +40,11 @@ extern const wchar_t WIN_EOL_fmt[];
inline int __cdecl StrLength(const wchar_t *str) { return (int) wcslen(str); }
-inline int IsSpace(wchar_t x) { return x==L' ' || x==L'\t'; }
+inline bool IsSpace(wchar_t x) { return x==L' ' || x==L'\t' || x==0x3000; }
-inline int IsEol(wchar_t x) { return x==L'\r' || x==L'\n'; }
+inline bool IsEol(wchar_t x) { return x==L'\r' || x==L'\n'; }
-inline int IsSpaceOrEos(wchar_t x) { return !x || x==L' ' || x==L'\t'; }
+inline bool IsSpaceOrEos(wchar_t x) { return !x || IsSpace(x); }
inline wchar_t __cdecl Upper(wchar_t Ch)
{
diff --git a/far2l/src/message.cpp b/far2l/src/message.cpp
index 090a5bcb..e2e273dc 100644
--- a/far2l/src/message.cpp
+++ b/far2l/src/message.cpp
@@ -144,7 +144,7 @@ static int ShowMessageSynched(
// предварительный обсчет максимального размера.
for (BtnLength=0,I=0; I<static_cast<DWORD>(Buttons); I++) //??
{
- BtnLength+=HiStrlen(Items[I+StrCount])+2+2+1; // "[ ", " ]", " "
+ BtnLength+=HiStrCellsCount(Items[I+StrCount])+2+2+1; // "[ ", " ]", " "
}
if(BtnLength)
{
diff --git a/far2l/src/mix/StrCells.cpp b/far2l/src/mix/StrCells.cpp
new file mode 100644
index 00000000..055b8f36
--- /dev/null
+++ b/far2l/src/mix/StrCells.cpp
@@ -0,0 +1,159 @@
+#include "headers.hpp"
+
+#include <utils.h>
+#include "StrCells.h"
+#include "config.hpp"
+
+size_t StrCellsCount(const wchar_t *pwz, size_t nw)
+{
+ size_t out = 0;
+ for (size_t i = 0; i < nw; ++i) {
+ if (IsCharFullWidth(pwz[i])) {
+ out+= 2;
+ } else if ((i == nw - 1 || !IsCharPrefix(pwz[i])) && (i == 0 || !IsCharSuffix(pwz[i]))) {
+ ++out;
+ }
+ }
+ return out;
+}
+
+size_t StrZCellsCount(const wchar_t *pwz)
+{
+ return StrCellsCount(pwz, wcslen(pwz));
+}
+
+size_t StrSizeOfCells(const wchar_t *pwz, size_t n, size_t &ng, bool round_up)
+{
+ size_t i = 0, g = 0;
+ for (; g < ng && i < n; ++g) {
+ for (; i < n; ++i) {
+ if (!IsCharPrefix(pwz[i])) {
+ break;
+ }
+ }
+ if (i < n) {
+ if (IsCharFullWidth(pwz[i])) {
+ ++g;
+ if (!round_up && g == ng) {
+ break;
+ }
+ }
+ ++i;
+ }
+ for (; i < n; ++i) {
+ if (!IsCharSuffix(pwz[i])) {
+ break;
+ }
+ }
+ }
+ ng = g;
+ return i;
+}
+
+size_t StrSizeOfCell(const wchar_t *pwz, size_t n)
+{
+ size_t ng = 1;
+ return StrSizeOfCells(pwz, n, ng, true);
+}
+
+static struct TruncReplacement
+{
+ const wchar_t *wz;
+ size_t len;
+} s_trunc_replacement[2] = { {L"...", 3}, {L"…", 1} };
+
+static const struct TruncReplacement &ChooseTruncReplacement()
+{
+ return s_trunc_replacement[Opt.NoGraphics ? 0 : 1];
+}
+
+void StrCellsTruncateLeft(wchar_t *pwz, size_t &n, size_t ng)
+{
+ size_t vl = StrCellsCount(pwz, n);
+ const auto &rpl = ChooseTruncReplacement();
+ if (vl <= ng || n < rpl.len) {
+ return;
+ }
+
+ for (size_t ofs = rpl.len; ofs < n; ++ofs) {
+ if (!IsCharXxxfix(pwz[ofs]) && StrCellsCount(pwz + ofs, n - ofs) + rpl.len <= ng) {
+ n-= ofs;
+ wmemmove(pwz + rpl.len, pwz + ofs, n);
+ n+= rpl.len;
+ wmemcpy(pwz, rpl.wz, rpl.len); //…
+ return;
+ }
+ }
+ wcsncpy(pwz, rpl.wz, ng);
+ n = std::min(ng, rpl.len);
+}
+
+void StrCellsTruncateRight(wchar_t *pwz, size_t &n, size_t ng)
+{
+ size_t vl = StrCellsCount(pwz, n);
+ const auto &rpl = ChooseTruncReplacement();
+ if (vl <= ng || n < rpl.len) {
+ return;
+ }
+
+ n-= rpl.len; // pre-reserve space for ...
+ do {
+ while (n > 0 && IsCharXxxfix(pwz[n - 1])) {
+ --n;
+ }
+ if (n == 0) {
+ break;
+ }
+ --n;
+ } while (StrCellsCount(pwz, n) + rpl.len > ng);
+
+ wmemcpy(&pwz[n], rpl.wz, rpl.len);
+ n+= rpl.len;
+}
+
+void StrCellsTruncateCenter(wchar_t *pwz, size_t &n, size_t ng)
+{
+ size_t vl = StrCellsCount(pwz, n);
+ const auto &rpl = ChooseTruncReplacement();
+ if (vl <= ng || n < rpl.len) {
+ return;
+ }
+
+ auto cut_start = n / 2;
+ if (cut_start > 0) {
+ --cut_start;
+ }
+ if (cut_start > 0 && rpl.len > 1) {
+ --cut_start;
+ }
+ while (cut_start > 0 && IsCharXxxfix(pwz[cut_start])) {
+ --cut_start;
+ }
+ auto cut_end = cut_start + rpl.len;
+ while (cut_end < n && IsCharXxxfix(pwz[cut_end])) {
+ ++cut_end;
+ }
+
+ while (StrCellsCount(pwz, cut_start) + StrCellsCount(pwz + cut_end, n - cut_end) + rpl.len > ng) {
+ if (cut_start > 0) {
+ --cut_start;
+ while (cut_start > 0 && IsCharXxxfix(pwz[cut_start])) {
+ --cut_start;
+ }
+ if (StrCellsCount(pwz, cut_start) + StrCellsCount(pwz + cut_end, n - cut_end) + rpl.len <= ng) {
+ break;
+ }
+ }
+ if (cut_end < n) {
+ ++cut_end;
+ while (cut_end < n && IsCharXxxfix(pwz[cut_end])) {
+ ++cut_end;
+ }
+ }
+ }
+
+ wmemmove(&pwz[cut_start + rpl.len], &pwz[cut_end], n - cut_end);
+ wmemcpy(&pwz[cut_start], rpl.wz, rpl.len);
+ n-= (cut_end - cut_start);
+ n+= rpl.len;
+}
diff --git a/far2l/src/mix/StrCells.h b/far2l/src/mix/StrCells.h
new file mode 100644
index 00000000..3840cab1
--- /dev/null
+++ b/far2l/src/mix/StrCells.h
@@ -0,0 +1,10 @@
+#pragma once
+
+size_t StrCellsCount(const wchar_t *pwz, size_t nw);
+size_t StrZCellsCount(const wchar_t *pwz);
+size_t StrSizeOfCells(const wchar_t *pwz, size_t nw, size_t &ng, bool round_up);
+size_t StrSizeOfCell(const wchar_t *pwz, size_t nw);
+
+void StrCellsTruncateLeft(wchar_t *pwz, size_t &n, size_t ng);
+void StrCellsTruncateRight(wchar_t *pwz, size_t &n, size_t ng);
+void StrCellsTruncateCenter(wchar_t *pwz, size_t &n, size_t ng);
diff --git a/far2l/src/mix/format.cpp b/far2l/src/mix/format.cpp
index 8ecf8132..2a36f985 100644
--- a/far2l/src/mix/format.cpp
+++ b/far2l/src/mix/format.cpp
@@ -38,35 +38,61 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void BaseFormat::Reset()
{
- _Width=0;
- _Precision=static_cast<size_t>(-1);
- _FillChar=L' ';
- _Align=fmt::A_RIGHT;
+ _Cells = false;
+ _Skip = 0;
+ _Expand = 0;
+ _Truncate = static_cast<size_t>(-1);
+ _FillChar = L' ';
+ _Align = fmt::A_RIGHT;
}
-void BaseFormat::Put(LPCWSTR Data,size_t Length)
+void BaseFormat::Put(LPCWSTR Data, size_t Length)
{
- if (_Precision==static_cast<size_t>(-1))
- {
- _Precision=Length;
+ if (_Skip != 0) {
+ size_t SkipChars;
+ if (_Cells) {
+ size_t ng = _Skip;
+ SkipChars = StrSizeOfCells(Data, Length, ng, true);
+ } else {
+ SkipChars = _Skip;
+ }
+ if (SkipChars < Length) {
+ Data+= SkipChars;
+ Length-= SkipChars;
+ } else {
+ Data+= Length;
+ Length = 0;
+ }
}
- FARString OutStr(Data,Min(_Precision,Length));
-
- if (_Align==fmt::A_RIGHT)
+ if (_Truncate != static_cast<size_t>(-1))
{
- while (OutStr.GetLength()<_Width)
+ if (_Cells)
{
- OutStr.Insert(0,_FillChar);
+ size_t ng = _Truncate;
+ Length = StrSizeOfCells(Data, Length, ng, false);
+ }
+ else if (Length > _Truncate)
+ {
+ Length = _Truncate;
}
}
- else
+
+ FARString OutStr(Data, Length);
+
+ size_t Count = _Cells ? OutStr.CellsCount() : OutStr.GetLength();
+
+ if (_Align == fmt::A_RIGHT)
{
- while (OutStr.GetLength()<_Width)
+ for(;Count < _Expand; ++Count)
{
- OutStr.Append(_FillChar);
+ OutStr.Insert(0, _FillChar);
}
}
+ else if (_Expand > Count)
+ {
+ OutStr.Append(_FillChar, _Expand - Count);
+ }
Commit(OutStr);
Reset();
@@ -109,18 +135,42 @@ BaseFormat& BaseFormat::operator<<(FARString& String)
return *this;
}
-BaseFormat& BaseFormat::operator<<(const fmt::Width& Manipulator)
+BaseFormat& BaseFormat::operator<<(const fmt::Chars&)
+{
+ SetCells(false);
+ return *this;
+}
+
+BaseFormat& BaseFormat::operator<<(const fmt::Cells&)
{
- SetWidth(Manipulator.GetValue());
+ SetCells(true);
return *this;
}
-BaseFormat& BaseFormat::operator<<(const fmt::Precision& Manipulator)
+BaseFormat& BaseFormat::operator<<(const fmt::Skip& Manipulator)
{
- SetPrecision(Manipulator.GetValue());
+ SetSkip(Manipulator.GetValue());
return *this;
}
+BaseFormat& BaseFormat::operator<<(const fmt::Expand& Manipulator)
+{
+ SetExpand(Manipulator.GetValue());
+ return *this;
+}
+
+BaseFormat& BaseFormat::operator<<(const fmt::Truncate& Manipulator)
+{
+ SetTruncate(Manipulator.GetValue());
+ return *this;
+}
+
+BaseFormat& BaseFormat::operator<<(const fmt::Size& Manipulator)
+{
+ SetTruncate(Manipulator.GetValue());
+ SetExpand(Manipulator.GetValue());
+ return *this;
+}
BaseFormat& BaseFormat::operator<<(const fmt::FillChar& Manipulator)
{
diff --git a/far2l/src/mix/format.hpp b/far2l/src/mix/format.hpp
index e1130e19..ae56740f 100644
--- a/far2l/src/mix/format.hpp
+++ b/far2l/src/mix/format.hpp
@@ -37,19 +37,38 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace fmt
{
- class Width
+ struct Cells { }; // makes modifiers operate in screen cells but not characters
+ struct Chars { }; // makes modifiers operate in characters but not screen cells
+
+ class Skip
+ {
+ size_t Value;
+ public:
+ Skip(size_t Value=static_cast<size_t>(-1)) {this->Value=Value;}
+ size_t GetValue()const {return Value;}
+ };
+
+ class Expand
+ {
+ size_t Value;
+ public:
+ Expand(size_t Value=0) {this->Value=Value;}
+ size_t GetValue()const {return Value;}
+ };
+
+ class Truncate
{
size_t Value;
public:
- Width(size_t Value=0) {this->Value=Value;}
+ Truncate(size_t Value=static_cast<size_t>(-1)) {this->Value=Value;}
size_t GetValue()const {return Value;}
};
- class Precision
+ class Size // same as Expand + Truncate with same parameter
{
size_t Value;
public:
- Precision(size_t Value=static_cast<size_t>(-1)) {this->Value=Value;}
+ Size(size_t Value=static_cast<size_t>(-1)) {this->Value=Value;}
size_t GetValue()const {return Value;}
};
@@ -75,8 +94,10 @@ namespace fmt
class BaseFormat
{
- size_t _Width;
- size_t _Precision;
+ bool _Cells;
+ size_t _Skip;
+ size_t _Expand;
+ size_t _Truncate;
WCHAR _FillChar;
fmt::AlignType _Align;
@@ -91,10 +112,12 @@ class BaseFormat
virtual ~BaseFormat() {}
// attributes
- void SetPrecision(size_t Precision=static_cast<size_t>(-1)) {_Precision=Precision;}
- void SetWidth(size_t Width=0) {_Width=Width;}
- void SetAlign(fmt::AlignType Align=fmt::A_RIGHT) {_Align=Align;}
- void SetFillChar(WCHAR Char=L' ') {_FillChar=Char;}
+ inline void SetCells(bool Cells = false) { _Cells = Cells; }
+ inline void SetSkip(size_t Skip = 0) { _Skip = Skip; }
+ inline void SetTruncate(size_t Truncate = static_cast<size_t>(-1)) { _Truncate=Truncate; }
+ inline void SetExpand(size_t Expand = 0) { _Expand = Expand; }
+ inline void SetAlign(fmt::AlignType Align = fmt::A_RIGHT) { _Align = Align; }
+ inline void SetFillChar(WCHAR Char = L' ') { _FillChar = Char; }
// data
BaseFormat& operator<<(INT64 Value);
@@ -114,8 +137,12 @@ class BaseFormat
BaseFormat& operator<<(FARString& String);
// manipulators
- BaseFormat& operator<<(const fmt::Width& Manipulator);
- BaseFormat& operator<<(const fmt::Precision& Manipulator);
+ BaseFormat& operator<<(const fmt::Cells&);
+ BaseFormat& operator<<(const fmt::Chars&);
+ BaseFormat& operator<<(const fmt::Skip& Manipulator);
+ BaseFormat& operator<<(const fmt::Expand& Manipulator);
+ BaseFormat& operator<<(const fmt::Truncate& Manipulator);
+ BaseFormat& operator<<(const fmt::Size& Manipulator);
BaseFormat& operator<<(const fmt::LeftAlign& Manipulator);
BaseFormat& operator<<(const fmt::RightAlign& Manipulator);
BaseFormat& operator<<(const fmt::FillChar& Manipulator);
diff --git a/far2l/src/mix/panelmix.cpp b/far2l/src/mix/panelmix.cpp
index 7758a7e9..673cc30b 100644
--- a/far2l/src/mix/panelmix.cpp
+++ b/far2l/src/mix/panelmix.cpp
@@ -494,7 +494,7 @@ const FARString FormatStr_Attribute( DWORD FileAttributes, DWORD UnixMode, int W
}
if (Width > 0)
- strResult<<fmt::Width(Width)<<fmt::Precision(Width);
+ strResult<<fmt::Expand(Width)<<fmt::Truncate(Width);
strResult<<OutStr;
@@ -550,7 +550,7 @@ const FARString FormatStr_DateTime(const FILETIME *FileTime,int ColumnType,DWORD
ConvertDate(*FileTime,strDateStr,strTimeStr,ColumnWidth,Brief,TextMonth,FullYear);
- strResult<<fmt::Width(Width)<<fmt::Precision(Width);
+ strResult<<fmt::Expand(Width)<<fmt::Truncate(Width);
switch(ColumnType)
{
case DATE_COLUMN:
@@ -592,9 +592,9 @@ const FARString FormatStr_Size(int64_t FileSize, int64_t PhysicalSize, const FAR
PtrName=Msg::ListSymLink;
}
- strResult<<fmt::Width(Width)<<fmt::Precision(Width);
+ strResult<<fmt::Expand(Width)<<fmt::Truncate(Width);
if (StrLength(PtrName) <= Width-2) {
- // precombine into tmp string to avoid miseffect of fmt::Width etc (#1137)
+ // precombine into tmp string to avoid miseffect of fmt::Expand etc (#1137)
strResult<<FARString(L"<").Append(PtrName).Append(L">");
} else {
strResult<<PtrName;
diff --git a/far2l/src/mix/strmix.cpp b/far2l/src/mix/strmix.cpp
index 317f68f2..4e1434ac 100644
--- a/far2l/src/mix/strmix.cpp
+++ b/far2l/src/mix/strmix.cpp
@@ -225,20 +225,13 @@ wchar_t* WINAPI TruncStrFromEnd(wchar_t *Str,int MaxLength)
{
assert(MaxLength >= 0);
- MaxLength=Max(0, MaxLength);
+ MaxLength = Max(0, MaxLength);
- if (Str)
- {
- int Length = StrLength(Str);
-
- if (Length > MaxLength)
- {
- if (MaxLength>3)
- wmemcpy(Str+MaxLength-3, L"...", 3);
-
- Str[MaxLength]=0;
- }
- }
+ const size_t Len = StrLength(Str);
+ size_t n = Len;
+ StrCellsTruncateRight(Str, n, MaxLength);
+ assert(n <= Len);
+ Str[n] = 0;
return Str;
}
@@ -248,27 +241,13 @@ wchar_t* WINAPI TruncStr(wchar_t *Str,int MaxLength)
{
assert(MaxLength >= 0);
- MaxLength=Max(0, MaxLength);
+ MaxLength = Max(0, MaxLength);
- if (Str)
- {
- int Length=StrLength(Str);
-
- if (MaxLength<0)
- MaxLength=0;
-
- if (Length > MaxLength)
- {
- if (MaxLength>3)
- {
- wchar_t *MovePos = Str+Length-MaxLength+3;
- wmemmove(Str+3, MovePos, StrLength(MovePos)+1);
- wmemcpy(Str,L"...",3);
- }
-
- Str[MaxLength]=0;
- }
- }
+ const size_t Len = StrLength(Str);
+ size_t n = Len;
+ StrCellsTruncateLeft(Str, n, MaxLength);
+ assert(n <= Len);
+ Str[n] = 0;
return Str;
}
@@ -286,31 +265,13 @@ wchar_t* TruncStrFromCenter(wchar_t *Str, int MaxLength)
{
assert(MaxLength >= 0);
- MaxLength=Max(0, MaxLength);
-
- if (Str)
- {
- int Length = StrLength(Str);
-
- if (MaxLength < 0)
- MaxLength=0;
-
- if (Length > MaxLength)
- {
- const int DotsLen = 3;
-
- if (MaxLength > DotsLen)
- {
- int Len1 = (MaxLength - DotsLen) / 2;
- int Len2 = MaxLength - DotsLen - Len1;
- wmemcpy(Str + Len1, L"...", DotsLen);
- wmemmove(Str + Len1 + DotsLen, Str + Length - Len2, Len2);
- }
-
- Str[MaxLength] = 0;
- }
- }
+ MaxLength = Max(0, MaxLength);
+ const size_t Len = StrLength(Str);
+ size_t n = Len;
+ StrCellsTruncateCenter(Str, n, MaxLength);
+ assert(n <= Len);
+ Str[n] = 0;
return Str;
}
@@ -324,44 +285,8 @@ FARString& TruncStrFromCenter(FARString &strStr, int MaxLength)
wchar_t* WINAPI TruncPathStr(wchar_t *Str, int MaxLength)
{
- assert(MaxLength >= 0);
-
- MaxLength=Max(0, MaxLength);
-
- if (Str)
- {
- int nLength = (int)wcslen(Str);
-
- if ((MaxLength > 0) && (nLength > MaxLength) && (nLength >= 2))
- {
- wchar_t *lpStart = nullptr;
-
-/* if (*Str && (Str[1] == L':') && IsSlash(Str[2]))
- lpStart = Str+3;
- else*/
- {
- if ((Str[0] == GOOD_SLASH) && (Str[1] == GOOD_SLASH))
- {
- if ((lpStart = const_cast<wchar_t*>(FirstSlash(Str+2))) )
- {
- wchar_t *lpStart2=lpStart;
-
- if ((lpStart-Str < nLength) && ((lpStart=const_cast<wchar_t*>(FirstSlash(lpStart2+1)))))
- lpStart++;
- }
- }
- }
-
- if (!lpStart || (lpStart-Str > MaxLength-5))
- return TruncStr(Str, MaxLength);
-
- wchar_t *lpInPos = lpStart+3+(nLength-MaxLength);
- wmemmove(lpStart+3, lpInPos, (wcslen(lpInPos)+1));
- wmemcpy(lpStart, L"...", 3);
- }
- }
-
- return Str;
+ // TODO
+ return TruncStr(Str, MaxLength);
}
@@ -515,7 +440,7 @@ FARString& CenterStr(const wchar_t *Src, FARString &strDest, int Length)
{
int Space = (Length - SrcLength) / 2;
FormatString FString;
- FString << fmt::Width(Space) << L"" << strTempStr << fmt::Width(Length - Space - SrcLength) << L"";
+ FString << fmt::Expand(Space) << L"" << strTempStr << fmt::Expand(Length - Space - SrcLength) << L"";
strDest = std::move(FString.strValue());
}
@@ -524,18 +449,11 @@ FARString& CenterStr(const wchar_t *Src, FARString &strDest, int Length)
FARString FixedSizeStr(FARString str, size_t Length, bool RAlign)
{
- if (str.GetLength() > Length)
+ if (str.CellsCount() > Length)
{
- if (str.GetLength() > 2)
- {
- size_t RmLen = (str.GetLength() - Length) + 1;
- size_t RmPos = (str.GetLength() - RmLen) / 2;
- str.Replace(RmPos, RmLen, L"…", 1);
- }
- else
- str = L"…";
+ TruncStr(str, Length);
}
- else while (str.GetLength() < Length)
+ else while (str.CellsCount() < Length)
{
if (RAlign)
str.Insert(0, L" ", 1);
diff --git a/far2l/src/mix/strmix.hpp b/far2l/src/mix/strmix.hpp
index 2c84649e..3905f3ef 100644
--- a/far2l/src/mix/strmix.hpp
+++ b/far2l/src/mix/strmix.hpp
@@ -96,7 +96,7 @@ inline bool IsWordDiv(const wchar_t *WordDiv, wchar_t Chr)
{ return wcschr(WordDiv, Chr) != nullptr; }
inline bool IsWordDivSTNR(const wchar_t *WordDiv, wchar_t Chr)
- { return wcschr(WordDiv, Chr) != nullptr || wcschr(L" \t\n\r", Chr) != nullptr; }
+ { return wcschr(WordDiv, Chr) != nullptr || IsSpace(Chr) || IsEol(Chr); }
// WordDiv - набор разделителей слова в кодировке OEM
// возвращает указатель на начало слова
diff --git a/far2l/src/plug/PluginA.cpp b/far2l/src/plug/PluginA.cpp
index e43b500f..610321c3 100644
--- a/far2l/src/plug/PluginA.cpp
+++ b/far2l/src/plug/PluginA.cpp
@@ -333,6 +333,21 @@ static void WINAPI farBackgroundTaskA(const char *Info, BOOL Started)
CtrlObject->Plugins.BackroundTaskFinished(MB2Wide(Info).c_str());
}
+static size_t WINAPI farStrCellsCountA(const char *Str, size_t CharsCount)
+{
+ std::wstring ws;
+ MB2Wide(Str, CharsCount, ws);
+ return StrCellsCount(ws.c_str(), ws.size());
+}
+
+static size_t WINAPI farStrSizeOfCellsA(const char *Str, size_t CharsCount, size_t *CellsCount, BOOL RoundUp)
+{
+ std::wstring ws;
+ MB2Wide(Str, CharsCount, ws);
+ size_t cnt = StrSizeOfCells(ws.c_str(), ws.size(), *CellsCount, RoundUp != FALSE);
+ ws.resize(cnt);
+ return StrWide2MB(ws).size();
+}
static void CreatePluginStartupInfoA(PluginA *pPlugin, oldfar::PluginStartupInfo *PSI, oldfar::FarStandardFunctions *FSF)
{
@@ -384,6 +399,8 @@ static void CreatePluginStartupInfoA(PluginA *pPlugin, oldfar::PluginStartupInfo
StandardFunctions.DisplayNotification = farDisplayNotificationA;
StandardFunctions.DispatchInterThreadCalls = farDispatchInterThreadCallsA;
StandardFunctions.BackgroundTask = farBackgroundTaskA;
+ StandardFunctions.StrCellsCount = farStrCellsCountA;
+ StandardFunctions.StrSizeOfCells = farStrSizeOfCellsA;
}
if (!StartupInfo.StructSize)
diff --git a/far2l/src/plug/PluginW.cpp b/far2l/src/plug/PluginW.cpp
index cde065be..aa0fa9ca 100644
--- a/far2l/src/plug/PluginW.cpp
+++ b/far2l/src/plug/PluginW.cpp
@@ -397,6 +397,16 @@ static void WINAPI farBackgroundTaskW(const wchar_t *Info, BOOL Started)
CtrlObject->Plugins.BackroundTaskFinished(Info);
}
+static size_t WINAPI farStrCellsCount(const wchar_t *Str, size_t CharsCount)
+{
+ return StrCellsCount(Str, CharsCount);
+}
+
+static size_t WINAPI farStrSizeOfCells(const wchar_t *Str, size_t CharsCount, size_t *CellsCount, BOOL RoundUp)
+{
+ return StrSizeOfCells(Str, CharsCount, *CellsCount, RoundUp != FALSE);
+}
+
void CreatePluginStartupInfo(Plugin *pPlugin, PluginStartupInfo *PSI, FarStandardFunctions *FSF)
{
static PluginStartupInfo StartupInfo{};
@@ -459,6 +469,8 @@ void CreatePluginStartupInfo(Plugin *pPlugin, PluginStartupInfo *PSI, FarStandar
StandardFunctions.DisplayNotification = farDisplayNotificationW;
StandardFunctions.DispatchInterThreadCalls = farDispatchInterThreadCallsW;
StandardFunctions.BackgroundTask = farBackgroundTaskW;
+ StandardFunctions.StrCellsCount = farStrCellsCount;
+ StandardFunctions.StrSizeOfCells = farStrSizeOfCells;
}
if (!StartupInfo.StructSize)
diff --git a/far2l/src/plug/wrap.cpp b/far2l/src/plug/wrap.cpp
index aeee159d..e08ef7fb 100644
--- a/far2l/src/plug/wrap.cpp
+++ b/far2l/src/plug/wrap.cpp
@@ -1271,10 +1271,12 @@ void AnsiVBufToUnicode(PCHAR_INFO VBufA, PCHAR_INFO VBuf, size_t Size,bool NoCvt
}
else
{
- AnsiToUnicodeBin(&VBufA[i].Char.AsciiChar,&VBuf[i].Char.UnicodeChar,1);
+ WCHAR wc{};
+ AnsiToUnicodeBin(&VBufA[i].Char.AsciiChar,&wc,1);
+ CI_SET_WCHAR(VBuf[i], wc);
}
- VBuf[i].Attributes = VBufA[i].Attributes;
+ CI_SET_ATTR(VBuf[i], VBufA[i].Attributes);
}
}
}
@@ -4046,7 +4048,7 @@ int WINAPI FarCharTableA(int Command, char *Buffer, int BufferSize)
ErrnoSaver ErSr;
const wchar_t *codePageName = L"";//FormatCodePageName(nCP, cpiex.CodePageName, sizeof(cpiex.CodePageName)/sizeof(wchar_t));
- sTableName<<fmt::Width(5)<<nCP<<BoxSymbols[BS_V1]<<L" "<<codePageName;
+ sTableName<<fmt::Expand(5)<<nCP<<BoxSymbols[BS_V1]<<L" "<<codePageName;
sTableName.strValue().GetCharString(TableSet->TableName, sizeof(TableSet->TableName) - 1, CP_OEMCP);
wchar_t *us=AnsiToUnicodeBin((char*)TableSet->DecodeTable, sizeof(TableSet->DecodeTable), nCP);
WINPORT(CharLowerBuff)(us, sizeof(TableSet->DecodeTable));
diff --git a/far2l/src/qview.cpp b/far2l/src/qview.cpp
index f0da0442..cd51fcb1 100644
--- a/far2l/src/qview.cpp
+++ b/far2l/src/qview.cpp
@@ -113,7 +113,7 @@ void QuickView::DisplayObject()
DrawSeparator(Y2-2);
SetColor(COL_PANELTEXT);
GotoXY(X1+1,Y2-1);
- FS<<fmt::LeftAlign()<<fmt::Width(X2-X1-1)<<fmt::Precision(X2-X1-1)<<PointToName(strCurFileName);
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(X2 - X1 - 1) << PointToName(strCurFileName);
if (!strCurFileType.IsEmpty())
{
@@ -466,7 +466,7 @@ void QuickView::PrintText(const wchar_t *Str)
if (WhereY()>Y2-3 || WhereX()>X2-2)
return;
- FS<<fmt::Precision(X2-2-WhereX()+1)<<Str;
+ FS << fmt::Cells() << fmt::Truncate(X2 - 2 - WhereX() + 1) << Str;
}
diff --git a/far2l/src/treelist.cpp b/far2l/src/treelist.cpp
index ddfd1001..159021ab 100644
--- a/far2l/src/treelist.cpp
+++ b/far2l/src/treelist.cpp
@@ -320,7 +320,7 @@ void TreeList::DisplayTree(int Fast)
if (WhereX()<X2)
{
- FS<<fmt::Width(X2-WhereX())<<L"";
+ FS << fmt::Cells() << fmt::Expand(X2-WhereX()) << L"";
}
}
@@ -336,7 +336,7 @@ void TreeList::DisplayTree(int Fast)
if (TreeCount>0)
{
GotoXY(X1+1,Y2-1);
- FS<<fmt::LeftAlign()<<fmt::Width(X2-X1-1)<<fmt::Precision(X2-X1-1)<<ListData[CurFile]->strName;
+ FS << fmt::LeftAlign() << fmt::Cells() << fmt::Size(X2-X1-1) << ListData[CurFile]->strName;
}
UpdateViewPanel();
@@ -359,18 +359,18 @@ void TreeList::DisplayTreeName(const wchar_t *Name,int Pos)
if (Focus || ModalMode)
{
SetColor((Pos==WorkDir) ? COL_PANELSELECTEDCURSOR:COL_PANELCURSOR);
- FS<<L" "<<fmt::Precision(X2-WhereX()-3)<<Name<<L" ";
+ FS << L" " << fmt::Cells() << fmt::Truncate(X2 - WhereX() - 3) << Name << L" ";
}
else
{
SetColor((Pos==WorkDir) ? COL_PANELSELECTEDTEXT:COL_PANELTEXT);
- FS<<L"["<<fmt::Precision(X2-WhereX()-3)<<Name<<L"]";
+ FS << L"[" << fmt::Cells() << fmt::Truncate(X2 - WhereX() - 3) << Name << L"]";
}
}
else
{
SetColor((Pos==WorkDir) ? COL_PANELSELECTEDTEXT:COL_PANELTEXT);
- FS<<fmt::Precision(X2-WhereX()-1)<<Name;
+ FS << fmt::Cells() << fmt::Truncate(X2 - WhereX() - 1) << Name;
}
}
diff --git a/far2l/src/usermenu.cpp b/far2l/src/usermenu.cpp
index 6c8302d2..a0efea1e 100644
--- a/far2l/src/usermenu.cpp
+++ b/far2l/src/usermenu.cpp
@@ -491,7 +491,7 @@ static int FillUserMenu(VMenu& UserMenu,const wchar_t *MenuKey,int MenuPos,int *
FuncNum=PrepareHotKey(strHotKey);
int Offset=strHotKey.At(0)==L'&'?5:4;
FormatString FString;
- FString<<((!strHotKey.IsEmpty() && !FuncNum)?L"&":L"")<<fmt::LeftAlign()<<fmt::Width(Offset)<<fmt::Precision(Offset)<<strHotKey;
+ FString<<((!strHotKey.IsEmpty() && !FuncNum)?L"&":L"")<<fmt::LeftAlign()<<fmt::Size(Offset)<<strHotKey;
UserMenuItem.strName=std::move(FString.strValue());
UserMenuItem.strName+=strLabel;
diff --git a/far2l/src/viewer.cpp b/far2l/src/viewer.cpp
index 8cce5339..30180d2a 100644
--- a/far2l/src/viewer.cpp
+++ b/far2l/src/viewer.cpp
@@ -137,7 +137,7 @@ Viewer::Viewer(bool bQuickView, UINT aCodePage):
for (int i=0; i<=MAXSCRY; i++)
{
Strings[i] = new ViewerString();
- Strings[i]->lpData = new wchar_t[MAX_VIEWLINEB];
+ Strings[i]->lpData[MAX_VIEWLINEB] = 0;
}
strLastSearchStr = strGlobalSearchString;
@@ -246,7 +246,6 @@ Viewer::~Viewer()
for (int i=0; i<=MAXSCRY; i++)
{
- delete [] Strings[i]->lpData;
delete Strings[i];
}
@@ -517,7 +516,7 @@ void Viewer::ShowPage(int nMode)
SetScreen(X1,Y1,X2,Y2,L' ',COL_VIEWERTEXT);
GotoXY(X1,Y1);
SetColor(COL_WARNDIALOGTEXT);
- FS<<fmt::Precision(XX2-X1+1)<<Msg::ViewerCannotOpenFile;
+ FS << fmt::Cells() << fmt::Truncate(XX2 - X1 + 1) << Msg::ViewerCannotOpenFile;
ShowStatus();
}
@@ -684,7 +683,7 @@ void Viewer::ShowHex()
if (EndFile)
{
- FS<<fmt::Width(ObjWidth)<<L"";
+ FS << fmt::Cells() << fmt::Expand(ObjWidth) << L"";
continue;
}
@@ -861,18 +860,18 @@ void Viewer::ShowHex()
if (StrLength(OutStr)>HexLeftPos)
{
- FS<<fmt::LeftAlign()<<fmt::Width(ObjWidth)<<fmt::Precision(ObjWidth)<<OutStr+static_cast<size_t>(HexLeftPos);
+ FS << fmt::Cells() << fmt::LeftAlign() << fmt::Size(ObjWidth) << OutStr + static_cast<size_t>(HexLeftPos);
}
else
{
- FS<<fmt::Width(ObjWidth)<<L"";
+ FS << fmt::Cells() << fmt::Expand(ObjWidth) << L"";
}
if (bSelStartFound && bSelEndFound)
{
SetColor(COL_VIEWERSELECTEDTEXT);
GotoXY((int)((int64_t)X1+SelStart-HexLeftPos),Y);
- FS<<fmt::Precision(SelEnd-SelStart+1)<<OutStr+static_cast<size_t>(SelStart);
+ FS << fmt::Cells() << fmt::Truncate(SelEnd - SelStart + 1) << OutStr + static_cast<size_t>(SelStart);
// SelSize = 0;
}
}
@@ -1211,7 +1210,6 @@ int Viewer::ProcessKey(int Key)
}
return TRUE;
}
- ViewerString vString;
/* $ 22.01.2001 IS
Происходят какие-то манипуляции -> снимем выделение
@@ -1683,17 +1681,13 @@ int Viewer::ProcessKey(int Key)
case KEY_ALTPGDN: case KEY_PGDN: case KEY_NUMPAD3: case KEY_SHIFTNUMPAD3: case KEY_CTRLDOWN:
{
- vString.lpData = new(std::nothrow) wchar_t[MAX_VIEWLINEB];
-
- if (!vString.lpData)
- return TRUE;
-
+ ViewerString vString;
+ vString.lpData[MAX_VIEWLINEB] = 0;
const auto InitialFilePos = FilePos;
for (unsigned boost = 0; boost <= iBoostPg; boost+= 4)
{
if (LastPage || !ViewFile.Opened())
{
- delete[] vString.lpData;
return TRUE;
}
@@ -1705,7 +1699,6 @@ int Viewer::ProcessKey(int Key)
if (LastPage)
{
- delete[] vString.lpData;
return TRUE;
}
}
@@ -1727,7 +1720,6 @@ int Viewer::ProcessKey(int Key)
InternalKey++;
ProcessKey(KEY_CTRLPGDN);
InternalKey--;
- delete[] vString.lpData;
return TRUE;
}
@@ -1740,7 +1732,6 @@ int Viewer::ProcessKey(int Key)
}
Show();
- delete [] vString.lpData;
// LastSelPos=FilePos;
return TRUE;
}
@@ -2446,7 +2437,7 @@ void ViewerSearchMsg(const wchar_t *MsgStr,int Percent)
wmemset(Progress+(CurPos),BoxSymbols[BS_X_B0],Length-CurPos);
strProgress.ReleaseBuffer(Length);
FormatString strTmp;
- strTmp<<L" "<<fmt::Width(PercentLength)<<strPercent<<L"%";
+ strTmp<<L" "<<fmt::Expand(PercentLength)<<strPercent<<L"%";
strProgress+=strTmp;
}
diff --git a/far2l/src/viewer.hpp b/far2l/src/viewer.hpp
index 8ff30a04..9f8684f3 100644
--- a/far2l/src/viewer.hpp
+++ b/far2l/src/viewer.hpp
@@ -62,11 +62,11 @@ class KeyBar;
struct ViewerString
{
- wchar_t *lpData /*[MAX_VIEWLINEB]*/;
int64_t nFilePos;
int64_t nSelStart;
int64_t nSelEnd;
bool bSelection;
+ wchar_t lpData[MAX_VIEWLINEB + 1];
};
struct InternalViewerBookMark
diff --git a/far2l/src/vmenu.cpp b/far2l/src/vmenu.cpp
index f50dc0ee..41985cd6 100644
--- a/far2l/src/vmenu.cpp
+++ b/far2l/src/vmenu.cpp
@@ -477,9 +477,9 @@ int VMenu::AddItem(const MenuItemEx *NewItem,int PosAdd)
Item[PosAdd]->ShowPos = 0;
if (CheckFlags(VMENU_SHOWAMPERSAND))
- UpdateMaxLength((int)Item[PosAdd]->strName.GetLength());
+ UpdateMaxLength((int)Item[PosAdd]->strName.CellsCount());
else
- UpdateMaxLength(HiStrlen(Item[PosAdd]->strName));
+ UpdateMaxLength(HiStrCellsCount(Item[PosAdd]->strName));
UpdateItemFlags(PosAdd, NewItem->Flags);
@@ -1070,9 +1070,9 @@ int VMenu::ProcessKey(int Key)
for (int I=0; I < ItemCount; ++I)
{
if (CheckFlags(VMENU_SHOWAMPERSAND))
- _len=static_cast<int>(Item[I]->strName.GetLength());
+ _len=static_cast<int>(Item[I]->strName.CellsCount());
else
- _len=HiStrlen(Item[I]->strName);
+ _len=HiStrCellsCount(Item[I]->strName);
if (_len >= MaxLineWidth)
Item[I]->ShowPos = _len - MaxLineWidth;
@@ -1495,9 +1495,9 @@ bool VMenu::ShiftItemShowPos(int Pos, int Direct)
int ItemShowPos = Item[Pos]->ShowPos;
if (VMFlags.Check(VMENU_SHOWAMPERSAND))
- _len = (int)Item[Pos]->strName.GetLength();
+ _len = (int)Item[Pos]->strName.CellsCount();
else
- _len = HiStrlen(Item[Pos]->strName);
+ _len = HiStrCellsCount(Item[Pos]->strName);
if (_len < MaxLineWidth || (Direct < 0 && !ItemShowPos) || (Direct > 0 && ItemShowPos > _len))
return false;
@@ -1731,7 +1731,7 @@ void VMenu::DrawTitles()
GotoXY(X1+(X2-X1-1-WidthTitle)/2,Y1);
SetColor(Colors[VMenuColorTitle]);
- FS << L" " << fmt::Width(WidthTitle) << fmt::Precision(WidthTitle) << strDisplayTitle << L" ";
+ FS << L" " << fmt::Size(WidthTitle) << strDisplayTitle << L" ";
}
if (!strBottomTitle.IsEmpty())
@@ -1744,7 +1744,7 @@ void VMenu::DrawTitles()
GotoXY(X1+(X2-X1-1-WidthTitle)/2,Y2);
SetColor(Colors[VMenuColorTitle]);
- FS << L" " << fmt::Width(WidthTitle) << fmt::Precision(WidthTitle) << strBottomTitle << L" ";
+ FS << L" " << fmt::Size(WidthTitle) << strBottomTitle << L" ";
}
}
@@ -1763,9 +1763,9 @@ void VMenu::ShowMenu(bool IsParent)
int ItemLen;
if (CheckFlags(VMENU_SHOWAMPERSAND))
- ItemLen = static_cast<int>(Item[i]->strName.GetLength());
+ ItemLen = static_cast<int>(Item[i]->strName.CellsCount());
else
- ItemLen = HiStrlen(Item[i]->strName);
+ ItemLen = HiStrCellsCount(Item[i]->strName);
if (ItemLen > MaxItemLength)
MaxItemLength = ItemLen;
@@ -1947,7 +1947,7 @@ void VMenu::ShowMenu(bool IsParent)
ItemWidth = X2-X1-3;
GotoXY(X1+(X2-X1-1-ItemWidth)/2,Y);
- FS << L" " << fmt::LeftAlign() << fmt::Width(ItemWidth) << fmt::Precision(ItemWidth) << Item[I]->strName << L" ";
+ FS << L" " << fmt::LeftAlign() << fmt::Size(ItemWidth) << Item[I]->strName << L" ";
}
strTmpStr.ReleaseBuffer();
@@ -1990,9 +1990,9 @@ void VMenu::ShowMenu(bool IsParent)
int strMItemPtrLen;
if (CheckFlags(VMENU_SHOWAMPERSAND))
- strMItemPtrLen = static_cast<int>(strMItemPtr.GetLength());
+ strMItemPtrLen = static_cast<int>(strMItemPtr.CellsCount());
else
- strMItemPtrLen = HiStrlen(strMItemPtr);
+ strMItemPtrLen = HiStrCellsCount(strMItemPtr);
// fit menu FARString into available space
if (strMItemPtrLen > MaxLineWidth)
@@ -2048,7 +2048,7 @@ void VMenu::ShowMenu(bool IsParent)
{
int Width = X2-WhereX()+(BoxType==NO_BOX?1:0);
if (Width > 0)
- FS << fmt::Width(Width) << L"";
+ FS << fmt::Expand(Width) << L"";
}
if (Item[I]->Flags & MIF_SUBMENU)
@@ -2089,7 +2089,7 @@ void VMenu::ShowMenu(bool IsParent)
SetColor(Colors[VMenuColorText]);
// сделаем добавочку для NO_BOX
- FS << fmt::Width(((BoxType!=NO_BOX)?X2-X1-1:X2-X1)+((BoxType==NO_BOX)?1:0)) << L"";
+ FS << fmt::Expand(((BoxType!=NO_BOX)?X2-X1-1:X2-X1)+((BoxType==NO_BOX)?1:0)) << L"";
}
}
@@ -2288,7 +2288,7 @@ bool VMenu::CheckKeyHiOrAcc(DWORD Key, int Type, int Translate)
void VMenu::UpdateMaxLengthFromTitles()
{
//тайтл + 2 пробела вокруг
- UpdateMaxLength((int)Max(strTitle.GetLength(),strBottomTitle.GetLength())+2);
+ UpdateMaxLength((int)Max(strTitle.CellsCount(),strBottomTitle.CellsCount())+2);
}
void VMenu::UpdateMaxLength(int Length)
@@ -2337,7 +2337,7 @@ void VMenu::SetBottomTitle(const wchar_t *BottomTitle)
else
strBottomTitle.Clear();
- UpdateMaxLength((int)strBottomTitle.GetLength() + 2);
+ UpdateMaxLength((int)strBottomTitle.CellsCount() + 2);
}
void VMenu::SetTitle(const wchar_t *Title)
@@ -2351,7 +2351,7 @@ void VMenu::SetTitle(const wchar_t *Title)
else
strTitle.Clear();
- UpdateMaxLength((int)strTitle.GetLength() + 2);
+ UpdateMaxLength((int)strTitle.CellsCount() + 2);
if (CheckFlags(VMENU_CHANGECONSOLETITLE))
{
diff --git a/far2l/src/vt/VTFar2lExtensios.cpp b/far2l/src/vt/VTFar2lExtensios.cpp
index 199874fd..1d4c10b3 100644
--- a/far2l/src/vt/VTFar2lExtensios.cpp
+++ b/far2l/src/vt/VTFar2lExtensios.cpp
@@ -516,6 +516,15 @@ void VTFar2lExtensios::OnInterract_SetFKeyTitles(StackSerializer &stk_ser)
stk_ser.PushPOD(out);
}
+void VTFar2lExtensios::OnInterract_GetColorPalette(StackSerializer &stk_ser)
+{
+ stk_ser.Clear();
+ const uint8_t bits = WINPORT(GetConsoleColorPalette)();
+ const uint8_t reserved = 0;
+ stk_ser.PushPOD(reserved);
+ stk_ser.PushPOD(bits);
+}
+
void VTFar2lExtensios::OnInterract(StackSerializer &stk_ser)
{
const char code = stk_ser.PopChar();
@@ -562,6 +571,10 @@ void VTFar2lExtensios::OnInterract(StackSerializer &stk_ser)
OnInterract_SetFKeyTitles(stk_ser);
break;
+ case FARTTY_INTERRACT_GET_COLOR_PALETTE:
+ OnInterract_GetColorPalette(stk_ser);
+ break;
+
default:
stk_ser.Clear();
}
diff --git a/far2l/src/vt/VTFar2lExtensios.h b/far2l/src/vt/VTFar2lExtensios.h
index 707a6c8f..e46e6560 100644
--- a/far2l/src/vt/VTFar2lExtensios.h
+++ b/far2l/src/vt/VTFar2lExtensios.h
@@ -40,6 +40,7 @@ class VTFar2lExtensios
void OnInterract_ChangeCursorHeigth(StackSerializer &stk_ser);
void OnInterract_DisplayNotification(StackSerializer &stk_ser);
void OnInterract_SetFKeyTitles(StackSerializer &stk_ser);
+ void OnInterract_GetColorPalette(StackSerializer &stk_ser);
void WriteInputEvent(const StackSerializer &stk_ser);
public:
diff --git a/far2l/src/vt/vtansi.cpp b/far2l/src/vt/vtansi.cpp
index 5723fe73..380affa7 100644
--- a/far2l/src/vt/vtansi.cpp
+++ b/far2l/src/vt/vtansi.cpp
@@ -239,7 +239,7 @@ static HANDLE hConOut = NULL; // handle to CONOUT$
#define SI '\x0F' // Shift In
#define ST '\x9c'
-#define MAX_ARG 16 // max number of args in an escape sequence
+#define MAX_ARG 32 // max number of args in an escape sequence
static int state; // automata state
static char prefix; // escape sequence prefix ( '[', ']' or '(' );
static char prefix2; // secondary prefix ( '?' or '>' );
@@ -460,8 +460,7 @@ void PushBuffer( WCHAR c )
r.Right = s.X - 1;
r.Top = r.Bottom = csbi.dwCursorPosition.Y;
WINPORT(ReadConsoleOutput)( hConOut, row, s, c, &r );
- blank.Char.UnicodeChar = blank_character;
- blank.Attributes = csbi.wAttributes;
+ CI_SET_WCATTR(blank, blank_character, csbi.wAttributes);
while (*(PDWORD)&row[c.X] == *(PDWORD)&blank)
if (++c.X == s.X) {
nl = (csbi.dwCursorPosition.X == 0) ? NULL : L"\r";
@@ -651,7 +650,7 @@ static void LimitByScrollRegion(SMALL_RECT &rect)
void InterpretEscSeq( void )
{
int i;
- WORD attribut;
+ DWORD64 attribut;
CONSOLE_SCREEN_BUFFER_INFO Info;
CONSOLE_CURSOR_INFO CursInfo;
DWORD len, NumberOfCharsWritten;
@@ -748,8 +747,7 @@ void InterpretEscSeq( void )
Rect.Top = Info.dwCursorPosition.Y - Info.srWindow.Top;
Rect.Bottom = Info.dwCursorPosition.Y - 1;
Pos.X = Pos.Y = 0;
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)(hConOut, &Rect, NULL, Pos, &CharInfo);
}
WINPORT(SetConsoleWindowInfo)( hConOut, TRUE, &Info.srWindow );
@@ -802,7 +800,7 @@ void InterpretEscSeq( void )
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L
if (es_argc != 1) return;
{
- LimitByScrollRegion(Info.srWindow);//fprintf(stderr, "!!!scroll 1\n");
+ LimitByScrollRegion(Info.srWindow); //fprintf(stderr, "!!!scroll 1\n");
Rect.Left = Info.srWindow.Left = 0;
Rect.Right = Info.srWindow.Right = (Info.dwSize.X - 1);
@@ -811,8 +809,7 @@ void InterpretEscSeq( void )
Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y + es_argv[0];
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Info.srWindow, Pos, &CharInfo );
// Technically should home the cursor, but perhaps not expeclted.
}
@@ -825,15 +822,14 @@ void InterpretEscSeq( void )
Pos.X = 0;
Pos.Y = Info.srWindow.Top;
- LimitByScrollRegion(Info.srWindow);//fprintf(stderr, "!!!scroll 2\n");
+ LimitByScrollRegion(Info.srWindow); //fprintf(stderr, "!!!scroll 2\n");
Rect.Left = Info.srWindow.Left = 0;
Rect.Right = Info.srWindow.Right = (Info.dwSize.X - 1);
Rect.Top = Pos.Y + es_argv[0];
Rect.Bottom = Info.srWindow.Bottom;
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Info.srWindow, Pos, &CharInfo );
}
return;
@@ -842,7 +838,7 @@ void InterpretEscSeq( void )
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[T == ESC[1T
if (es_argc != 1) return;
/*while (es_argv[0]--)*/ {
- LimitByScrollRegion(Info.srWindow);//fprintf(stderr, "!!!scroll 3\n");
+ LimitByScrollRegion(Info.srWindow); //fprintf(stderr, "!!!scroll 3\n");
Rect.Left = Info.srWindow.Left = 0;
Rect.Right = Info.srWindow.Right = (Info.dwSize.X - 1);
@@ -852,8 +848,7 @@ void InterpretEscSeq( void )
Pos.X = 0;
Pos.Y = Rect.Top + es_argv[0];
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Info.srWindow, Pos, &CharInfo );
}
return;
@@ -863,19 +858,18 @@ void InterpretEscSeq( void )
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M
if (es_argc != 1) return;
{
- LimitByScrollRegion(Info.srWindow);//fprintf(stderr, "!!!scroll 4\n");
+ LimitByScrollRegion(Info.srWindow);
+ //fprintf(stderr, "!!!scroll 4 srWindow[%d %d %d %d] by %d\n", Info.srWindow.Left, Info.srWindow.Top, Info.srWindow.Right, Info.srWindow.Bottom, es_argv[0]);
Rect.Left = Info.srWindow.Left = 0;
Rect.Right = Info.srWindow.Right = (Info.dwSize.X - 1);
Rect.Bottom = Info.srWindow.Bottom;
- Rect.Top = Info.dwCursorPosition.Y + es_argv[0];
+ Rect.Top = Info.dwCursorPosition.Y;
Pos.X = 0;
- Pos.Y = Info.srWindow.Top = Info.dwCursorPosition.Y;
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ Pos.Y = Rect.Top - es_argv[0];
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
- Info.srWindow.Bottom-= es_argv[0];
- WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Info.srWindow, Pos, &CharInfo );
+ WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Rect, Pos, &CharInfo );
}
// Technically should home the cursor, but perhaps not expected.
return;
@@ -889,8 +883,7 @@ void InterpretEscSeq( void )
Pos.Y =
Rect.Top =
Rect.Bottom = Info.dwCursorPosition.Y;
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Info.srWindow, Pos, &CharInfo );
return;
@@ -903,8 +896,7 @@ void InterpretEscSeq( void )
Pos.Y =
Rect.Top =
Rect.Bottom = Info.dwCursorPosition.Y;
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = Info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)( hConOut, &Rect, &Info.srWindow, Pos, &CharInfo );
return;
@@ -1214,8 +1206,7 @@ static void ReverseIndex()
SMALL_RECT Rect = {info.srWindow.Left, scroll_top, info.srWindow.Right, (SHORT)(scroll_bottom - 1) };
COORD Pos = {0, (SHORT) (scroll_top + 1) };
CHAR_INFO CharInfo;
- CharInfo.Char.UnicodeChar = blank_character;
- CharInfo.Attributes = info.wAttributes;
+ CI_SET_WCATTR(CharInfo, blank_character, info.wAttributes);
WINPORT(ScrollConsoleScreenBuffer)(hConOut, &Rect, NULL, Pos, &CharInfo);
}
diff --git a/far2l/src/vt/vtlog.cpp b/far2l/src/vt/vtlog.cpp
index b2b12ca5..0dbb5539 100644
--- a/far2l/src/vt/vtlog.cpp
+++ b/far2l/src/vt/vtlog.cpp
@@ -83,7 +83,13 @@ namespace VTLog
attr_prev = attr_now;
}
- if (Chars[i].Char.UnicodeChar > 0x80) {
+ if (CI_USING_COMPOSITE_CHAR(Chars[i])) {
+ const wchar_t *pwc = WINPORT(CompositeCharLookup)(Chars[i].Char.UnicodeChar);
+ for (; pwc && *pwc; ++pwc) {
+ Wide2MB_UnescapedAppend(*pwc, out);
+ }
+
+ } else if (Chars[i].Char.UnicodeChar > 0x80) {
Wide2MB_UnescapedAppend(Chars[i].Char.UnicodeChar, out);
} else if (Chars[i].Char.UnicodeChar != 0) {
diff --git a/far2l/src/vt/vtshell.cpp b/far2l/src/vt/vtshell.cpp
index a1444d5e..9e573a5f 100644
--- a/far2l/src/vt/vtshell.cpp
+++ b/far2l/src/vt/vtshell.cpp
@@ -30,6 +30,9 @@
#include "vtshell_compose.h"
#define __USE_BSD
#include <termios.h>
+#include "palette.hpp"
+#include "AnsiEsc.hpp"
+
const char *VT_TranslateSpecialKey(const WORD key, bool ctrl, bool alt, bool shift, unsigned char keypad = 0,
WCHAR uc = 0);
@@ -387,8 +390,6 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
}
}
-
-
// Will need to ensure that HISTCONTROL prevents adding to history commands that start by space
// to avoid shell history pollution by far2l's intermediate script execution commands
std::string hc_override;
@@ -402,15 +403,37 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
fprintf(stderr, "Override HISTCONTROL='%s'\n", hc_override.c_str());
}
- //shell = "/usr/bin/zsh";
- //shell = "/bin/bash";
- //shell = "/bin/sh";
+ const BYTE col = FarColorToReal(COL_COMMANDLINEUSERSCREEN);
+ char colorfgbg[32];
+ sprintf(colorfgbg, "%u;%u",
+ AnsiEsc::ConsoleColorToAnsi(col & 0xf),
+ AnsiEsc::ConsoleColorToAnsi((col >> 4) & 0xf));
+
+ const auto color_bpp = WINPORT(GetConsoleColorPalette)();
int r = fork();
if (r != 0) {
return r;
}
+ switch (color_bpp) {
+ case 24:
+ setenv("TERM", "xterm-256color", 1);
+ setenv("COLORTERM", "truecolor", 1);
+ break;
+
+ case 8:
+ setenv("TERM", "xterm-256color", 1);
+ setenv("COLORTERM", "256color", 1);
+ break;
+
+ default:
+ setenv("TERM", "xterm", 1);
+ unsetenv("COLORTERM");
+ }
+
+ setenv("COLORFGBG", colorfgbg, 1);
+
if (!hc_override.empty()) {
setenv("HISTCONTROL", hc_override.c_str(), 1);
}
diff --git a/far2l/src/vt/vtshell_leader.cpp b/far2l/src/vt/vtshell_leader.cpp
index 51952b8d..9e9a921b 100644
--- a/far2l/src/vt/vtshell_leader.cpp
+++ b/far2l/src/vt/vtshell_leader.cpp
@@ -38,8 +38,6 @@ static void SetupSignalHandlers(bool propogation)
static int VTShell_ExecShell(const char *shell)
{
- //setenv("TERM", "xterm-256color", 1);
- setenv("TERM", "xterm", 1);
int r = (*shell == '/')
? execl(shell, shell, "-i", NULL)
: execlp(shell, shell, "-i", NULL);
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 3b12f6f3..77966432 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -30,7 +30,9 @@ set(SOURCES
src/TestPath.cpp
src/PipeIPC.cpp
src/PathParts.cpp
+ src/CharClasses.cpp
src/POpen.cpp
+ src/VT256ColorTable.cpp
)
add_library (utils ${SOURCES})
diff --git a/utils/include/VT256ColorTable.h b/utils/include/VT256ColorTable.h
new file mode 100644
index 00000000..a3533a6b
--- /dev/null
+++ b/utils/include/VT256ColorTable.h
@@ -0,0 +1,13 @@
+#pragma once
+#include <stdint.h>
+/*
+ * First 16 colors of 256-color table are mapped to base system 16-color palette.
+ * So actual table defines 240 elements.
+ */
+
+#define VT_256COLOR_TABLE_COUNT (256 - 16)
+
+extern const uint32_t g_VT256ColorTable[VT_256COLOR_TABLE_COUNT];
+
+#define COMPOSE_RGB(R, G, B) ((uint32_t(R)) | ((uint32_t(G)) << 8) | ((uint32_t(B)) << 16))
+
diff --git a/utils/include/utils.h b/utils/include/utils.h
index 4d4b3538..1e2f381f 100644
--- a/utils/include/utils.h
+++ b/utils/include/utils.h
@@ -234,22 +234,22 @@ template <class CharT>
}
template <class CharT>
- void StrTrimRight(std::basic_string<CharT> &str, const CharT *spaces = " \t")
+ void StrTrimRight(std::basic_string<CharT> &str, const char *spaces = " \t")
{
- while (!str.empty() && strchr(spaces, str[str.size() - 1]) != NULL) {
- str.resize(str.size() - 1);
+ while (!str.empty() && unsigned(str.back()) <= 0x7f && strchr(spaces, str.back()) != NULL) {
+ str.pop_back();
}
}
template <class CharT>
- void StrTrimLeft(std::basic_string<CharT> &str, const CharT *spaces = " \t")
+ void StrTrimLeft(std::basic_string<CharT> &str, const char *spaces = " \t")
{
- while (!str.empty() && strchr(spaces, str[0]) != NULL) {
+ while (!str.empty() && unsigned(str[0]) <= 0x7f && strchr(spaces, str[0]) != NULL) {
str.erase(0, 1);
}
}
template <class CharT>
- void StrTrim(std::basic_string<CharT> &str, const CharT *spaces = " \t")
+ void StrTrim(std::basic_string<CharT> &str, const char *spaces = " \t")
{
StrTrimRight(str, spaces);
StrTrimLeft(str, spaces);
@@ -335,3 +335,8 @@ bool POpen(std::string &result, const char *command);
bool POpen(std::vector<std::wstring> &result, const char *command);
#define DBGLINE fprintf(stderr, "%d %d @%s\n", getpid(), __LINE__, __FILE__)
+
+bool IsCharFullWidth(wchar_t c);
+bool IsCharPrefix(wchar_t c);
+bool IsCharSuffix(wchar_t c);
+bool IsCharXxxfix(wchar_t c);
diff --git a/utils/src/CharClasses.cpp b/utils/src/CharClasses.cpp
new file mode 100644
index 00000000..e879b68e
--- /dev/null
+++ b/utils/src/CharClasses.cpp
@@ -0,0 +1,464 @@
+// this file autogenerated by CharClasses_mk.cpp
+
+#include <wchar.h>
+
+bool IsCharFullWidth(wchar_t c)
+{
+ switch (c) {
+ case 0x1100 ... 0x115f:
+ case 0x231a: case 0x231b:
+ case 0x2329: case 0x232a:
+ case 0x23e9 ... 0x23ec:
+ case 0x23f0:
+ case 0x23f3:
+ case 0x25fd: case 0x25fe:
+ case 0x2614: case 0x2615:
+ case 0x2648 ... 0x2653:
+ case 0x267f:
+ case 0x2693:
+ case 0x26a1:
+ case 0x26aa: case 0x26ab:
+ case 0x26bd: case 0x26be:
+ case 0x26c4: case 0x26c5:
+ case 0x26ce:
+ case 0x26d4:
+ case 0x26ea:
+ case 0x26f2: case 0x26f3:
+ case 0x26f5:
+ case 0x26fa:
+ case 0x26fd:
+ case 0x2705:
+ case 0x270a: case 0x270b:
+ case 0x2728:
+ case 0x274c:
+ case 0x274e:
+ case 0x2753 ... 0x2755:
+ case 0x2757:
+ case 0x2795 ... 0x2797:
+ case 0x27b0:
+ case 0x27bf:
+ case 0x2b1b: case 0x2b1c:
+ case 0x2b50:
+ case 0x2b55:
+ case 0x2e80 ... 0x2e99:
+ case 0x2e9b ... 0x2ef3:
+ case 0x2f00 ... 0x2fd5:
+ case 0x2ff0 ... 0x2ffb:
+ case 0x3000 ... 0x303e:
+ case 0x3041 ... 0x3096:
+ case 0x3099 ... 0x30ff:
+ case 0x3105 ... 0x312f:
+ case 0x3131 ... 0x318e:
+ case 0x3190 ... 0x31e3:
+ case 0x31f0 ... 0x321e:
+ case 0x3220 ... 0x3247:
+ case 0x3250 ... 0x4dbf:
+ case 0x4e00 ... 0xa48c:
+ case 0xa490 ... 0xa4c6:
+ case 0xa960 ... 0xa97c:
+ case 0xac00 ... 0xd7a3:
+ case 0xf900 ... 0xfaff:
+ case 0xfe10 ... 0xfe19:
+ case 0xfe30 ... 0xfe52:
+ case 0xfe54 ... 0xfe66:
+ case 0xfe68 ... 0xfe6b:
+ case 0xff01 ... 0xff60:
+ case 0xffe0 ... 0xffe6:
+ case 0x16fe0 ... 0x16fe4:
+ case 0x16ff0: case 0x16ff1:
+ case 0x17000 ... 0x187f7:
+ case 0x18800 ... 0x18cd5:
+ case 0x18d00 ... 0x18d08:
+ case 0x1b000 ... 0x1b11e:
+ case 0x1b150 ... 0x1b152:
+ case 0x1b164 ... 0x1b167:
+ case 0x1b170 ... 0x1b2fb:
+ case 0x1f004:
+ case 0x1f0cf:
+ case 0x1f18e:
+ case 0x1f191 ... 0x1f19a:
+ case 0x1f200 ... 0x1f202:
+ case 0x1f210 ... 0x1f23b:
+ case 0x1f240 ... 0x1f248:
+ case 0x1f250: case 0x1f251:
+ case 0x1f260 ... 0x1f265:
+ case 0x1f300 ... 0x1f320:
+ case 0x1f32d ... 0x1f335:
+ case 0x1f337 ... 0x1f37c:
+ case 0x1f37e ... 0x1f393:
+ case 0x1f3a0 ... 0x1f3ca:
+ case 0x1f3cf ... 0x1f3d3:
+ case 0x1f3e0 ... 0x1f3f0:
+ case 0x1f3f4:
+ case 0x1f3f8 ... 0x1f43e:
+ case 0x1f440:
+ case 0x1f442 ... 0x1f4fc:
+ case 0x1f4ff ... 0x1f53d:
+ case 0x1f54b ... 0x1f54e:
+ case 0x1f550 ... 0x1f567:
+ case 0x1f57a:
+ case 0x1f595: case 0x1f596:
+ case 0x1f5a4:
+ case 0x1f5fb ... 0x1f64f:
+ case 0x1f680 ... 0x1f6c5:
+ case 0x1f6cc:
+ case 0x1f6d0 ... 0x1f6d2:
+ case 0x1f6d5 ... 0x1f6d7:
+ case 0x1f6eb: case 0x1f6ec:
+ case 0x1f6f4 ... 0x1f6fc:
+ case 0x1f7e0 ... 0x1f7eb:
+ case 0x1f90c ... 0x1f93a:
+ case 0x1f93c ... 0x1f945:
+ case 0x1f947 ... 0x1f978:
+ case 0x1f97a ... 0x1f9cb:
+ case 0x1f9cd ... 0x1f9ff:
+ case 0x1fa70 ... 0x1fa74:
+ case 0x1fa78 ... 0x1fa7a:
+ case 0x1fa80 ... 0x1fa86:
+ case 0x1fa90 ... 0x1faa8:
+ case 0x1fab0 ... 0x1fab6:
+ case 0x1fac0 ... 0x1fac2:
+ case 0x1fad0 ... 0x1fad6:
+ case 0x20000 ... 0x2fffd:
+ case 0x30000 ... 0x3fffd:
+ return true;
+ default: return false;
+ }
+}
+
+bool IsCharPrefix(wchar_t c)
+{
+ switch (c) {
+ case 0xd800 ... 0xdfff:
+ return true;
+ default: return false;
+ }
+}
+
+bool IsCharSuffix(wchar_t c)
+{
+ switch (c) {
+ case 0x300 ... 0x36f:
+ case 0x483 ... 0x487:
+ case 0x591 ... 0x5bd:
+ case 0x5bf:
+ case 0x5c1: case 0x5c2:
+ case 0x5c4: case 0x5c5:
+ case 0x5c7:
+ case 0x610 ... 0x61a:
+ case 0x620:
+ case 0x622 ... 0x65f:
+ case 0x66e ... 0x673:
+ case 0x675 ... 0x6d3:
+ case 0x6d5 ... 0x6dc:
+ case 0x6df ... 0x6e4:
+ case 0x6e7: case 0x6e8:
+ case 0x6ea ... 0x6ef:
+ case 0x6fa ... 0x6fc:
+ case 0x6ff:
+ case 0x710 ... 0x74a:
+ case 0x74d ... 0x77f:
+ case 0x7a6 ... 0x7b0:
+ case 0x7ca ... 0x7f3:
+ case 0x7fa:
+ case 0x7fd:
+ case 0x816 ... 0x819:
+ case 0x81b ... 0x823:
+ case 0x825 ... 0x827:
+ case 0x829 ... 0x82d:
+ case 0x840 ... 0x85b:
+ case 0x860:
+ case 0x862 ... 0x865:
+ case 0x867 ... 0x86a:
+ case 0x8a0 ... 0x8ac:
+ case 0x8ae ... 0x8b4:
+ case 0x8b6 ... 0x8c7:
+ case 0x8d3 ... 0x8e1:
+ case 0x8e3 ... 0x903:
+ case 0x93a ... 0x93c:
+ case 0x93e ... 0x94f:
+ case 0x951 ... 0x957:
+ case 0x962: case 0x963:
+ case 0x981 ... 0x983:
+ case 0x9bc:
+ case 0x9be ... 0x9c4:
+ case 0x9c7: case 0x9c8:
+ case 0x9cb ... 0x9cd:
+ case 0x9d7:
+ case 0x9e2: case 0x9e3:
+ case 0x9fe:
+ case 0xa01 ... 0xa03:
+ case 0xa3c:
+ case 0xa3e ... 0xa42:
+ case 0xa47: case 0xa48:
+ case 0xa4b ... 0xa4d:
+ case 0xa51:
+ case 0xa70: case 0xa71:
+ case 0xa75:
+ case 0xa81 ... 0xa83:
+ case 0xabc:
+ case 0xabe ... 0xac5:
+ case 0xac7 ... 0xac9:
+ case 0xacb ... 0xacd:
+ case 0xae2: case 0xae3:
+ case 0xafa ... 0xaff:
+ case 0xb01 ... 0xb03:
+ case 0xb3c:
+ case 0xb3e ... 0xb44:
+ case 0xb47: case 0xb48:
+ case 0xb4b ... 0xb4d:
+ case 0xb55 ... 0xb57:
+ case 0xb62: case 0xb63:
+ case 0xb82:
+ case 0xbbe ... 0xbc2:
+ case 0xbc6 ... 0xbc8:
+ case 0xbca ... 0xbcd:
+ case 0xbd7:
+ case 0xc00 ... 0xc04:
+ case 0xc3e ... 0xc44:
+ case 0xc46 ... 0xc48:
+ case 0xc4a ... 0xc4d:
+ case 0xc55: case 0xc56:
+ case 0xc62: case 0xc63:
+ case 0xc81 ... 0xc83:
+ case 0xcbc:
+ case 0xcbe ... 0xcc4:
+ case 0xcc6 ... 0xcc8:
+ case 0xcca ... 0xccd:
+ case 0xcd5: case 0xcd6:
+ case 0xce2: case 0xce3:
+ case 0xd00 ... 0xd03:
+ case 0xd3b: case 0xd3c:
+ case 0xd3e ... 0xd44:
+ case 0xd46 ... 0xd48:
+ case 0xd4a ... 0xd4d:
+ case 0xd57:
+ case 0xd62: case 0xd63:
+ case 0xd81 ... 0xd83:
+ case 0xdca:
+ case 0xdcf ... 0xdd4:
+ case 0xdd6:
+ case 0xdd8 ... 0xddf:
+ case 0xdf2: case 0xdf3:
+ case 0xe31:
+ case 0xe34 ... 0xe3a:
+ case 0xe47 ... 0xe4e:
+ case 0xeb1:
+ case 0xeb4 ... 0xebc:
+ case 0xec8 ... 0xecd:
+ case 0xf18: case 0xf19:
+ case 0xf35:
+ case 0xf37:
+ case 0xf39:
+ case 0xf3e: case 0xf3f:
+ case 0xf71 ... 0xf84:
+ case 0xf86: case 0xf87:
+ case 0xf8d ... 0xf97:
+ case 0xf99 ... 0xfbc:
+ case 0xfc6:
+ case 0x102b ... 0x103e:
+ case 0x1056 ... 0x1059:
+ case 0x105e ... 0x1060:
+ case 0x1062 ... 0x1064:
+ case 0x1067 ... 0x106d:
+ case 0x1071 ... 0x1074:
+ case 0x1082 ... 0x108d:
+ case 0x108f:
+ case 0x109a ... 0x109d:
+ case 0x135d ... 0x135f:
+ case 0x1712 ... 0x1714:
+ case 0x1732 ... 0x1734:
+ case 0x1752: case 0x1753:
+ case 0x1772: case 0x1773:
+ case 0x17b4 ... 0x17d3:
+ case 0x17dd:
+ case 0x1807:
+ case 0x180a ... 0x180d:
+ case 0x1820 ... 0x1878:
+ case 0x1885 ... 0x18aa:
+ case 0x1920 ... 0x192b:
+ case 0x1930 ... 0x193b:
+ case 0x1a17 ... 0x1a1b:
+ case 0x1a55 ... 0x1a5e:
+ case 0x1a60 ... 0x1a7c:
+ case 0x1a7f:
+ case 0x1ab0 ... 0x1b04:
+ case 0x1b34 ... 0x1b44:
+ case 0x1b6b ... 0x1b73:
+ case 0x1b80 ... 0x1b82:
+ case 0x1ba1 ... 0x1bad:
+ case 0x1be6 ... 0x1bf3:
+ case 0x1c24 ... 0x1c37:
+ case 0x1cd0 ... 0x1cd2:
+ case 0x1cd4 ... 0x1ce8:
+ case 0x1ced:
+ case 0x1cf4:
+ case 0x1cf7 ... 0x1cf9:
+ case 0x1dc0 ... 0x1dff:
+ case 0x200d:
+ case 0x20d0 ... 0x20ff:
+ case 0x2cef ... 0x2cf1:
+ case 0x2d7f:
+ case 0x2de0 ... 0x2dff:
+ case 0x302a ... 0x302f:
+ case 0x3099: case 0x309a:
+ case 0xa66f:
+ case 0xa674 ... 0xa67d:
+ case 0xa69e: case 0xa69f:
+ case 0xa6f0: case 0xa6f1:
+ case 0xa802:
+ case 0xa806:
+ case 0xa80b:
+ case 0xa823 ... 0xa827:
+ case 0xa82c:
+ case 0xa840 ... 0xa872:
+ case 0xa880: case 0xa881:
+ case 0xa8b4 ... 0xa8c5:
+ case 0xa8e0 ... 0xa8f1:
+ case 0xa8ff:
+ case 0xa926 ... 0xa92d:
+ case 0xa947 ... 0xa953:
+ case 0xa980 ... 0xa983:
+ case 0xa9b3 ... 0xa9c0:
+ case 0xa9e5:
+ case 0xaa29 ... 0xaa36:
+ case 0xaa43:
+ case 0xaa4c: case 0xaa4d:
+ case 0xaa7b ... 0xaa7d:
+ case 0xaab0:
+ case 0xaab2 ... 0xaab4:
+ case 0xaab7: case 0xaab8:
+ case 0xaabe: case 0xaabf:
+ case 0xaac1:
+ case 0xaaeb ... 0xaaef:
+ case 0xaaf5: case 0xaaf6:
+ case 0xabe3 ... 0xabea:
+ case 0xabec: case 0xabed:
+ case 0xfb1e:
+ case 0xfe00 ... 0xfe0f:
+ case 0xfe20 ... 0xfe2f:
+ case 0x101fd:
+ case 0x102e0:
+ case 0x10376 ... 0x1037a:
+ case 0x10a01 ... 0x10a03:
+ case 0x10a05: case 0x10a06:
+ case 0x10a0c ... 0x10a0f:
+ case 0x10a38 ... 0x10a3a:
+ case 0x10a3f:
+ case 0x10ac0 ... 0x10ac5:
+ case 0x10ac7:
+ case 0x10ac9: case 0x10aca:
+ case 0x10acd ... 0x10ae1:
+ case 0x10ae4 ... 0x10ae6:
+ case 0x10aeb ... 0x10aef:
+ case 0x10b80 ... 0x10b91:
+ case 0x10ba9 ... 0x10bae:
+ case 0x10d00 ... 0x10d27:
+ case 0x10eab: case 0x10eac:
+ case 0x10f30 ... 0x10f44:
+ case 0x10f46 ... 0x10f54:
+ case 0x10fb0:
+ case 0x10fb2 ... 0x10fb6:
+ case 0x10fb8 ... 0x10fbf:
+ case 0x10fc1 ... 0x10fc4:
+ case 0x10fc9 ... 0x10fcb:
+ case 0x11000 ... 0x11002:
+ case 0x11038 ... 0x11046:
+ case 0x1107f ... 0x11082:
+ case 0x110b0 ... 0x110ba:
+ case 0x11100 ... 0x11102:
+ case 0x11127 ... 0x11134:
+ case 0x11145: case 0x11146:
+ case 0x11173:
+ case 0x11180 ... 0x11182:
+ case 0x111b3 ... 0x111c0:
+ case 0x111c9 ... 0x111cc:
+ case 0x111ce: case 0x111cf:
+ case 0x1122c ... 0x11237:
+ case 0x1123e:
+ case 0x112df ... 0x112ea:
+ case 0x11300 ... 0x11303:
+ case 0x1133b: case 0x1133c:
+ case 0x1133e ... 0x11344:
+ case 0x11347: case 0x11348:
+ case 0x1134b ... 0x1134d:
+ case 0x11357:
+ case 0x11362: case 0x11363:
+ case 0x11366 ... 0x1136c:
+ case 0x11370 ... 0x11374:
+ case 0x11435 ... 0x11446:
+ case 0x1145e:
+ case 0x114b0 ... 0x114c3:
+ case 0x115af ... 0x115b5:
+ case 0x115b8 ... 0x115c0:
+ case 0x115dc: case 0x115dd:
+ case 0x11630 ... 0x11640:
+ case 0x116ab ... 0x116b7:
+ case 0x1171d ... 0x1172b:
+ case 0x1182c ... 0x1183a:
+ case 0x11930 ... 0x11935:
+ case 0x11937: case 0x11938:
+ case 0x1193b ... 0x1193e:
+ case 0x11940:
+ case 0x11942: case 0x11943:
+ case 0x119d1 ... 0x119d7:
+ case 0x119da ... 0x119e0:
+ case 0x119e4:
+ case 0x11a01 ... 0x11a0a:
+ case 0x11a33 ... 0x11a39:
+ case 0x11a3b ... 0x11a3e:
+ case 0x11a47:
+ case 0x11a51 ... 0x11a5b:
+ case 0x11a8a ... 0x11a99:
+ case 0x11c2f ... 0x11c36:
+ case 0x11c38 ... 0x11c3f:
+ case 0x11c92 ... 0x11ca7:
+ case 0x11ca9 ... 0x11cb6:
+ case 0x11d31 ... 0x11d36:
+ case 0x11d3a:
+ case 0x11d3c: case 0x11d3d:
+ case 0x11d3f ... 0x11d45:
+ case 0x11d47:
+ case 0x11d8a ... 0x11d8e:
+ case 0x11d90: case 0x11d91:
+ case 0x11d93 ... 0x11d97:
+ case 0x11ef3 ... 0x11ef6:
+ case 0x16af0 ... 0x16af4:
+ case 0x16b30 ... 0x16b36:
+ case 0x16f4f:
+ case 0x16f51 ... 0x16f87:
+ case 0x16f8f ... 0x16f92:
+ case 0x16fe4:
+ case 0x16ff0: case 0x16ff1:
+ case 0x1bc9d: case 0x1bc9e:
+ case 0x1d165 ... 0x1d169:
+ case 0x1d16d ... 0x1d172:
+ case 0x1d17b ... 0x1d182:
+ case 0x1d185 ... 0x1d18b:
+ case 0x1d1aa ... 0x1d1ad:
+ case 0x1d242 ... 0x1d244:
+ case 0x1da00 ... 0x1da36:
+ case 0x1da3b ... 0x1da6c:
+ case 0x1da75:
+ case 0x1da84:
+ case 0x1da9b ... 0x1da9f:
+ case 0x1daa1 ... 0x1daaf:
+ case 0x1e000 ... 0x1e006:
+ case 0x1e008 ... 0x1e018:
+ case 0x1e01b ... 0x1e021:
+ case 0x1e023: case 0x1e024:
+ case 0x1e026 ... 0x1e02a:
+ case 0x1e130 ... 0x1e136:
+ case 0x1e2ec ... 0x1e2ef:
+ case 0x1e8d0 ... 0x1e8d6:
+ case 0x1e900 ... 0x1e94a:
+ case 0xe0100 ... 0xe01ef:
+ return true;
+ default: return false;
+ }
+}
+
+bool IsCharXxxfix(wchar_t c)
+{
+ return IsCharPrefix(c) || IsCharSuffix(c);
+}
diff --git a/utils/src/CharClasses_mk.cpp b/utils/src/CharClasses_mk.cpp
new file mode 100644
index 00000000..3e583e48
--- /dev/null
+++ b/utils/src/CharClasses_mk.cpp
@@ -0,0 +1,79 @@
+#include "unicode/uchar.h"
+#include "unicode/utypes.h"
+#include "unicode/stringoptions.h"
+#include "stdio.h"
+
+/// Usage:
+/// g++ -O2 ./CharClasses_mk.cpp -o /tmp/CharClasses_mk -licuuc && /tmp/CharClasses_mk > CharClasses.cpp
+
+template <class FN>
+ static void WriteFunc(const char *name, FN fn)
+{
+ UChar32 c, last = 0x10ffff;
+ UChar32 start = 0;
+ printf("bool %s(wchar_t c)\n", name);
+ printf("{\n");
+ printf("\tswitch (c) {\n");
+ for (c = 1; c <= last + 1; ++c) {
+ const bool matched = (c <= last) && fn(c);
+ if (matched) {
+ if (!start) {
+ start = c;
+ }
+
+ } else if (start) {
+ if (start + 2 == c) {
+ printf("\t\tcase 0x%x: case 0x%x:\n", (unsigned int)start, (unsigned int)c - 1);
+ } else if (start + 1 < c) {
+ printf("\t\tcase 0x%x ... 0x%x:\n", (unsigned int)start, (unsigned int)c - 1);
+ } else {
+ //printf("(c == 0x%x)\n", (unsigned int)start);
+ printf("\t\tcase 0x%x:\n", (unsigned int)start);
+ }
+ start = 0;
+ }
+ }
+ printf("\t\t\treturn true;\n");
+ printf("\t\tdefault: return false;\n");
+ printf("\t}\n");
+ printf("}\n\n");
+}
+
+int main()
+{
+// printf("%u\n", u_getIntPropertyValue(0xcbe, UCHAR_GENERAL_CATEGORY));
+// return -1;
+ UChar32 c, last = 0x10ffff;
+ UChar32 unstable_start = 0;
+ bool first = true;
+ printf("// this file autogenerated by CharClasses_mk.cpp\n\n");
+ printf("#include <wchar.h>\n\n");
+
+ WriteFunc("IsCharFullWidth", [](wchar_t c)->bool {
+ const auto ea_width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
+ return ea_width == U_EA_FULLWIDTH || ea_width == U_EA_WIDE;
+ });
+
+ WriteFunc("IsCharPrefix", [](wchar_t c)->bool {
+ const auto cat = u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY);
+ return (cat == U_SURROGATE);
+ });
+
+ WriteFunc("IsCharSuffix", [](wchar_t c)->bool {
+ const auto block = u_getIntPropertyValue(c, UCHAR_BLOCK);
+ const auto jt = u_getIntPropertyValue(c, UCHAR_JOINING_TYPE);
+ const auto cat = u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY);
+ return ( (jt != U_JT_NON_JOINING && jt != U_JT_TRANSPARENT)
+ || cat == U_NON_SPACING_MARK || cat == U_COMBINING_SPACING_MARK
+ || block == UBLOCK_COMBINING_DIACRITICAL_MARKS
+ || block == UBLOCK_COMBINING_MARKS_FOR_SYMBOLS
+ || block == UBLOCK_COMBINING_HALF_MARKS
+ || block == UBLOCK_COMBINING_DIACRITICAL_MARKS_SUPPLEMENT
+ || block == UBLOCK_COMBINING_DIACRITICAL_MARKS_EXTENDED);
+ });
+
+ printf("bool IsCharXxxfix(wchar_t c)\n");
+ printf("{\n");
+ printf("\treturn IsCharPrefix(c) || IsCharSuffix(c);\n");
+ printf("}\n");
+}
diff --git a/utils/src/VT256ColorTable.cpp b/utils/src/VT256ColorTable.cpp
new file mode 100644
index 00000000..c9bcd7af
--- /dev/null
+++ b/utils/src/VT256ColorTable.cpp
@@ -0,0 +1,244 @@
+#include "VT256ColorTable.h"
+
+const uint32_t g_VT256ColorTable[VT_256COLOR_TABLE_COUNT] = {
+ COMPOSE_RGB(0, 0, 0),
+ COMPOSE_RGB(0, 0, 95),
+ COMPOSE_RGB(0, 0, 135),
+ COMPOSE_RGB(0, 0, 175),
+ COMPOSE_RGB(0, 0, 215),
+ COMPOSE_RGB(0, 0, 255),
+ COMPOSE_RGB(0, 95, 0),
+ COMPOSE_RGB(0, 95, 95),
+ COMPOSE_RGB(0, 95, 135),
+ COMPOSE_RGB(0, 95, 175),
+ COMPOSE_RGB(0, 95, 215),
+ COMPOSE_RGB(0, 95, 255),
+ COMPOSE_RGB(0, 135, 0),
+ COMPOSE_RGB(0, 135, 95),
+ COMPOSE_RGB(0, 135, 135),
+ COMPOSE_RGB(0, 135, 175),
+ COMPOSE_RGB(0, 135, 215),
+ COMPOSE_RGB(0, 135, 255),
+ COMPOSE_RGB(0, 175, 0),
+ COMPOSE_RGB(0, 175, 95),
+ COMPOSE_RGB(0, 175, 135),
+ COMPOSE_RGB(0, 175, 175),
+ COMPOSE_RGB(0, 175, 215),
+ COMPOSE_RGB(0, 175, 255),
+ COMPOSE_RGB(0, 215, 0),
+ COMPOSE_RGB(0, 215, 95),
+ COMPOSE_RGB(0, 215, 135),
+ COMPOSE_RGB(0, 215, 175),
+ COMPOSE_RGB(0, 215, 215),
+ COMPOSE_RGB(0, 215, 255),
+ COMPOSE_RGB(0, 255, 0),
+ COMPOSE_RGB(0, 255, 95),
+ COMPOSE_RGB(0, 255, 135),
+ COMPOSE_RGB(0, 255, 175),
+ COMPOSE_RGB(0, 255, 215),
+ COMPOSE_RGB(0, 255, 255),
+ COMPOSE_RGB(95, 0, 0),
+ COMPOSE_RGB(95, 0, 95),
+ COMPOSE_RGB(95, 0, 135),
+ COMPOSE_RGB(95, 0, 175),
+ COMPOSE_RGB(95, 0, 215),
+ COMPOSE_RGB(95, 0, 255),
+ COMPOSE_RGB(95, 95, 0),
+ COMPOSE_RGB(95, 95, 95),
+ COMPOSE_RGB(95, 95, 135),
+ COMPOSE_RGB(95, 95, 175),
+ COMPOSE_RGB(95, 95, 215),
+ COMPOSE_RGB(95, 95, 255),
+ COMPOSE_RGB(95, 135, 0),
+ COMPOSE_RGB(95, 135, 95),
+ COMPOSE_RGB(95, 135, 135),
+ COMPOSE_RGB(95, 135, 175),
+ COMPOSE_RGB(95, 135, 215),
+ COMPOSE_RGB(95, 135, 255),
+ COMPOSE_RGB(95, 175, 0),
+ COMPOSE_RGB(95, 175, 95),
+ COMPOSE_RGB(95, 175, 135),
+ COMPOSE_RGB(95, 175, 175),
+ COMPOSE_RGB(95, 175, 215),
+ COMPOSE_RGB(95, 175, 255),
+ COMPOSE_RGB(95, 215, 0),
+ COMPOSE_RGB(95, 215, 95),
+ COMPOSE_RGB(95, 215, 135),
+ COMPOSE_RGB(95, 215, 175),
+ COMPOSE_RGB(95, 215, 215),
+ COMPOSE_RGB(95, 215, 255),
+ COMPOSE_RGB(95, 255, 0),
+ COMPOSE_RGB(95, 255, 95),
+ COMPOSE_RGB(95, 255, 135),
+ COMPOSE_RGB(95, 255, 175),
+ COMPOSE_RGB(95, 255, 215),
+ COMPOSE_RGB(95, 255, 255),
+ COMPOSE_RGB(135, 0, 0),
+ COMPOSE_RGB(135, 0, 95),
+ COMPOSE_RGB(135, 0, 135),
+ COMPOSE_RGB(135, 0, 175),
+ COMPOSE_RGB(135, 0, 215),
+ COMPOSE_RGB(135, 0, 255),
+ COMPOSE_RGB(135, 95, 0),
+ COMPOSE_RGB(135, 95, 95),
+ COMPOSE_RGB(135, 95, 135),
+ COMPOSE_RGB(135, 95, 175),
+ COMPOSE_RGB(135, 95, 215),
+ COMPOSE_RGB(135, 95, 255),
+ COMPOSE_RGB(135, 135, 0),
+ COMPOSE_RGB(135, 135, 95),
+ COMPOSE_RGB(135, 135, 135),
+ COMPOSE_RGB(135, 135, 175),
+ COMPOSE_RGB(135, 135, 215),
+ COMPOSE_RGB(135, 135, 255),
+ COMPOSE_RGB(135, 175, 0),
+ COMPOSE_RGB(135, 175, 95),
+ COMPOSE_RGB(135, 175, 135),
+ COMPOSE_RGB(135, 175, 175),
+ COMPOSE_RGB(135, 175, 215),
+ COMPOSE_RGB(135, 175, 255),
+ COMPOSE_RGB(135, 215, 0),
+ COMPOSE_RGB(135, 215, 95),
+ COMPOSE_RGB(135, 215, 135),
+ COMPOSE_RGB(135, 215, 175),
+ COMPOSE_RGB(135, 215, 215),
+ COMPOSE_RGB(135, 215, 255),
+ COMPOSE_RGB(135, 255, 0),
+ COMPOSE_RGB(135, 255, 95),
+ COMPOSE_RGB(135, 255, 135),
+ COMPOSE_RGB(135, 255, 175),
+ COMPOSE_RGB(135, 255, 215),
+ COMPOSE_RGB(135, 255, 255),
+ COMPOSE_RGB(175, 0, 0),
+ COMPOSE_RGB(175, 0, 95),
+ COMPOSE_RGB(175, 0, 135),
+ COMPOSE_RGB(175, 0, 175),
+ COMPOSE_RGB(175, 0, 215),
+ COMPOSE_RGB(175, 0, 255),
+ COMPOSE_RGB(175, 95, 0),
+ COMPOSE_RGB(175, 95, 95),
+ COMPOSE_RGB(175, 95, 135),
+ COMPOSE_RGB(175, 95, 175),
+ COMPOSE_RGB(175, 95, 215),
+ COMPOSE_RGB(175, 95, 255),
+ COMPOSE_RGB(175, 135, 0),
+ COMPOSE_RGB(175, 135, 95),
+ COMPOSE_RGB(175, 135, 135),
+ COMPOSE_RGB(175, 135, 175),
+ COMPOSE_RGB(175, 135, 215),
+ COMPOSE_RGB(175, 135, 255),
+ COMPOSE_RGB(175, 175, 0),
+ COMPOSE_RGB(175, 175, 95),
+ COMPOSE_RGB(175, 175, 135),
+ COMPOSE_RGB(175, 175, 175),
+ COMPOSE_RGB(175, 175, 215),
+ COMPOSE_RGB(175, 175, 255),
+ COMPOSE_RGB(175, 215, 0),
+ COMPOSE_RGB(175, 215, 95),
+ COMPOSE_RGB(175, 215, 135),
+ COMPOSE_RGB(175, 215, 175),
+ COMPOSE_RGB(175, 215, 215),
+ COMPOSE_RGB(175, 215, 255),
+ COMPOSE_RGB(175, 255, 0),
+ COMPOSE_RGB(175, 255, 95),
+ COMPOSE_RGB(175, 255, 135),
+ COMPOSE_RGB(175, 255, 175),
+ COMPOSE_RGB(175, 255, 215),
+ COMPOSE_RGB(175, 255, 255),
+ COMPOSE_RGB(215, 0, 0),
+ COMPOSE_RGB(215, 0, 95),
+ COMPOSE_RGB(215, 0, 135),
+ COMPOSE_RGB(215, 0, 175),
+ COMPOSE_RGB(215, 0, 215),
+ COMPOSE_RGB(215, 0, 255),
+ COMPOSE_RGB(215, 95, 0),
+ COMPOSE_RGB(215, 95, 95),
+ COMPOSE_RGB(215, 95, 135),
+ COMPOSE_RGB(215, 95, 175),
+ COMPOSE_RGB(215, 95, 215),
+ COMPOSE_RGB(215, 95, 255),
+ COMPOSE_RGB(215, 135, 0),
+ COMPOSE_RGB(215, 135, 95),
+ COMPOSE_RGB(215, 135, 135),
+ COMPOSE_RGB(215, 135, 175),
+ COMPOSE_RGB(215, 135, 215),
+ COMPOSE_RGB(215, 135, 255),
+ COMPOSE_RGB(215, 175, 0),
+ COMPOSE_RGB(215, 175, 95),
+ COMPOSE_RGB(215, 175, 135),
+ COMPOSE_RGB(215, 175, 175),
+ COMPOSE_RGB(215, 175, 215),
+ COMPOSE_RGB(215, 175, 255),
+ COMPOSE_RGB(215, 215, 0),
+ COMPOSE_RGB(215, 215, 95),
+ COMPOSE_RGB(215, 215, 135),
+ COMPOSE_RGB(215, 215, 175),
+ COMPOSE_RGB(215, 215, 215),
+ COMPOSE_RGB(215, 215, 255),
+ COMPOSE_RGB(215, 255, 0),
+ COMPOSE_RGB(215, 255, 95),
+ COMPOSE_RGB(215, 255, 135),
+ COMPOSE_RGB(215, 255, 175),
+ COMPOSE_RGB(215, 255, 215),
+ COMPOSE_RGB(215, 255, 255),
+ COMPOSE_RGB(255, 0, 0),
+ COMPOSE_RGB(255, 0, 95),
+ COMPOSE_RGB(255, 0, 135),
+ COMPOSE_RGB(255, 0, 175),
+ COMPOSE_RGB(255, 0, 215),
+ COMPOSE_RGB(255, 0, 255),
+ COMPOSE_RGB(255, 95, 0),
+ COMPOSE_RGB(255, 95, 95),
+ COMPOSE_RGB(255, 95, 135),
+ COMPOSE_RGB(255, 95, 175),
+ COMPOSE_RGB(255, 95, 215),
+ COMPOSE_RGB(255, 95, 255),
+ COMPOSE_RGB(255, 135, 0),
+ COMPOSE_RGB(255, 135, 95),
+ COMPOSE_RGB(255, 135, 135),
+ COMPOSE_RGB(255, 135, 175),
+ COMPOSE_RGB(255, 135, 215),
+ COMPOSE_RGB(255, 135, 255),
+ COMPOSE_RGB(255, 175, 0),
+ COMPOSE_RGB(255, 175, 95),
+ COMPOSE_RGB(255, 175, 135),
+ COMPOSE_RGB(255, 175, 175),
+ COMPOSE_RGB(255, 175, 215),
+ COMPOSE_RGB(255, 175, 255),
+ COMPOSE_RGB(255, 215, 0),
+ COMPOSE_RGB(255, 215, 95),
+ COMPOSE_RGB(255, 215, 135),
+ COMPOSE_RGB(255, 215, 175),
+ COMPOSE_RGB(255, 215, 215),
+ COMPOSE_RGB(255, 215, 255),
+ COMPOSE_RGB(255, 255, 0),
+ COMPOSE_RGB(255, 255, 95),
+ COMPOSE_RGB(255, 255, 135),
+ COMPOSE_RGB(255, 255, 175),
+ COMPOSE_RGB(255, 255, 215),
+ COMPOSE_RGB(255, 255, 255),
+ COMPOSE_RGB(8, 8, 8),
+ COMPOSE_RGB(18, 18, 18),
+ COMPOSE_RGB(28, 28, 28),
+ COMPOSE_RGB(38, 38, 38),
+ COMPOSE_RGB(48, 48, 48),
+ COMPOSE_RGB(58, 58, 58),
+ COMPOSE_RGB(68, 68, 68),
+ COMPOSE_RGB(78, 78, 78),
+ COMPOSE_RGB(88, 88, 88),
+ COMPOSE_RGB(98, 98, 98),
+ COMPOSE_RGB(108, 108, 108),
+ COMPOSE_RGB(118, 118, 118),
+ COMPOSE_RGB(128, 128, 128),
+ COMPOSE_RGB(138, 138, 138),
+ COMPOSE_RGB(148, 148, 148),
+ COMPOSE_RGB(158, 158, 158),
+ COMPOSE_RGB(168, 168, 168),
+ COMPOSE_RGB(178, 178, 178),
+ COMPOSE_RGB(188, 188, 188),
+ COMPOSE_RGB(198, 198, 198),
+ COMPOSE_RGB(208, 208, 208),
+ COMPOSE_RGB(218, 218, 218),
+ COMPOSE_RGB(228, 228, 228),
+ COMPOSE_RGB(238, 238, 238)
+};