Fashioned Turbo Imaginative and prescient 2.0

74
Fashioned Turbo Imaginative and prescient 2.0

A recent port of Turbo Imaginative and prescient 2.0, the classical framework for textual mumble-primarily based fully user interfaces. Now cross-platform and with Unicode toughen.

tvedit on Konsole

I began this as a private mission at the very close of 2018. By Would possibly perchance perchance moreover merely 2020 I notion about it became very shut to feature parity with the contemporary, and determined to derive it originate.

The distinctive targets of this mission possess been:

  • Making Turbo Imaginative and prescient work on Linux by altering the legacy codebase as petite as conceivable.
  • Maintaining it helpful on DOS/Windows.
  • Being as like minded as conceivable at the provision code level with oldschool Turbo Imaginative and prescient applications. This led me to implement a number of of the Borland C++ RTL capabilities, as explained beneath.

At one level I notion about I had executed passable, and that any makes an try at revamping the library and overcoming its contemporary obstacles would require both extending the API or breaking backward compatibility, and that a significant rewrite could perchance be in all likelihood important.

On the different hand, between July and August 2020 I discovered how to mix fats-fledged Unicode toughen into the present arquitecture, wrote the Turbo textual mumble editor and likewise made the original capabilities readily accessible on Windows. So I’m confident that Turbo Imaginative and prescient can now meet a number of the expectations of up-to-the-minute customers and programmers.

The distinctive space of this mission is https://github.com/magiblot/tvision.

What’s Turbo Imaginative and prescient upright for?

Loads has changed since Borland created Turbo Imaginative and prescient within the early 90’s. Many GUI instruments at the present time separate appearance specification from behaviour specification, employ safer or dynamic languages which extinguish no longer segfault on error, and toughen both parallel or asynchronous programming, or each and each.

Turbo Imaginative and prescient would no longer excel at any of those, but it indubitably overcomes a number of the components programmers restful face at the present time when writing terminal applications:

  1. Overlook about terminal capabilities and speak terminal I/O. When writing a Turbo Imaginative and prescient application, all it be crucial to care about is what you are looking out to possess your application to behave and ogle like—there’s never in any respect times any wish to add workarounds to your code. Turbo Imaginative and prescient tries its finest to manufacture the an identical results on all environments. As an illustration: in notify to derive a consuming background color on the Linux console, the blink attribute has to be place of abode. Turbo Imaginative and prescient does this for you.

  2. Reuse what has already been executed. Turbo Imaginative and prescient presents many widget classes (on occasion called views), along side resizable, overlapping windows, pull-down menus, dialog containers, buttons, scroll bars, enter containers, test containers and radio buttons. You would also employ and lengthen these; but even within the occasion you grab setting up your appreciate, Turbo Imaginative and prescient already handles match dispatching, exclaim of fullwidth Unicode characters, and so forth.: you extinguish no longer wish to extinguish time rewriting any of that.

  3. Can you concentrate on writing a textual mumble-primarily based fully interface that works each and each on Linux and Windows (and thus is cross-platform) out-of-the-box, and not using a #ifdefs? Turbo Imaginative and prescient makes this conceivable. First: Turbo Imaginative and prescient retains on the usage of char arrays as a replace of relying on the implementation-defined and platform-dependent wchar_t or TCHAR. Second: which skill of UTF-8 toughen in setlocale in latest variations of Microsoft’s RTL, code like the following will work as intended:

    std::ifstream f("コンピュータ.txt"); // On Windows, the RTL converts this to the device encoding on-the-flit.

How extinguish I employ Turbo Imaginative and prescient?

You would also initiating with the Turbo Imaginative and prescient For C++ Particular person’s Data, and ogle at the sample applications hi there, tvdemo and tvedit. Even as you set up the basics,
I counsel you’re taking a ogle at the Turbo Imaginative and prescient 2.0 Programming Data, which is, personally, more intuitive and more uncomplicated to maintain, despite the usage of Pascal. By then you undoubtedly will seemingly be drawn to the palette example, which contains a detailed description of how palettes are outmoded.

Form no longer put out of your mind to have a study the capabilities and API adjustments sections as properly.

Releases and downloads

This mission has no trusty releases for the time being. Whenever you occur to are a developer, try to persist with the most modern commit and document any components you be conscious whereas upgrading.

Whenever you occur to correct are looking out to test the demo applications:

  • Unix systems: you can wish to invent Turbo Imaginative and prescient yourself. You would also put collectively the invent instructions beneath.
  • Windows: you furthermore mght can stand up-to-date binaries within the Actions portion. Click on on the first successful workflow (with a green tick) within the checklist. On the bottom of the workflow web page, as lengthy as you furthermore mght can possess logged in to GitHub, you can discover an Artifacts portion with the following files:
    • examples-dos32.zip: 32-bit executables constructed with Borland C++. No Unicode toughen.
    • examples-x86.zip: 32-bit executables constructed with MSVC. Windows Vista or later required.
    • examples-x64.zip: 64-bit executables constructed with MSVC. x64 Windows Vista or later required.

Net environment

Linux

Turbo Imaginative and prescient could even be constructed as an static library with CMake and GCC/Clang.

cmake . -B ./invent -DCMAKE_BUILD_TYPE=Release && # Would possibly perchance perchance perchance also be 'Debug', 'MinSizeRel' or 'RelWithDebInfo'.
cmake --invent ./invent # or `cd ./invent; derive`

CMake variations older than 3.13 can also no longer toughen the -B possibility. You would also strive the following as a replace:

mkdir -p invent; cd invent
cmake .. -DCMAKE_BUILD_TYPE=Release &&
cmake --invent .

The above produces the following files:

  • libtvision.a, which is the Turbo Imaginative and prescient library.
  • The demo applications hi there, tvdemo, tvedit, tvdir, which possess been bundled with the contemporary Turbo Imaginative and prescient (despite the indisputable truth that a number of of them possess a number of enhancements).
  • The demo applications mmenu and palette from Borland’s Technical Reinforce.
  • tvhc, the Turbo Imaginative and prescient Wait on Compiler.

The library and executables could even be discovered in ./invent.

The invent requirements are:

  • A compiler supporting C++14.
  • libncursesw (voice the ‘w’).
  • libgpm (for mouse toughen on the Linux console) (elective).

In case your distribution presents separate devel programs (e.g. libncurses-dev, libgpm-dev in Debian-primarily based fully distros), install these too.

The minimal repeat line required to invent a Turbo Imaginative and prescient application (e.g. hi there.cpp with GCC) from this mission’s root is:

g++ -std=c++14 -o hi there hi there.cpp ./invent/libtvision.a -Iinclude -lncursesw -lgpm

