magiblot / tvision

A modern port of Turbo Vision 2.0, the classical framework for text-based user interfaces. Now cross-platform and with Unicode support.
Other
1.99k stars 150 forks source link

TEditor color mistake/bug in the source, and a alternative to set the color of TEditor sub classes #121

Open paule32 opened 9 months ago

paule32 commented 9 months ago

Hello magiblot ! I found an old issue. - Can you remember, as we discuss with the implementation of a Syntax Highlighter, week's, and month's ago ? In the source: https://github.com/magiblot/tvision/blob/master/source/tvision/edits.cpp#L51

...
    for (int r = 0; r < 3; ++r)   // <-- loop
    {
        Color = ranges[r].color;  // <-- loop access Color (at end it's: 0x03 (balck on green)
        while (P < ranges[r].end)
        {
...

You assign the "Color" by a for-loop, and the last color for this is 0x03. So, the background color of TEditor windows will be display with black background (0x0), and green foreground/text color (0x3). This can be a no-go for someone who is using TEditor.

I came to this point, as I remember, that I change the edits.cpp.

I added Code/Variable "EditTextColor", I came to no point to get a better name. But you can rename it - please notify the other users than, or right write documentation.

I add "TColorAttr EditTextColor = 0x1e;" to the C++ header file editors.h. So each individual TEditor can have it's own customizable Color.

Here comes my Code (like you can see, it is extended by a comment-parser) in edits.cpp:

void
TEditor::formatLine(
    TScreenCell *DrawBuf,
    uint P,
    int Width,
    TAttrPair
    ) { 

    TSpan<TScreenCell> Cells(DrawBuf, Width);
    TStringView chars;
    TColorAttr  Color;

    char Ch;

    int X = 0;
    Color = EditorTextColor;   // <-- the magic key

    while (1) {
    if (P >= bufLen || X >= Width) break;
        chars = bufChars(P);
        Ch = chars[0];
        if (Ch == '(') {
            ::setCell(Cells[X], '(', EditorTextColor);
            X++;
            P++;
            chars = bufChars(P);
            Ch = chars[0];
            if (P >= bufLen || X >= Width) break;
            if (Ch == '*') {
                tokenIsComment = true;
                ::setCell(Cells[X-1], '(', 0x03);
                ::setCell(Cells[X  ], '*', 0x03);
                X++;
                P++;
                while (1) {
            if (P >= bufLen || X >= Width) break;
                    chars = bufChars(P);
                    Ch = chars[0];
                    if (Ch == '*') {
                        ::setCell(Cells[X], '*', 0x03);
                        X++;
                        P++;
            if (P >= bufLen || X >= Width) break;
                        chars = bufChars(P);
                        Ch = chars[0];
                        if (Ch == ')') {
                            ::setCell(Cells[X], Ch, 0x03);
                            tokenIsComment = false;
                            Color = EditorTextColor;
                            X++;
                            P++;
                            break;
                        }   else
                        if (Ch == '\r' || Ch == '\n')
                        {
                            while (X < Width)
                            ::setCell(Cells[X++], ' ', 0x03);
                            P++;
                            break;
                        }   else {
                            ::setCell(Cells[X], Ch, 0x03);
                            X++;
                            P++;
               if (P >= bufLen || X >= Width) break;
                        }
                    }   else
                    if (Ch == '\r' || Ch == '\n') {
                        while (X < Width)
                        ::setCell(Cells[X++], ' ', 0x03);
                        P++;
            if (P >= bufLen || X >= Width) break;
                    }   else {
                        ::setCell(Cells[X], Ch, 0x03);
                        X++;
                        P++;
            if (P >= bufLen || X >= Width) break;
                    }
                }
            }   else {
                ::setCell(Cells[X], Ch, EditorTextColor);
                X++;
                P++;
        if (P >= bufLen || X >= Width) break;
            }
        }   else
        if (Ch == '*') {
            if (tokenIsComment) {
                ::setCell(Cells[X], '*', 0x03);
                X++;
                P++;
        if (P >= bufLen || X >= Width) break;
                chars = bufChars(P);
                Ch = chars[0];

                if (Ch == ')') {
                    tokenIsComment = false;
                    Color = EditorTextColor;
                    ::setCell(Cells[X], ')', 0x03);
                    X++;
                    P++;
            if (P >= bufLen || X >= Width) break;
                }   else {
                    Color = 0x03;
                    ::setCell(Cells[X], '*', 0x03);
                    X++;
                    P++;
            if (P >= bufLen || X >= Width) break;
                }
            }   else {
                ::setCell(Cells[X], '*', EditorTextColor);
                X++;
                P++;
        if (P >= bufLen || X >= Width) break;
            }
        }   else
        if (Ch == '\r' || Ch == '\n')
        {
            if (tokenIsComment)
            Color = 0x03; else
            Color = EditorTextColor;

            while (X < Width)
            ::setCell(Cells[X++], ' ', Color);
            P++;
            break;
        }   else
        if (Ch == '\t')
        {
            if (tokenIsComment)
            Color = 0x03; else
            Color = EditorTextColor;

            if (X < Width) {
                do {
                    ::setCell(Cells[X++], ' ', Color);
                } while (X%8 != 0 && X < Width);
                ++P;
            }   else break;
        }   else {
            if (tokenIsComment)
            Color = 0x03; else
            Color = EditorTextColor;

            if (!formatCell(Cells, (uint&) X, chars, P, Color))
            break;
        }
    }
    while (X < Width)
    ::setCell(Cells[X++], ' ', Color);
}

and there (editors.h) extended Code (only one line, but I add some extra lines for orientation):

...
class TEditor : public TView
{
public:
// added: paule32 at: 2023-11-16
// change the text & background color of TEditor, default is blue on yellow
// the BIOS color code: 0x1e
TColorAttr EditorTextColor = 0x1e;

    friend void genRefs();

    TEditor( const TRect&, TScrollBar *, TScrollBar *, TIndicator *, uint ) noexcept;
    virtual ~TEditor();
...

So, you can create a sub-class of the TEditor:

class MyEditorChild: public TEditor {
public:
    MyEditorChild(
        const TRect& bounds,
        TScrollBar * hScrollBar,
        TScrollBar * vScrollBar,
        TIndicator * indicator,
        TStringView  filename):
        TEditor( bounds,hScrollBar,vScrollBar,indicator,999999999) {

        EditorTextColor = 0x40;  // <-- red on black
    }
    void handleEvent( TEvent &event )
    {
        TEditor::handleEvent( event );
        ...
    }
};

I wish you a good mood, and day. Hope this Help

Jens aka paule32