You would also moreover want:

  • -Iinclude/tvision if your application uses Turbo Imaginative and prescient 1.x comprises (#encompass as a replace of #encompass ).

  • -Iinclude/tvision/compat if your application comprises Borland headers (dir.h, iostream.h, and so forth.).

  • On Gentoo (and perchance others): -ltinfow if each and each libtinfo.so and libtinfow.so are readily accessible to your device. In every other case, you furthermore mght can derive a segmentation fault when running Turbo Imaginative and prescient applications (#11). Portray that tinfo is bundled with ncurses.

-lgpm is most appealing important if Turbo Imaginative and prescient became constructed with libgpm toughen.

The backward-compatibility headers in encompass/tvision/compat emulate the Borland C++ RTL. Turbo Imaginative and prescient’s offer code restful is relying on them, and they also’ll also very properly be helpful if porting oldschool applications. This also skill that along side tvision/tv.h will elevate a number of std names to the worldwide namespace.

Windows (MSVC)

The invent direction of with MSVC is rather of more complex, as there are more alternate suggestions to utilize from. Portray that you just will need completely different invent directories for a lot of aim architectures. Shall we whisper, to generate optimized binaries:

cmake . -B ./invent && # Add '-A x64' (64-bit) or '-A Snatch32' (32-bit) to override the default platform.
cmake --invent ./invent --config Release # Would possibly perchance perchance perchance also be 'Debug', 'MinSizeRel' or 'RelWithDebInfo'.

Within the example above, tvision.lib and the example applications will seemingly be positioned at ./invent/Release.

Whenever you occur to are looking out to hyperlink Turbo Imaginative and prescient statically against Microsofts’s bustle-time library (/MT as a replace of /MD), allow the TV_USE_STATIC_RTL possibility (-DTV_USE_STATIC_RTL=ON when calling cmake).

Whenever you occur to are looking out to hyperlink an application against Turbo Imaginative and prescient, voice that MSVC will no longer will mean you furthermore mght can mix /MT with /MD or debug with non-debug binaries. All parts wish to be linked against the RTL within the an identical intention.

Whenever you occur to accomplish your appreciate Turbo Imaginative and prescient application make certain that to permit the following compiler flags, or else it’s essential perchance perchance derive compilation errors when along side :

/permissive-
/Zc:__cplusplus

Whenever you occur to employ Turbo Imaginative and prescient as a CMake submodule, these flags will seemingly be enabled robotically.

Portray: Turbo Imaginative and prescient uses setlocale to position of abode the RTL capabilities in UTF-8 mode. This will no longer work within the occasion you employ an oldschool model of the RTL.

With the RTL statically linked in, and if UTF-8 is supported in setlocale, Turbo Imaginative and prescient applications are transportable and work by default on Windows Vista and later.

Windows (MinGW)

Once your MinGW environment is wisely place of abode up, invent is executed in a an identical technique to Linux:

cmake . -B ./invent -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release &&
cmake --invent ./invent

Within the example above, libtvision.a and all examples are in ./invent if TV_BUILD_EXAMPLES possibility is ON (the default).

Whenever you occur to are looking out to hyperlink an application against Turbo Imaginative and prescient, merely add -L./invent/lib -ltvision to your linker and -I./encompass to your compiler

Windows/DOS (Borland C++)

Turbo Imaginative and prescient can restful be constructed both as a DOS or Windows library with Borland C++. Obviously, there’s never in any respect times any Unicode toughen right here.

I’m able to ascertain the invent direction of works with:

  • Borland C++ 4.52 with the Borland PowerPack for DOS.
  • Turbo Assembler 4.0.

You would also face completely different problems relying to your invent environment. Shall we whisper, Turbo Assembler desires a patch to work beneath Windows 95. On Windows XP the total lot appears to be like to work gorgeous. On Windows 10, MAKE can also emit the error Lethal: Clarify arguments too lengthy, which is willing to be mounted by upgrading MAKE to the one bundled with Borland C++ 5.x.

Sure, this works on 64-bit Windows 10. What’s going to no longer work is the Borland C++ installer, which is a 16-bit application. You can wish to bustle it on but every other environment or strive your honest correct fortune with winevdm.

A Borland Makefile could even be discovered within the mission directory. Net could even be executed by doing:

cd mission
derive.exe options>

Where could even be:

  • -DDOS32 for 32-bit DPMI applications (which restful work on 64-bit Windows).
  • -DWIN32 for 32-bit native Snatch32 applications (no longer conceivable for TVDEMO, which depends on farcoreleft() and completely different antiquities).
  • -DDEBUG to invent debug variations of the applying and the library.
  • -DTVDEBUG to hyperlink the applications with the debug model of the library.
  • -DOVERLAY, -DALIGNMENT={2,4}, -DEXCEPTION, -DNO_STREAMABLE, -DNOTASM for things I if fact be told possess nave beneath no circumstances outmoded but seemed within the contemporary makefiles.

This also can compile the library into a LIB directory subsequent to mission, and can also restful compile executables for the demo applications in their respective examples/* directories.

I’m sorry, the root makefile assumes it’s executed from the mission directory. You would also restful bustle the contemporary makefiles straight (in offer/tvision and examples/*) within the occasion you are looking out to hope to employ completely different settings.

Turbo Imaginative and prescient as a CMake dependency (no longer Borland C++)

Whenever you occur to to resolve the CMake invent device for your application, there are two main strategies to hyperlink against Turbo Imaginative and prescient:

  • Installing Turbo Imaginative and prescient and importing it with find_package. Set up is relying on the generator form:

    • First, resolve an install prefix. The default one will work out-of-the-box, but on the general requires admin privileges. On Unix systems, you furthermore mght can employ $HOME/.local as a replace. On Windows, you furthermore mght can employ any custom path you are looking out to possess but you can wish to add it to the CMAKE_PREFIX_PATH environment variable when constructing your application.

    • For mono-config mills (Unix Makefiles, Ninja…), you most appealing wish to invent and install once:

      cmake . -B ./invent # '-DCMAKE_INSTALL_PREFIX=...' to override the install prefix.
      cmake --invent ./invent
      cmake --install ./invent
    • For multi-config mills (Visual Studio, Ninja Multi-Config…) you furthermore mght can restful invent and install all configurations:

      cmake . -B ./invent # '-DCMAKE_INSTALL_PREFIX=...' to override the install prefix.
      cmake --invent ./invent --config Release
      cmake --invent ./invent --config Debug --aim tvision
      cmake --invent ./invent --config RelWithDebInfo --aim tvision
      cmake --invent ./invent --config MinSizeRel --aim tvision
      cmake --install ./invent --config Release
      cmake --install ./invent --config Debug --component library
      cmake --install ./invent --config RelWithDebInfo --component library
      cmake --install ./invent --config MinSizeRel --component library

    Then, to your application’s CMakeLists.txt, you furthermore mght can import it like this:

    find_package(tvision CONFIG)
    target_link_libraries(my_application tvision::tvision)
  • Salvage Turbo Imaginative and prescient in a submodule to your repository and import it with add_subdirectory:

    add_subdirectory(tvision) # Assuming Turbo Imaginative and prescient is within the 'tvision' directory.
    target_link_libraries(my_application tvision)

In both case, will seemingly be readily accessible to your application’s encompass path all through compilation, and your application will seemingly be linked against the important libraries (Ncurses, GPM…) robotically.

Parts

Fashioned platforms (no longer Borland C++)

  • UTF-8 toughen. You would also strive it out within the tvedit application.
  • 24-bit color toughen (up from the contemporary 16 colors).
  • ‘Initiate File’ dialogs accepts each and each Unix and Windows-vogue file paths and could perchance derive bigger ~/ into $HOME.
  • Redirection of stdin/stdout/stderr would no longer interfere with terminal I/O.
  • Compatibility with 32-bit abet files.

There are a number of environment variables that have an effect on the behaviour of all Turbo Imaginative and prescient applications:

  • TVISION_MAX_FPS: most refresh rate, default 60. This also can abet retain smoothness in terminal emulators with unefficient facing of box-drawing characters. Special values for this possibility are 0, to disable refresh rate limiting, and -1, to in actuality scheme to the terminal in every name to THardwareInfo::screenWrite (helpful when debugging).

  • TVISION_CODEPAGE: the character place of abode outmoded internally by Turbo Imaginative and prescient to translate prolonged ASCII into Unicode. Legit values are now 437 and 850, with 437 being the default, despite the indisputable truth that along side more takes very petite effort.

Unix

  • Ncurses-primarily based fully terminal toughen.
  • Intensive mouse and keyboard toughen:
    • Reinforce for X10 and SGR mouse encodings.
    • Reinforce for Xterm’s modifyOtherKeys.
    • Reinforce for Paul Evans’ fixterms and Kitty’s keyboard protocol.
    • Reinforce for key modifiers (by the usage of TIOCLINUX) and mouse (by the usage of GPM) within the Linux console.
  • Customized ticket handler that restores the terminal explain earlier than this draw crashes.
  • When stderr is a tty, messages written to it are redirected to a buffer to shut them from messing up the exclaim and are at final printed to the console when the applying shuts down or is suspended.

The following environment variables are also taken into myth:

  • TERM: Ncurses uses it to search out out terminal capabilities. It is miles place of abode robotically by the terminal emulator.

  • COLORTERM: when place of abode to truecolor or 24bit, Turbo Imaginative and prescient will cast off the terminal emulator helps 24-bit color. It is miles place of abode robotically by terminal emulators that toughen it.

  • TVISION_ESCDELAY: the number of milliseconds to wait after receiving an ESC key press, default 10. If but every other secret’s pressed all through this lengthen, it could perchance perchance be interpreted as an Alt+Key mixture. The employ of the next rate is helpful when the terminal would no longer toughen the Alt key.

  • TVISION_USE_STDIO: when no longer empty, terminal I/O is carried out through stdin/stdout, in voice that it could perchance perchance be redirected from the shell. By default, Turbo Imaginative and prescient performs terminal I/O through /dev/tty, permitting the user to redirect stdin, stdout and stderr for their desires, without affecting the applying’s balance.

    As an illustration, the following will leave out.txt empty:

    Whereas the following will dump your total destroy out sequences and textual mumble printed by the applying into out.txt:

    TVISION_USE_STDIO=1 tvdemo | tee out.txt
  • TVISION_DISPLAY: approach for drawing to display veil. Legit values are ansi and ncurses, with ansi being the default. The Ncurses library is outmoded in both case, with the variation that ncurses uses Ncurses’ appreciate scheme strategies and is diminutive to 16 colors, whereas ansi helps 24-bit color and avoids redundant buffering and UTF-8 to wide char conversions.

Windows

  • Easiest like minded with the Snatch32 Console API. On terminal emulators that don’t toughen this, Turbo Imaginative and prescient will robotically pop up a separate console window.
  • Applications fit the console window size as a replace of the buffer size (no scrollbars are visible) and the console buffer is restored when exiting or suspending Turbo Imaginative and prescient.

The following are no longer readily accessible when compiling with Borland C++:

  • The console’s codepage is place of abode to UTF-8 on startup and restored on exit.
  • Microsoft’s C runtime capabilities are place of abode robotically to UTF-8 mode, so you as a developer don’t wish to employ the wchar_t variants.
  • If the console crashes, a brand original one is distributed robotically.

Portray: Turbo Imaginative and prescient writes UTF-8 textual mumble straight to the Windows console. If the console is place of abode in legacy mode and the bitmap font is being outmoded, Unicode characters is perchance no longer displayed properly (photograph). To retain faraway from this, Turbo Imaginative and prescient detects this scenario and tries to commerce the console font to Consolas or Lucida Console.

All platforms

The following are original capabilities no longer readily accessible in Borland’s open of Turbo Imaginative and prescient or in earlier originate offer ports (Sigala, SET):

  • Center mouse button and mouse wheel toughen.
  • Arbitrary display veil size toughen (up to 32767 rows or columns) and ravishing facing of display veil resize occasions.
  • Windows could even be resized from their bottom left nook.
  • Windows could even be dragged from empty areas with the middle mouse button.
  • Improved usability of menus: they’ll also be closed by clicking again on the guardian menu item.
  • Improved usability of scrollbars: dragging them also scrolls the web page. Clicking on an empty home of the scrollbar strikes the thumb upright beneath the cursor. They respond by default to mouse wheel occasions.
  • TInputLines no longer scroll the textual mumble exclaim on level of interest/unfocus, permitting associated textual mumble to set up visible.
  • Reinforce for LF line endings in TFileViewer (tvdemo) and TEditor (tvedit). TEditor preserves the road ending on file set up but all newly created files employ CRLF by default.
  • TEditor: context menu on upright click on.
  • TEditor: high-tail scroll with middle mouse button.
  • TEditor, TInputLine: delete total words with kbAltBack, kbCtrlBack and kbCtrlDel.
  • TEditor: the House key toggles between starting of line and starting of indented textual mumble.
  • TEditor: toughen for files bigger than 64 KiB on 32-bit or 64-bit builds.
  • tvdemo: match viewer applet helpful for match debugging.
  • tvdemo: possibility to commerce the background sample.

API adjustments

  • Show veil writes are buffered and are on the general sent to the terminal once for every iteration of the spirited match loop (figuring out also TVISION_MAX_FPS). In notify for you to update the display veil all through a busy loop, you furthermore mght can employ TScreen::flushScreen().

  • TDrawBuffer is never any longer a mounted-size array. The an identical of sizeof(TDrawBuffer)/sizeof(ushort) is the .size() approach.

  • TTextDevice is now buffered, so within the occasion you possess been the usage of otstream you furthermore mght can wish to send std::flush or std::endl through it for do_sputn to be invoked.

  • TApplication now presents dosShell(), cascade() and tile(), and handles cmDosShell, cmCascade and cmTile by default. These capabilities could even be personalized by overriding getTileRect() and writeShellMsg(). This is the an identical behaviour as within the Pascal model.

  • Mouse wheel toughen: original mouse match evMouseWheel. The wheel path is specified within the original field match.mouse.wheel, whose conceivable values are mwUp, mwDown, mwLeft or mwRight.

  • Center mouse button toughen: original mouse button flag mbMiddleButton.

  • The buttons field in evMouseUp occasions is never any longer empty. It now indicates which button became released.

  • Triple-click on toughen: original mouse match flag meTripleClick.

  • TRect strategies pass, grow, intersect and Union now return TRect& as a replace of being void so they’ll also be chained.

  • TOutlineViewer now lets within the root node to possess siblings.

  • Original characteristic ushort popupMenu(TPoint the place, TMenuItem &aMenu, TGroup *receiver=0) which spawns a TMenuPopup on the desktop. Explore offer/tvision/popupmnu.cpp.

  • Original digital approach TMenuItem& TEditor::initContextMenu(TPoint p) that determines the entries of the upright-click on context menu in TEditor.

  • fexpand can now take a 2d parameter relativeTo.

  • Original class TStringView, inspired by std::string_view.

    • Many capabilities which originally had null-terminated string parameters now receive TStringView as a replace. TStringView is like minded with std::string_view, std::string and const char * (even nullptr).
  • Original class TSpan, inspired by std::span.

  • Original classes TDrawSurface and TSurfaceView, figuring out .

  • Original approach TVMemMgr::reallocateDiscardable() which is willing to be outmoded along allocateDiscardable and freeDiscardable.

  • Original approach TView::textEvent() which lets in receiving textual mumble in an efficient manner, figuring out Clipboard interplay.

  • Unicode toughen, figuring out Unicode.

  • Ravishing Color toughen, figuring out prolonged colors.

  • Original approach static void TEvent::waitEvent(int timeoutMs) which could also block for up to timeoutMs milliseconds ready for enter occasions. If it blocks, it has the side attain of flushing display veil updates. It is miles invoked by TProgram::getEvent() with static int TProgram::appEventTimeout (default 20) as argument in voice that the match loop would no longer delight in 100% CPU.

  • Original approach static void TEvent::putNothing() which puts an evNothing match into the match queue and causes TEvent::waitEvent() no longer to block unless an evNothing is returned by TEvent::getKeyEvent(). This also can on the general trigger the main thread to wake up from TEvent::waitEvent() and to invoke TApplication::sluggish() straight. This approach is thread-trusty, so it could perchance perchance be outmoded to unblock the match loop from any completely different thread.

  • It is miles now conceivable to specify a most textual mumble width or most grapheme count in TInputLine. This is executed through a brand original parameter in TInputLine‘s constructor, ushort limitMode, which controls how the 2d constructor parameter, uint restrict, is to be treated. The ilXXXX constants define the conceivable values of limitMode:

    • ilMaxBytes (the default): the textual mumble could even be up to restrict bytes lengthy, along side the null terminator.
    • ilMaxWidth: the textual mumble could even be up to restrict columns wide.
    • ilMaxGraphemes: the textual mumble can derive up to restrict non-combining characters.

    After all, the textual mumble in a TInputLine can beneath no circumstances be more than 256 bytes lengthy, along side the null terminator.

Screenshots

It is seemingly you’ll perchance get some screenshots right here. Genuinely feel free to add your appreciate!

Contributing

If of any Turbo Imaginative and prescient applications whose offer code has no longer been misplaced and that can also possess the advantage of this, let me know.

Applications the usage of Turbo Imaginative and prescient

In case your application is constant with this mission and likewise you would love it to appear within the following checklist, correct let me know.

The Turbo Imaginative and prescient API has been prolonged to permit receiving Unicode enter and displaying Unicode textual mumble. The supported encoding is UTF-8, for a lot of causes:

  • It is miles like minded with already exclaim records styles (char *), so it would no longer require intrusive adjustments to present code.
  • It is the an identical encoding outmoded for terminal I/O, so redundant conversions are kept faraway from.
  • Conformance to the UTF-8 In every single space Manifesto, which exposes many a bunch of advantages.

Portray that after constructed with Borland C++, Turbo Imaginative and prescient would no longer toughen Unicode. On the different hand, this would no longer have an effect on the manner Turbo Imaginative and prescient applications are written, for the explanation that API extensions are designed to permit for encoding-agnostic code.

Reading Unicode enter

The oldschool technique to derive textual mumble from a key press match is as follows:

// 'ev' is a TEvent, and 'ev.what' equals 'evKeyDown'.
switch (ev.keyDown.keyCode) {
    // Key shortcuts are on the general checked first.
    // ...
    default: {
        // The character is encoded within the most modern codepage
        // (CP437 by default).
        char c=ev.keyDown.charScan.charCode;
        // ...
    }
}

Among the present Turbo Imaginative and prescient classes that contend with textual mumble enter restful depend on this methodology, which has no longer changed. Single-byte characters, when representable within the most modern codepage, proceed to be readily accessible in ev.keyDown.charScan.charCode.

Unicode toughen consists in two original fields in ev.keyDown (which is a struct KeyDownEvent):

  • char textual mumble[4], which could also derive without reference to became read from the terminal: on the general a UTF-8 sequence, but perchance any form of raw records.
  • uchar textLength, which is the number of bytes of records readily accessible in textual mumble, from 0 to 4.

Portray that the textual mumble field can also derive garbage or uninitialized records from space textLength on.

You would also moreover derive a TStringView out of a KeyDownEvent with the getText() approach.

So a Unicode character could even be retrieved from TEvent within the following intention:

switch (ev.keyDown.keyCode) {
    // ...
    default: {
        std::string_view sv=ev.keyDown.getText();
        processText(sv);
    }
}

Let’s figuring out it from but every other viewpoint. If the user styles ñ, a TEvent is generated with the following keyDown struct:

KeyDownEvent {
    union {
        .keyCode=0xA4,
        .charScan=CharScanType {
            .charCode=164 ('ñ'), // In CP437
            .scanCode=0
        }
    },
    .controlKeyState=0x200 (kbInsState),
    .textual mumble={'xC3', 'xB1'}, // In UTF-8
    .textLength=2
}

On the different hand, within the occasion that they form the following will occur:

KeyDownEvent {
    union {
        .keyCode=0x0 (kbNoKey), // '€' no longer portion of CP437
        .charScan=CharScanType {
            .charCode=0,
            .scanCode=0
        }
    },
    .controlKeyState=0x200 (kbInsState),
    .textual mumble={'xE2', 'x82', 'xAC'}, // In UTF-8
    .textLength=3
}

If a key shortcut is pressed as a replace, textual mumble is empty:

KeyDownEvent {
    union {
        .keyCode=0xB (kbCtrlK),
        .charScan=CharScanType {
            .charCode=11 (''),
            .scanCode=0
        }
    },
    .controlKeyState=0x20C (kbCtrlShift | kbInsState),
    .textual mumble={},
    .textLength=0
}

So, briefly: views designed without Unicode enter in mind will proceed to work exactly as they did earlier than, and views which could be looking out to be Unicode-conscious will don’t possess any components in being so.

Showing Unicode textual mumble

The distinctive develop of Turbo Imaginative and prescient uses 16 bits to whisper a display veil cell—8 bit for a character and eight bit for BIOS color attributes.

A brand original TScreenCell form is defined in which is in a position to preserving a diminutive number of UTF-8 codepoints as well to to prolonged attributes (plucky, underline, italic…). On the different hand, you mustn’t write textual mumble into a TScreenCell straight but derive employ of Unicode-conscious API capabilities as a replace.

Text exclaim principles

A character offered as argument to any of the Turbo Imaginative and prescient API capabilities that contend with displaying textual mumble is interpreted as follows:

  • Non-printable characters within the variety 0x00 to 0xFF are interpreted as characters within the spirited codepage. Shall we whisper, 0x7F is displayed as and 0xF0 as if the usage of CP437. As an exception, 0x00 is continually displayed as a conventional home. These characters are all one column wide.
  • Persona sequences which could be no longer legitimate UTF-8 are interpreted as sequences of characters within the most modern codepage, as within the case above.
  • Legit UTF-8 sequences with a exclaim width completely different than one are taken care of in a distinctive intention, figuring out beneath.

As an illustration, the string "╔[xFE]╗" could perchance be displayed as ╔[■]╗. This means that box-drawing characters could even be mixed with UTF-8 on the general, which is helpful for backward compatibility. Whenever you occur to depend on this behaviour, though, you furthermore mght can derive surprising results: let’s whisper, "xC4xBF" is a legitimate UTF-8 sequence and is displayed as Ŀ as a replace of ─┐.

Thought to be one of many considerations with Unicode toughen is the existence of multi-width characters and combining characters. This conflicts with Turbo Imaginative and prescient’s contemporary assumption that the display veil is a grid of cells occupied by a single character each and each. However, these cases are dealt with within the following intention:

  • Multi-width characters could even be drawn wherever on the display veil and nothing noxious happens within the occasion that they overlap partly with completely different characters.

  • Zero-width characters overlay the earlier character. As an illustration, the sequence में contains the single-width character and the combining characters and . On this case, three Unicode codepoints are fit into the an identical cell.

    The ZERO WIDTH JOINER (U+200D) is continually uncared for, as it complicates things too well-known. As an illustration, it could perchance perchance turn a string like "👩👦" (4 columns wide) into "👩‍👦" (2 columns wide). Not all terminal emulators respect the ZWJ, so, in notify to manufacture predictable results, Turbo Imaginative and prescient will print each and each "👩👦" and "👩‍👦" as 👩👦.

  • No essential graphical system defects will occur as lengthy as your terminal emulator respects character widths as measured by wcwidth.

Here is an example of such characters within the Turbo textual mumble editor:
Wide character display

Unicode-conscious API capabilities

The frequent intention of writing to the display veil is by the usage of TDrawBuffer. A few strategies possess been added and others possess changed their which implies:

void TDrawBuffer::moveChar(ushort indent, char c, TColorAttr attr, ushort count);
void TDrawBuffer::putChar(ushort indent, char c);

c is continually interpreted as a character within the spirited codepage.

ushort TDrawBuffer::moveStr(ushort indent, TStringView str, TColorAttr attr);
ushort TDrawBuffer::moveCStr(ushort indent, TStringView str, TAttrPair attrs);

str is interpreted per the principles exposed beforehand.

ushort TDrawBuffer::moveStr(ushort indent, TStringView str, TColorAttr attr, ushort width, ushort initiating up=0); // Original

str is interpreted per the principles exposed beforehand. On the different hand:

  • width specifies the most number of exclaim columns that must be read from str.
  • initiating up specifies the number of exclaim columns that must be skipped at the starting of str. This is helpful for horizontal scrolling. If initiating up is all through a multi-width character, the final positions in that character are crammed with areas.

The return values are the number of exclaim columns that possess been if fact be told crammed with textual mumble.

void TDrawBuffer::moveBuf(ushort indent, const void *offer, TColorAttr attr, ushort count);

The determine of this characteristic is misleading. Even in its contemporary implementation, offer is treated as a string. So it’s an identical to moveStr(indent, TStringView((const char*) offer, count), attr).

There are completely different helpful Unicode-conscious capabilities:

int cstrlen(TStringView s);

Returns the displayed size of s per the aforementioned principles, discarding ~ characters.

int strwidth(TStringView s); // Original

Returns the displayed size of s.

On Borland C++, these strategies cast off a single-byte encoding and all characters being one column wide. This makes it conceivable to write encoding-agnostic scheme() and handleEvent() strategies that work on each and each platforms with out a single #ifdef.

The capabilities above are implemented the usage of the capabilities from the TText namespace, but every other API extension. You can wish to employ them straight within the occasion you are looking out to hope to possess TScreenCell objects with textual mumble manually. To provide an example, beneath are a number of of the TText capabilities. You would also get all of them with total descriptions in .

size_t TText::subsequent(TStringView textual mumble);
size_t TText::prev(TStringView textual mumble, size_t index);
void TText::drawChar(TSpan cells, char c);
size_t TText::drawStr(TSpan cells, size_t indent, TStringView textual mumble, int textIndent);
bool TText::drawOne(TSpan cells, size_t &i, TStringView textual mumble, size_t &j);

For drawing TScreenCell buffers into a figuring out, the following strategies are readily accessible:

void TView::writeBuf(brief x, brief y, brief w, brief h, const TScreenCell *b); // Original
void TView::writeLine(brief x, brief y, brief w, brief h, const TScreenCell *b); // Original

Instance: Unicode textual mumble in menus and blueprint bars

It be as easy as it could perchance perchance be. Let’s alter hi there.cpp as follows:

TMenuBar *THelloApp::initMenuBar( TRect r )
{
    r.b.y=r.a.y+1;
    return original TMenuBar( r,
      *original TSubMenu( "~Ñ~ello", kbAltH ) +
        *original TMenuItem( "階~毎~料入報最...", GreetThemCmd, kbAltG ) +
        *original TMenuItem( "五劫~の~擦り切れ", cmYes, kbNoKey, hcNoContext ) +
        *original TMenuItem( "העברית ~א~ינטרנט", cmNo, kbNoKey, hcNoContext ) +
         newLine() +
        *original TMenuItem( "E~x~it", cmQuit, cmQuit, hcNoContext, "Alt-X" )
        );
}

TStatusLine *THelloApp::initStatusLine( TRect r )
{
    r.a.y=r.b.y-1;
    return original TStatusLine( r,
        *original TStatusDef( 0, 0xFFFF ) +
            *original TStatusItem( "~Alt-Ç~ Exit", kbAltX, cmQuit ) +
            *original TStatusItem( 0, kbF10, cmMenu )
            );
}

Here’s what it appears to be like as if:

Unicode Hello

Instance: writing Unicode-conscious scheme() strategies

The following is an excerpt from an oldschool implementation of TFileViewer::scheme() (portion of the tvdemo application), which would no longer scheme Unicode textual mumble properly:

if (delta.y + i getCount()) {
    char s[maxLineLength+1];
    p=(char *)(fileLines->at(delta.y+i));
    if (p==0 || strlen(p) x)
        s[0]=EOS;
    else
        strnzcpy(s, p+delta.x, maxLineLength+1);
    b.moveStr(0, s, c);
}
writeBuf( 0, i, size.x, 1, b );

All it does is pass portion of a string in fileLines into b, which is a TDrawBuffer. delta is a TPoint representing the scroll offset within the textual mumble figuring out, and i is the index of the visible line being processed. c is the textual mumble color. A few components are exclaim:

  • TDrawBuffer::moveStr(ushort, const char *, TColorAttr) takes a null-terminated string. In notify to pass a substring of the most modern line, a reproduction is made into the array s, at the threat of a buffer overrun. The case the place the road would no longer fit into s is no longer dealt with, so at most maxLineLenght characters will seemingly be copied. What’s more, a multibyte character shut to space maxLineLength can also very properly be copied incompletely and be displayed as garbage.
  • delta.x is the first visible column. With multibyte-encoded textual mumble, it’s no longer sincere that such column begins at space delta.x within the string.

Under is a corrected model of the code above that handles Unicode properly:

if (delta.y + i getCount()) {
    p=(char *)(fileLines->at(delta.y+i));
    if (p)
        b.moveStr(0, p, c, size.x, delta.x);
}
writeBuf( 0, i, size.x, 1, b );

The overload of moveStr outmoded right here is TDrawBuffer::moveStr(ushort indent, TStringView str, TColorAttr attr, ushort width, ushort initiating up). This characteristic no longer most appealing presents Unicode toughen, but additionally helps us write cleaner code and overcome a number of of the obstacles beforehand exclaim:

  • The middleman reproduction is kept faraway from, so the displayed textual mumble is no longer diminutive to maxLineLength bytes.
  • moveStr takes care of printing the string starting at column delta.x. We extinguish no longer even wish to wretchedness about what number of bytes correspond to delta.x columns.
  • Equally, moveStr is truly helpful to reproduction at most size.x columns of textual mumble without us having to care about what number of bytes that is nor facing edge cases. The code is written in an encoding-agnostic intention and can also restful work whether or no longer multibyte characters are being notion about or no longer.
  • Whenever you hadn’t realized but, the middleman reproduction within the earlier model became fully pointless. It would possess been important most appealing if we had important to desirable the close of the road, but that became no longer the case: textual mumble occupies all of the figuring out’s width, and TView::writeBuf already takes care of no longer writing beyond it. Yet it’s appealing to figuring out how an pointless step no longer most appealing became limiting functionality but additionally became inclined to bugs.

Unicode toughen all the intention through identical earlier views

Reinforce for setting up Unicode-conscious views is in space, and most views within the contemporary Turbo Imaginative and prescient library possess been tailored to address Unicode.

The following views can exclaim Unicode textual mumble properly. Some of them also extinguish horizontal scrolling or observe wrapping; all of that must work gorgeous.

The following views can, as well to, direction of Unicode textual mumble or user enter:

  • TInputLine (81066ee5, cb489d42).
  • TEditor (702114dc). Conditions are in UTF-8 mode by default. You would also switch again to single-byte mode by pressing Ctrl+P. This most appealing adjustments how the document is displayed and the encoding of user enter; it would no longer alter the document. This class is outmoded within the tvedit application; you furthermore mght can test it there.

Views no longer on this checklist can also no longer possess important any corrections or I merely forgot to repair them. Please post a query within the occasion you be conscious anything no longer working as expected.

Utilize cases the place Unicode is no longer supported (no longer an exhaustive checklist):

  • Highlighted key shortcuts, on the general (e.g. TMenuBox, TStatusLine, TButton…).

The Turbo Imaginative and prescient API presents no integration with the device clipboard. As a developer you furthermore mght can restful access it by completely different skill (e.g. by the usage of libclipboard). Nonetheless unless you extinguish that, the explicit intention for a user to stick textual mumble into your application is to extinguish so throughout the terminal emulator.

Unfortunately, each and each character is processed as a separate evKeyDown match. If the user pastes 5000 characters, the applying will invent the an identical operations as if the user pressed the keyboard 5000 cases. This comprises drawing views, polishing off the match loop, updating the display veil, etcetera. As you furthermore mght can keep in mind, that is intention from optimum.

For the motive of facing this scenario, the Turbo Imaginative and prescient API has been prolonged with the following characteristic:

Boolean TView::textEvent(TEvent &match, TSpanchar> dest, size_t &size);

TEditor takes again of this characteristic to manufacture a upright user journey when pasting textual mumble throughout the terminal. You would also test it out within the tvedit application. As a developer, you furthermore mght could be drawn to the usage of it within the occasion you are imposing a textual mumble enhancing component. In every other case, you do no longer wish to care about it.

Correct for the legend, right here is a more detailed explanation:

textEvent() tries to read textual mumble from identical earlier enter and stores it in a user-offered buffer dest. It returns Flawed when no more occasions are readily accessible on this draw’s enter queue or if a non-textual mumble match is discovered, whereby case this match is saved with putEvent() in voice that it could perchance perchance be processed within the following iteration of the match loop.

The categorical number of bytes read is stored within the output parameter size, which is willing to beneath no circumstances be higher than dest.size().

It is miles intended to be outmoded as follows:

// 'ev' is a TEvent, and 'ev.what' equals 'evKeyDown'.
// If the match incorporates textual mumble...
if (ev.keyDown.textLength) {
    char buf[512];
    size_t size;
    // Hold 'buf' with textual mumble from the enter queue,
    // along side the textual mumble in 'ev'.
    whereas (textEvent(ev, buf, size)) {
        // Route of 'size' bytes of textual mumble in 'buf'.
        // ...
    }
    // 'textEvent()' clears 'ev' after learning it the first time
    // (by this level, 'ev.what' is 'evNothing').
}

The Turbo Imaginative and prescient API has been prolonged to permit more than the contemporary 16 colors.

Colours could even be specified the usage of any of the following codecs:

  • BIOS color attributes (4-bit), the format outmoded originally on MS-DOS.
  • RGB (24-bit).
  • xterm-256color palette indices (8-bit).
  • The terminal default color. This is the color outmoded by terminal emulators when no exclaim attributes (plucky, color…) are enabled (on the general white for foreground and dusky for background).

Though Turbo Imaginative and prescient applications tend to be ran in a terminal emulator, the API makes no assumptions about the exclaim tool. That is, the complexity of facing terminal emulators is hidden from the programmer and managed by Turbo Imaginative and prescient itself.

As an illustration: color toughen varies amongst terminals. If the programmer uses a color format no longer supported by the terminal emulator, Turbo Imaginative and prescient will quantize it to what the terminal can exclaim. The following images command the quantization of a 24-bit RGB image to 256, 16 and eight color palettes:

Extended color toughen on the general comes all the manner down to the following:

  • Turbo Imaginative and prescient has originally outmoded BIOS color attributes stored in an uchar. ushort is outmoded to whisper attribute pairs. This is restful the case when the usage of Borland C++.
  • In contemporary platforms a brand original form TColorAttr has been added which replaces uchar. It specifies a foreground and background color and a vogue. Colours could even be specified in completely different codecs (BIOS color attributes, 24-bit RGB…). Kinds are the everyday ones (plucky, italic, underline…). There’s also TAttrPair, which replaces ushort.
  • TDrawBuffer‘s strategies, which outmoded to take uchar or ushort parameters to specify color attributes, now take TColorAttr or TAttrPair.
  • TPalette, which outmoded to derive an array of uchar, now incorporates an array of TColorAttr. The TView::mapColor approach also returns TColorAttr as a replace of uchar.
  • TView::mapColor has been made digital in voice that the palette device could even be bypassed and not using a have to rewrite any scheme strategies.
  • TColorAttr and TAttrPair could even be initialized with and casted into uchar and ushort in a intention such that legacy code restful compiles out-of-the-box without any commerce in functionality.

Under is a more detailed explanation geared in direction of builders.

API reference of prolonged color toughen (click on to derive bigger).

Data Kinds

Within the first space we can exclaim the records styles the programmer desires to understand in notify to take again of the prolonged color suport.

To derive access to them, define the macro Uses_TColorAttr earlier than along side . You would also no longer wish to extinguish this because completely different classes like TView or TDrawBuffer already depend on it.

The final styles described on this portion are trivial. This means that they’ll also be memset‘d and memcpy‘d. Nonetheless variables of these styles are uninitialized when declared without initializer, correct like veteran styles. So make certain that you just do no longer manipulate them earlier than initializing them.

Color format styles

Loads of styles are defined which command completely different color codecs.
The motive why these styles exist is to permit distinguishing color codecs the usage of the fashion device. Some of them also possess public fields which derive it more uncomplicated to manipulate person bits.

  • TColorBIOS represents a BIOS color. It behaves the an identical as uint8_t, but lets in accessing the r, g, b and consuming bits personally.

    The memory format is:

    • Bit 0: Blue (field b).
    • Bit 1: Inexperienced (field g).
    • Bit 2: Crimson (field r).
    • Bit 3: Luminous (field consuming).
    • Bits 4-7: unused.
    TColorBIOS bios=0x4;  // 0x4: crimson.
    bios.consuming=1;        // 0xC: gentle crimson.
    bios.b=bios.r;        // 0xD: gentle magenta.
    bios=bios ^ 3;        // 0xE: yellow.
    uint8_t c=bios;       // Implicit conversion to integer styles.

    In terminal emulators, BIOS colors are mapped to the classic 16 ANSI colors.

  • TColorRGB represents a color in 24-bit RGB. It behaves the an identical as uint32_t but lets in accessing the r, g and b bit fields personally.

    The memory format is:

    • Bits 0-7: Blue (field b).
    • Bits 8-15: Inexperienced (field g).
    • Bits 16-23: Crimson (field r).
    • Bits 24-31: unused.
    TColorRGB rgb=0x9370DB;   // 0xRRGGBB.
    rgb={0x93, 0x70, 0xDB};   // {R, G, B}.
    rgb=rgb ^ 0xFFFFFF;       // Negated.
    rgb.g=rgb.r & 0x88;       // Net entry to to person parts.
    uint32_t c=rgb;           // Implicit conversion to integer styles.
  • TColorXTerm represents an index into the xterm-256color color palette. It behaves the an identical as uint8_t.

TColorDesired

TColorDesired represents a color which the programmer intends to voice on display veil, encoded in any of the supported color styles.

A TColorDesired could even be initialized within the following strategies:

  • As a BIOS color: with a char literal or a TColorBIOS object:

    TColorDesired bios1='xF';
    TColorDesired bios2=TColorBIOS(0xF);
  • As a RGB color: with an int literal or a TColorRGB object:

    TColorDesired rgb1=0xFF7700; // 0xRRGGBB.
    TColorDesired rgb2=TColorRGB(0xFF, 0x77, 0x00); // {R, G, B}.
    TColorDesired rgb3=TColorRGB(0xFF7700); // 0xRRGGBB.
  • As an XTerm palette index: with a TColorXTerm object.

  • Because the terminal default color: through zero-initialization:

    TColorDesired def1 {};
    // Or with 'memset': 
    TColorDesired def2;
    memset(&def2, 0, sizeof(def2));

TColorDesired has strategies to query the contained color, but you can on the general no longer wish to employ them. Explore the struct definition in for more records.

Trivia: the determine is inspired by Scintilla‘s ColourDesired.

TColorAttr

TColorAttr describes the color attributes of a display veil cell. This is the fashion you are in all likelihood to work along side within the occasion you propose to commerce the colors in a figuring out.

A TColorAttr contains:

  • A foreground color, of form TColorDesired.

  • A background color, of form TColorDesired.

  • A mode bitmask containing a mix of the following flags:

    • slBold.
    • slItalic.
    • slUnderline.
    • slBlink.
    • slReverse.
    • slStrike.

    These flags are constant with the classic exclaim attributes selectable through ANSI destroy out codes. The results can also fluctuate between terminal emulators. slReverse is perchance the least professional of them: grab the usage of the TColorAttr reverseAttribute(TColorAttr attr) free characteristic over environment this flag.

Basically the most straight-forward technique to extinguish a TColorAttr is by the usage of the TColorAttr(TColorDesired fg, TColorDesired bg, ushort vogue=0) and TColorAttr(int bios) constructors:

// Foreground: RGB 0x892312
// Background: RGB 0x7F00BB
// Vogue: Favorite.
TColorAttr a1={TColorRGB(0x89, 0x23, 0x12), TColorRGB(0x7F, 0x00, 0xBB)};

// Foreground: BIOS 0x7.
// Background: RGB 0x7F00BB.
// Vogue: Daring, Italic.
TColorAttr a2={'x7', 0x7F00BB, slBold | slItalic};

// Foreground: Terminal default.
// Background: BIOS 0xF.
// Vogue: Favorite.
TColorAttr a3={{}, TColorBIOS(0xF)};

// Foreground: Terminal default.
// Background: Terminal default.
// Vogue: Favorite.
TColorAttr a4={};

// Foreground: BIOS 0x0
// Background: BIOS 0x7
// Vogue: Favorite
TColorAttr a5=0x70;

The fields of a TColorAttr could even be accessed with the following free capabilities:

TColorDesired getFore(const TColorAttr &attr);
TColorDesired getBack(const TColorAttr &attr);
ushort getStyle(const TColorAttr &attr);
void setFore(TColorAttr &attr, TColorDesired fg);
void setBack(TColorAttr &attr, TColorDesired bg);
void setStyle(TColorAttr &attr, ushort vogue);

TAttrPair

TAttrPair is a pair of TColorAttr, outmoded by some API capabilities to pass two attributes at once.

You would also initialize a TAttrPair with the TAttrPair(const TColorAttrs &lo, const TColorAttrs &hi there) constructor:

TColorAttr cNormal={0x234983, 0x267232};
TColorAttr cHigh={0x309283, 0x127844};
TAttrPair attrs={cNormal, cHigh};
TDrawBuffer b;
b.moveCStr(0, "Favorite textual mumble, ~Highlighted textual mumble~", attrs);

The attributes could even be accessed with the [0] and [1] subindices:

TColorAttr lo={0x892343, 0x271274};
TColorAttr hi there='x93';
TAttrPair attrs={lo, hi there};
say(lo==attrs[0]);
say(hi there==attrs[1]);

Altering the appears to be like of a TView

Views are repeatedly drawn by the usage of a TDrawBuffer. Most TDrawBuffer member capabilities take color attributes by parameter. As an illustration:

ushort TDrawBuffer::moveStr(ushort indent, TStringView str, TColorAttr attr);
ushort TDrawBuffer::moveCStr(ushort indent, TStringView str, TAttrPair attrs);
void TDrawBuffer::putAttribute(ushort indent, TColorAttr attr);

On the different hand, the views supplied with Turbo Imaginative and prescient on the general store their color records in palettes. A figuring out’s palette could even be queried with the following member capabilities:

TColorAttr TView::mapColor(uchar index);
TAttrPair TView::getColor(ushort indices);
  • mapColor appears to be like up a single color attribute within the figuring out’s palette, given an index into the palette. Undergo in mind that the palette indices for every and each figuring out class could even be discovered within the Turbo Imaginative and prescient headers. As an illustration, says the following about TScrollBar:

    /* ---------------------------------------------------------------------- */
    /*      class TScrollBar                                                  */
    /*                                                                        */
    /*      Palette format                                                    */
    /*        1=Net page areas                                                  */
    /*        2=Arrows                                                      */
    /*        3=Indicator                                                   */
    /* ---------------------------------------------------------------------- */
  • getColor is a helper characteristic that lets in querying two cell attributes at once. Every byte within the indices parameter incorporates an index into the palette. The TAttrPair result incorporates the 2 cell attributes.

    As an illustration, the following could even be discovered within the scheme approach of TMenuBar:

    TAttrPair cNormal=getColor(0x0301);
    TAttrPair cSelect=getColor(0x0604);

    Which could perchance be an identical to this:

    TAttrPair cNormal={mapColor(1), mapColor(3)};
    TAttrPair cSelect={mapColor(4), mapColor(6)};

As an API extension, the mapColor approach has been made digital. This makes it conceivable to override Turbo Imaginative and prescient’s hierarchical palette device with a custom resolution and not using a have to rewrite the scheme() approach.

So, on the general, there are 3 strategies to employ prolonged colors in views:

  1. By offering prolonged color attributes straight to TDrawBuffer strategies, if the palette device is no longer being outmoded. As an illustration:

    // The 'TMyView' class inherits from 'TView' and overrides 'TView::scheme'.
    void TMyView::scheme()
    {
        TDrawBuffer b;
        TColorAttr color {0x1F1C1B, 0xFAFAFA, slBold};
        b.moveStr(0, "This is plucky dusky textual mumble over a white background", color);
        /* ... */
    }
  2. By enhancing the palettes. There are two strategies to extinguish this:

    1. By enhancing the applying palette after it has been constructed. Portray that the palette parts are TColorAttr. As an illustration:
    void updateAppPalette()
    {
        TPalette &friend=TProgram::application->getPalete();
        friend[1]={0x762892, 0x828712};              // TBackground.
        friend[2]={0x874832, 0x249838, slBold};      // TMenuView contemporary textual mumble.
        friend[3]={{}, {}, slItalic | slUnderline};  // TMenuView disabled textual mumble.
        /* ... */
    }
    1. By the usage of prolonged color attributes within the applying palette definition:
    static const TColorAttr cpMyApp[]=
    {
        {0x762892, 0x828712},               // TBackground.
        {0x874832, 0x249838, slBold},       // TMenuView contemporary textual mumble.
        {{}, {}, slItalic | slUnderline},   // TMenuView disabled textual mumble.
        /* ... */
    };
    
    // The 'TMyApp' class inherits from 'TApplication' and overrides 'TView::getPalette'.
    TPalette &TMyApp::getPalette() const
    {
        static TPalette palette(cpMyApp);
        return palette;
    }
  3. By returning prolonged color attributes from an overriden mapColor approach:

// The 'TMyScrollBar' class inherits from 'TScrollBar' and overrides 'TView::mapColor'.
TColorAttr TMyScrollBar::mapColor(uchar index) noexcept
{
    // On this case the values are hardcoded,
    // but they'll also very properly be stored in completely different locations if desired.
    switch (index)
    {
        case 1:     return {0x492983, 0x826124}; // Net page areas.
        case 2:     return {0x438939, 0x091297}; // Arrows.
        case 3:     return {0x123783, 0x329812}; // Indicator.
        default:    return errorAttr;
    }
}

Portray capabilities

TScreen::screenMode exposes some records about the exclaim’s color toughen:

  • If (TScreen::screenMode & 0xFF)==TDisplay::smMono, the exclaim is monocolor (most appealing associated in DOS).
  • If (TScreen::screenMode & 0xFF)==TDisplay::smBW80, the exclaim is grayscale (most appealing associated in DOS).
  • If (TScreen::screenMode & 0xFF)==TDisplay::smCO80, the exclaim helps at the least 16 colors.
    • If TScreen::screenMode & TDisplay::smColor256, the exclaim helps at the least 256 colors.
    • If TScreen::screenMode & TDisplay::smColorHigh, the exclaim helps intention more colors (e.g. 24-bit color). TDisplay::smColor256 could be place of abode on this case.

Backward-compatibility

The styles defined beforehand command ideas that are also crucial when increasing for Borland C++:

Thought Format in Borland C++ Format in contemporary platforms
Color Attribute uchar. A BIOS color attribute. struct TColorAttr.
Color A 4-bit number. struct TColorDesired.
Attribute Pair ushort. An attribute in each and each byte. struct TAttrPair.

Thought to be one of this mission’s key ideas is that the API can also restful be outmoded within the an identical intention each and each in Borland C++ and contemporary platforms, that is, without the need for #ifdefs. One more precept is that legacy code can also restful compile out-of-the-box, and adapting it to the original capabilities can also restful lift complexity as petite as conceivable.

Backward-compatibility is executed within the following intention:

  • In Borland C++, TColorAttr and TAttrPair are typedef‘d to uchar and ushort, respectively.

  • In contemporary platforms, TColorAttr and TAttrPair could even be outmoded comparatively than uchar and ushort, respectively. That is, the assertions within the following code will no longer fail:

    // Any rate which works into a 'uchar' could even be
    // losslessly handed through TColorAttr.
    uchar c=0;
    extinguish {
        say(uchar(TColorAttr {c})==c);
    } whereas (c++ // Any rate which works into a 'ushort' could even be
    // losslessly handed through TAttrPair.
    ushort s=0;
    extinguish {
        say(ushort(TAttrPair {s})==s);
    } whereas (s++ 

    A TColorAttr initialized with uchar represents a BIOS color attribute. When converting again to uchar, the following happens:

    • If fg and bg are BIOS colors, and vogue is cleared, the resulting uchar represents the an identical BIOS color attribute contained within the TColorAttr (as within the code above).
    • In every other case, the conversion leads to a color attribute that stands out, i.e. white on magenta, which implies that the programmer can also restful retain in mind changing uchar/ushort with TColorAttr/TAttrPair within the occasion that they intend to toughen the prolonged color attributes.

    The identical goes for TAttrPair and ushort, alive to by that it’s mild of two TColorAttr.

A employ case of backward-compatibility within Turbo Imaginative and prescient itself is the TPalette class, core of the palette device. In its contemporary develop, it outmoded a single records form (uchar) to whisper a lot of things: array size, palette indices or color attributes.

The original develop merely replaces uchar with TColorAttr. This means there don’t look like any adjustments within the manner TPalette is outmoded, but TPalette is now ready to store prolonged color attributes.

TColorDialog hasn’t been transformed but, and thus it can not be outmoded to grab prolonged color attributes at runtime.

Instance: along side prolonged color toughen to legacy code

The following sample of code is frequent all the intention through scheme strategies of views:

void TMyView::scheme()
{
    ushort cFrame, cTitle;
    if (explain & sfDragging)
    {
        cFrame=0x0505;
        cTitle=0x0005;
    }
    else
    {
        cFrame=0x0503;
        cTitle=0x0004;
    }
    cFrame=getColor(cFrame);
    cTitle=getColor(cTitle);
    /* ... */
}

On this case, ushort is outmoded each and each as a pair of palette indices and as a pair of color attributes. getColor now returns a TAttrPair, so despite the indisputable truth that this compiles out-of-the-box, prolonged attributes will seemingly be misplaced within the implicit conversion to ushort.

The code above restful works correct adore it did originally. It be most appealing non-BIOS color attributes that don’t fabricate the expected result. Because of the the compatibility between TAttrPair and ushort, the following is passable to permit toughen for prolonged color attributes:

-    ushort cFrame, cTitle;
+    TAttrPair cFrame, cTitle;

Nothing prevents you from the usage of completely different variables for palette indices and color attributes, which is what can also restful if fact be told be

>>
Read More

Vanic
WRITTEN BY

Vanic

“Simplicity, patience, compassion.
These three are your greatest treasures.
Simple in actions and thoughts, you return to the source of being.
Patient with both friends and enemies,
you accord with the way things are.
Compassionate toward yourself,
you reconcile all beings in the world.”
― Lao Tzu, Tao Te Ching