From 806fa1d9d1855962182ae87257f645995641c5ee Mon Sep 17 00:00:00 2001 From: orbitalquark <70453897+orbitalquark@users.noreply.github.com> Date: Wed, 12 Nov 2025 21:06:22 -0500 Subject: [PATCH 1/2] Added ability to disable use of the terminal's default color palette. This tries to preserve the 16 default colors if the terminal doesn't have enough colors. --- PlatCurses.cxx | 19 ++++++++++++++----- PlatCurses.h | 3 +++ ScintillaCurses.cxx | 2 ++ ScintillaCurses.h | 8 ++++++++ docs/README.md | 4 ++++ docs/api.md | 7 +++++++ docs/scinterm.luadoc | 5 +++++ 7 files changed, 43 insertions(+), 5 deletions(-) diff --git a/PlatCurses.cxx b/PlatCurses.cxx index dd995fa..ee7c665 100644 --- a/PlatCurses.cxx +++ b/PlatCurses.cxx @@ -131,12 +131,15 @@ Colors &Colors::instance() { short Colors::get(const ColourRGBA &color) { if (const auto entry = colors.find(color.OpaqueRGB()); entry != colors.end()) return entry->second; - if (colorOffset + colors.size() >= std::numeric_limits::max()) return COLOR_WHITE; - const short c = colorOffset + colors.size(); - init_color(c, color.GetRed() * 1000.0 / 255, color.GetGreen() * 1000.0 / 255, + short i = colorOffset + colors.size(); + // try not to overwrite a default color + if (!usePalette && COLORS > 16 && colorOffset < 16) + i += 16 - colorOffset; + if (i >= COLORS || i >= std::numeric_limits::max()) return COLOR_WHITE; + init_color(i, color.GetRed() * 1000.0 / 255, color.GetGreen() * 1000.0 / 255, color.GetBlue() * 1000.0 / 255); - colors.emplace(color.OpaqueRGB(), c); - return c; + colors.emplace(color.OpaqueRGB(), i); + return i; } short Colors::Pair(const ColourRGBA &fore, const ColourRGBA &back) { @@ -160,6 +163,12 @@ ColourRGBA Colors::Find(const short color) { return Colors::White; } +void Colors::DisablePalette() { + instance().usePalette = false; + instance().colors.clear(); + instance().pairs.clear(); +} + void Colors::SetOffsets(int colorOffset, int pairOffset) { instance().colorOffset = colorOffset; instance().pairOffset = pairOffset; diff --git a/PlatCurses.h b/PlatCurses.h index 93fe715..a00d3e3 100644 --- a/PlatCurses.h +++ b/PlatCurses.h @@ -141,6 +141,7 @@ class Colors { std::map colors; // map of RGB ints to curses color numbers. std::map, short> pairs; // map of curses colors to their pair numbers int colorOffset = 0, pairOffset = 0; + bool usePalette = true; Colors(); static Colors &instance(); @@ -156,6 +157,8 @@ class Colors { /** Returns the Scintilla color for a given curses color number. */ static ColourRGBA Find(const short color); + /** Disables use of the terminal's default color palette. */ + static void DisablePalette(); /** Sets the offsets for colors and color pairs generated on-demand. */ static void SetOffsets(int colorOffset, int pairOffset); }; diff --git a/ScintillaCurses.cxx b/ScintillaCurses.cxx index 6b53ebf..f892438 100644 --- a/ScintillaCurses.cxx +++ b/ScintillaCurses.cxx @@ -699,6 +699,8 @@ void scintilla_update_cursor(void *sci) { void scintilla_delete(void *sci) { delete reinterpret_cast(sci); } +void scintilla_disable_color_palette() { Scintilla::Internal::Colors::DisablePalette(); } + void scintilla_set_color_offsets(int color_offset, int pair_offset) { Scintilla::Internal::Colors::SetOffsets(color_offset, pair_offset); } diff --git a/ScintillaCurses.h b/ScintillaCurses.h index 159a0f5..98a38c2 100644 --- a/ScintillaCurses.h +++ b/ScintillaCurses.h @@ -116,9 +116,17 @@ void scintilla_update_cursor(void *sci); */ void scintilla_delete(void *sci); +/** + * Disables use of the terminal's default color palette for all Scintilla windows. + * This only needs to be called once, after calling `start_color()` + * and ideally before any calls to `scintilla_new()`. + */ +void scintilla_disable_color_palette(void); + /** * Sets the offsets for colors and color pairs generated on-demand. * Applications that define their own colors and color pairs can tell Scinterm where to start from. + * This should be called after `start_color()`. */ void scintilla_set_color_offsets(int color_offset, int pair_offset); diff --git a/docs/README.md b/docs/README.md index 5f631f1..0666b56 100644 --- a/docs/README.md +++ b/docs/README.md @@ -68,6 +68,8 @@ application. ### Colors If your terminal emulator supports RGB colors, you may use them freely in Scintilla messages. +However, if you use any of the colors listed below, they will be mapped to your terminal's +default color palette. To prevent this, call [`scintilla_disable_color_palette()`][]. If you prefer to use your terminal emulator's palette of up to 16 colors, you must use the colors from the following table, which are listed in Scintilla's "0xBBGGRR" format. @@ -83,6 +85,8 @@ colors from the following table, which are listed in Scintilla's "0xBBGGRR" form Your terminal will map these colors to its palette for display. In some terminals, you may need to set a style's bold attribute in order to use the light color variant. +[`scintilla_disable_color_palette`]: api.md#scintilla_disable_color_palette + ## Curses Compatibility Scinterm lacks some Scintilla features due to the terminal's constraints: diff --git a/docs/api.md b/docs/api.md index 659233b..5be6611 100644 --- a/docs/api.md +++ b/docs/api.md @@ -16,6 +16,13 @@ Parameters: Returns: `void` + +### `scintilla_disable_color_palette`() + +Disables use of the terminal's default color palette for all Scintilla windows. + +This only needs to be called once, and ideally before any calls to `scintilla_new()`. + ### `scintilla_get_clipboard`(*sci*, *len*) diff --git a/docs/scinterm.luadoc b/docs/scinterm.luadoc index f96f00c..b7cb1a1 100644 --- a/docs/scinterm.luadoc +++ b/docs/scinterm.luadoc @@ -88,8 +88,13 @@ -- @return `void` -- @function scintilla_delete +--- Disables use of the terminal's default color palette for all Scintilla windows. +-- This only needs to be called once, and ideally before any calls to `scintilla_new()`. +-- @function scintilla_disable_color_palette + --- Sets the offsets for colors and color pairs generated on-demand. -- Applications that define their own colors and color pairs can tell Scinterm where to start from. +-- This should be called after `start_color()`. -- @param color_offset The offset for Scinterm's calls to `init_color()`. -- @param pair_offset The offset for Scinterm's calls to `init_pair()`. -- @function scintilla_set_color_offsets From 14c560e63d280f2a8f26b4bbf287d7af679b0a13 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Sat, 9 May 2026 16:33:36 +0200 Subject: [PATCH 2/2] added scintilla_set_default_colors() allows substituting specific foreground and background colors with ncurses default colors (-1), which will preserve the terminal emulator's native color scheme. --- PlatCurses.cxx | 130 +++++++++++++++++++++++++++++++------------ PlatCurses.h | 13 ++++- ScintillaCurses.cxx | 38 ++++++++++--- ScintillaCurses.h | 11 ++++ docs/scinterm.luadoc | 10 ++++ 5 files changed, 157 insertions(+), 45 deletions(-) diff --git a/PlatCurses.cxx b/PlatCurses.cxx index ee7c665..5113995 100644 --- a/PlatCurses.cxx +++ b/PlatCurses.cxx @@ -129,23 +129,40 @@ Colors &Colors::instance() { } short Colors::get(const ColourRGBA &color) { - if (const auto entry = colors.find(color.OpaqueRGB()); entry != colors.end()) + if (const auto entry = instance().colors.find(color.OpaqueRGB()); entry != instance().colors.end()) return entry->second; - short i = colorOffset + colors.size(); + short i = instance().colorOffset + instance().colors.size(); // try not to overwrite a default color - if (!usePalette && COLORS > 16 && colorOffset < 16) - i += 16 - colorOffset; + if (!instance().usePalette && COLORS > 16 && instance().colorOffset < 16) + i += 16 - instance().colorOffset; if (i >= COLORS || i >= std::numeric_limits::max()) return COLOR_WHITE; init_color(i, color.GetRed() * 1000.0 / 255, color.GetGreen() * 1000.0 / 255, color.GetBlue() * 1000.0 / 255); - colors.emplace(color.OpaqueRGB(), i); + instance().colors.emplace(color.OpaqueRGB(), i); return i; } -short Colors::Pair(const ColourRGBA &fore, const ColourRGBA &back) { - if (!has_colors()) return 0; +short Colors::Pair(attr_t &attrs, const ColourRGBA &fore, const ColourRGBA &back) { + // If the terminal is a dumb one without colors, we can work with a "second pair" + // that is the reverse of the current one if the background color to draw is + // white. This applies to all `mvwchgat()` and `wattr_set()` calls. + if (!has_colors()) { + if (!(back.Opaque() == Colors::Black)) attrs ^= WA_REVERSE; + return 0; + } + + short fore_id, back_id; + + if (fore.OpaqueRGB() == instance().defaultBack && back.OpaqueRGB() == instance().defaultFore) { + fore_id = back_id = -1; + attrs ^= WA_REVERSE; + } else { + fore_id = fore.OpaqueRGB() == instance().defaultFore ? -1 : get(fore); + back_id = back.OpaqueRGB() == instance().defaultBack ? -1 : get(back); + } + + const auto pair = std::make_pair(fore_id, back_id); auto &pairs = instance().pairs; - const auto pair = std::make_pair(instance().get(fore), instance().get(back)); if (const auto entry = pairs.find(pair); entry != pairs.end()) return entry->second; size_t max_pairs = COLOR_PAIRS; if (const size_t short_max = std::numeric_limits::max(); short_max < max_pairs) @@ -174,6 +191,19 @@ void Colors::SetOffsets(int colorOffset, int pairOffset) { instance().pairOffset = pairOffset; } +void Colors::SetDefaultColors(int fore, int back) { + instance().defaultFore = fore; + instance().defaultBack = back; +} + +int Colors::GetDefaultFore() { + return instance().defaultFore; +} + +int Colors::GetDefaultBack() { + return instance().defaultBack; +} + // Surface handling. SurfaceImpl::~SurfaceImpl() noexcept { Release(); } @@ -233,12 +263,9 @@ void SurfaceImpl::PolyLine(const Point *pts, size_t npts, Stroke stroke) { short pair = 0, unused_color, back = COLOR_BLACK; mvwin_wch(win, y, x, &wch), getcchar(&wch, unused_wch, &attrs, &pair, nullptr); if (pair > 0) pair_content(pair, &unused_color, &back); - // If the terminal is a dumb one without colors, we can work with a "second pair" - // that is the reverse of the current one if the background color to draw is - // white. This applies to all `mvwchgat()` and `wattr_set()` calls. - if (!(has_colors() || Colors::Find(back).Opaque() == Colors::Black)) attrs |= WA_REVERSE; - mvwchgat( - win, y, x, 1, attrs | WA_UNDERLINE, Colors::Pair(stroke.colour, Colors::Find(back)), nullptr); + if (back < 0) back = Colors::get(ColourRGBA::FromRGB(Colors::GetDefaultBack())); + pair = Colors::Pair(attrs, stroke.colour, Colors::Find(back)); + mvwchgat(win, y, x, 1, attrs | WA_UNDERLINE, pair, nullptr); } } @@ -247,8 +274,11 @@ void SurfaceImpl::PolyLine(const Point *pts, size_t npts, Stroke stroke) { // normally drawn as polygons are handled in `DrawLineMarker()`. void SurfaceImpl::Polygon(const Point *pts, size_t npts, FillStroke fillStroke) { ColourRGBA &back = fillStroke.fill.colour; - const attr_t attrs = has_colors() ? 0 : WA_REVERSE; - wattr_set(win, attrs, Colors::Pair(back, Colors::White), nullptr); // invert + const ColourRGBA &fore = Colors::GetDefaultFore() >= 0 + ? ColourRGBA::FromRGB(Colors::GetDefaultFore()) : Colors::White; + attr_t attrs = 0; + short pair = Colors::Pair(attrs, back, fore); // invert + wattr_set(win, attrs, pair, nullptr); if (pts[0].y < pts[npts - 1].y) // up arrow mvwaddstr(win, static_cast(pts[0].y), static_cast(pts[npts - 1].x - 2), "▲"); else if (pts[0].y > pts[npts - 1].y) // down arrow @@ -265,19 +295,25 @@ void SurfaceImpl::RectangleFrame(PRectangle /*rc*/, Stroke /*stroke*/) {} // Normally this clears the given portion of the screen with the given background color. In // some cases however, it can be determined that whitespace is being drawn. If so, draw it // appropriately instead of clearing the given portion of the screen. +// This can also draw the caret. void SurfaceImpl::FillRectangle(PRectangle rc, Fill fill) { if (!win) { // Drawing to a pixmap, probably the fold margin. Record the color for a later fill. pixmapColor = fill.colour; return; } - const attr_t attrs = has_colors() || fill.colour.Opaque() == Colors::Black ? 0 : WA_REVERSE; - wattr_set(win, attrs, Colors::Pair(Colors::White, fill.colour), nullptr); + attr_t attrs = 0; + const ColourRGBA &fore = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::White; + short pair = Colors::Pair(attrs, fore, fill.colour); + wattr_set(win, attrs, pair, nullptr); chtype ch = ' '; if (fabs(rc.left - static_cast(rc.left)) > 0.1) { // If rc.left is a fractional value (e.g. 4.5) then whitespace dots are being drawn. Draw // them appropriately. - wattr_set(win, attrs, Colors::Pair(fill.colour, fill.colour), nullptr); + attrs = 0; + short pair = Colors::Pair(attrs, fill.colour, fill.colour); + wattr_set(win, attrs, pair, nullptr); rc.right = static_cast(rc.right), ch = ACS_BULLET | A_BOLD; } for (int y = static_cast(rc.top); y < rc.bottom; y++) @@ -314,8 +350,9 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, XYPOSITION /*cornerSize*/, FillS short pair = 0, fore = COLOR_WHITE, unused_color; mvwin_wch(win, y, x, &wch), getcchar(&wch, unused_wch, &attrs, &pair, nullptr); if (pair > 0) pair_content(pair, &fore, &unused_color); - if (!(has_colors() || fill.Opaque() == Colors::Black)) attrs |= WA_REVERSE; - mvwchgat(win, y, x, 1, attrs, Colors::Pair(Colors::Find(fore), fill), nullptr); + if (fore < 0) fore = Colors::get(ColourRGBA::FromRGB(Colors::GetDefaultFore())); + pair = Colors::Pair(attrs, Colors::Find(fore), fill); + mvwchgat(win, y, x, 1, attrs, pair, nullptr); } } @@ -335,11 +372,22 @@ void SurfaceImpl::Stadium(PRectangle /*rc*/, FillStroke /*fillStroke*/, Ends /*e // Only called when drawing indentation guides or during certain drawing operations when double // buffering is enabled. Since the latter is not supported, assume the former. void SurfaceImpl::Copy(PRectangle rc, Point /*from*/, Surface &surfaceSource) { - const ColourRGBA &fore = dynamic_cast(&surfaceSource)->isIndentGuideHighlight ? - Colors::White : - Colors::Black; + ColourRGBA fore, back; + if (dynamic_cast(&surfaceSource)->isIndentGuideHighlight) { + fore = Colors::GetDefaultFore() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultFore()) : Colors::White; + back = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; + } else { + fore = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; + back = Colors::GetDefaultFore() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultFore()) : Colors::White; + } if (rc.left - 1 < clip.left) return; - wattr_set(win, 0, Colors::Pair(fore, Colors::Black), nullptr); + attr_t attrs = 0; + short pair = Colors::Pair(attrs, fore, back); + wattr_set(win, attrs, pair, nullptr); mvwaddch(win, static_cast(rc.top), static_cast(rc.left - 1), '|' | A_BOLD); } @@ -369,8 +417,8 @@ int grapheme_width(const char *s) { void SurfaceImpl::DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION /*ybase*/, std::string_view text, ColourRGBA fore, ColourRGBA back) { attr_t attrs = dynamic_cast(font_)->attrs; - if (!(has_colors() || back.Opaque() == Colors::Black)) attrs |= WA_REVERSE; - wattr_set(win, attrs, Colors::Pair(fore, back), nullptr); + short pair = Colors::Pair(attrs, fore, back); + wattr_set(win, attrs, pair, nullptr); if (rc.left < clip.left) { // Do not overwrite margin text. auto clip_chars = static_cast(clip.left - rc.left); @@ -422,6 +470,11 @@ void SurfaceImpl::DrawTextTransparent( pair_content(pair, &unused_color, &back); else if (attrs & WA_REVERSE) // !has_colors() and white terminal background back = COLOR_WHITE; + if (back < 0) { + // We cannot pass on attrs, so the background color must be correct. + int c = attrs & WA_REVERSE ? Colors::GetDefaultFore() : Colors::GetDefaultBack(); + back = Colors::get(ColourRGBA::FromRGB(c)); + } } DrawTextNoClip(rc, font_, ybase, text, fore, Colors::Find(back)); } @@ -489,9 +542,9 @@ void SurfaceImpl::FlushDrawing() {} // N/A void SurfaceImpl::DrawLineMarker( const PRectangle &rcWhole, const Font *fontForCharacter, int tFold, const void *data) { auto marker = reinterpret_cast(data); - attr_t attr = has_colors() || marker->back.Opaque() == Colors::Black ? 0 : WA_REVERSE; - if (tFold) attr |= WA_BOLD; - wattr_set(win, attr, Colors::Pair(marker->fore, marker->back), nullptr); + attr_t attr = tFold ? WA_BOLD : 0; + short pair = Colors::Pair(attr, marker->fore, marker->back); + wattr_set(win, attr, pair, nullptr); int top = static_cast(rcWhole.top), left = static_cast(rcWhole.left); switch (marker->markType) { case MarkerSymbol::Circle: mvwaddstr(win, top, left, "●"); return; @@ -535,17 +588,24 @@ void SurfaceImpl::DrawLineMarker( // Draws the text representation of a wrap marker. void SurfaceImpl::DrawWrapMarker(PRectangle rcPlace, bool isEndMarker, ColourRGBA wrapColour) { - wattr_set(win, 0, Colors::Pair(wrapColour, Colors::Black), nullptr); + const ColourRGBA &back = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; + attr_t attrs = 0; + short pair = Colors::Pair(attrs, wrapColour, back); + wattr_set(win, attrs, pair, nullptr); mvwaddstr( win, static_cast(rcPlace.top), static_cast(rcPlace.left), isEndMarker ? "↩" : "↪"); } // Draws the text representation of a tab arrow. void SurfaceImpl::DrawTabArrow(PRectangle rcTab, const ViewStyle &vsDraw) { - const ColourRGBA &fore = vsDraw.ElementColour(Element::WhiteSpace).value_or(Colors::Black); - const ColourRGBA &back = vsDraw.ElementColour(Element::WhiteSpaceBack).value_or(Colors::Black); - const attr_t attr = has_colors() || back.Opaque() == Colors::Black ? 0 : WA_REVERSE; - wattr_set(win, attr, Colors::Pair(fore, back), nullptr); + const ColourRGBA &c = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; + const ColourRGBA &fore = vsDraw.ElementColour(Element::WhiteSpace).value_or(c); + const ColourRGBA &back = vsDraw.ElementColour(Element::WhiteSpaceBack).value_or(c); + attr_t attr = 0; + short pair = Colors::Pair(attr, fore, back); + wattr_set(win, attr, pair, nullptr); for (int i = static_cast(std::max(rcTab.left - 1, clip.left)); i < rcTab.right; i++) mvwaddch(win, static_cast(rcTab.top), i, '-' | A_BOLD); char tail = vsDraw.tabDrawMode == TabDrawMode::LongArrow ? '>' : '-'; diff --git a/PlatCurses.h b/PlatCurses.h index a00d3e3..879850c 100644 --- a/PlatCurses.h +++ b/PlatCurses.h @@ -142,18 +142,19 @@ class Colors { std::map, short> pairs; // map of curses colors to their pair numbers int colorOffset = 0, pairOffset = 0; bool usePalette = true; + int defaultFore = -1, defaultBack = -1; Colors(); static Colors &instance(); - /** Returns the curses number for a Scintilla color, initializing it if necessary. */ - short get(const ColourRGBA &color); public: static ColourRGBA Black, Red, Green, Yellow, Blue, Magenta, Cyan, White; static ColourRGBA LBlack, LRed, LGreen, LYellow, LBlue, LMagenta, LCyan, LWhite; + /** Returns the curses number for a Scintilla color, initializing it if necessary. */ + static short get(const ColourRGBA &color); /** Returns the curses pair number for a Scintilla color pair, initializing it if necessary. */ - static short Pair(const ColourRGBA &fore, const ColourRGBA &back); + static short Pair(attr_t &attrs, const ColourRGBA &fore, const ColourRGBA &back); /** Returns the Scintilla color for a given curses color number. */ static ColourRGBA Find(const short color); @@ -161,6 +162,12 @@ class Colors { static void DisablePalette(); /** Sets the offsets for colors and color pairs generated on-demand. */ static void SetOffsets(int colorOffset, int pairOffset); + /** Sets the default foreground and background colors. */ + static void SetDefaultColors(int fore, int back); + /** Gets default foreground color as an integer RGB */ + static int GetDefaultFore(); + /** Gets default background color as an integer RGB */ + static int GetDefaultBack(); }; inline WINDOW *_WINDOW(WindowID wid) { return reinterpret_cast(wid); } diff --git a/ScintillaCurses.cxx b/ScintillaCurses.cxx index f892438..eaa1e16 100644 --- a/ScintillaCurses.cxx +++ b/ScintillaCurses.cxx @@ -266,14 +266,21 @@ void ScintillaCurses::SetVerticalScrollPos() { WINDOW *w = GetWINDOW(); int maxy = getmaxy(w), maxx = getmaxx(w); if (scrollBarHeight == maxy) return; // no point in drawing a non-scrollable bar yet + const ColourRGBA &fore = Colors::GetDefaultFore() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultFore()) : Colors::White; + const ColourRGBA &back = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; // Draw the gutter. - wattr_set(w, 0, Colors::Pair(Colors::White, Colors::Black), nullptr); + attr_t attrs = 0; + short pair = Colors::Pair(attrs, fore, back); + wattr_set(w, attrs, pair, nullptr); for (int i = 0; i < maxy; i++) mvwaddch(w, i, maxx - 1, ACS_CKBOARD); // Draw the bar. scrollBarVPos = static_cast(static_cast(topLine) / (MaxScrollPos() + LinesOnScreen() - 1) * maxy); - const attr_t attr = has_colors() ? 0 : WA_REVERSE; - wattr_set(w, attr, Colors::Pair(Colors::Black, Colors::White), nullptr); // invert + attrs = 0; + pair = Colors::Pair(attrs, back, fore); // invert + wattr_set(w, attrs, pair, nullptr); for (int i = scrollBarVPos; i < scrollBarVPos + scrollBarHeight; i++) mvwaddch(w, i, maxx - 1, ACS_VLINE); } @@ -283,13 +290,20 @@ void ScintillaCurses::SetHorizontalScrollPos() { WINDOW *w = GetWINDOW(); int maxy = getmaxy(w), maxx = getmaxx(w); if (scrollBarWidth == maxx) return; // no point in drawing a non-scrollable bar yet + const ColourRGBA &fore = Colors::GetDefaultFore() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultFore()) : Colors::White; + const ColourRGBA &back = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; // Draw the gutter. - wattr_set(w, 0, Colors::Pair(Colors::White, Colors::Black), nullptr); + attr_t attrs = 0; + short pair = Colors::Pair(attrs, fore, back); + wattr_set(w, attrs, pair, nullptr); for (int i = 0; i < maxx; i++) mvwaddch(w, maxy - 1, i, ACS_CKBOARD); // Draw the bar. scrollBarHPos = static_cast(static_cast(xOffset) / scrollWidth * maxx); - const attr_t attr = has_colors() ? 0 : WA_REVERSE; - wattr_set(w, attr, Colors::Pair(Colors::Black, Colors::White), nullptr); // invert + attrs = 0; + pair = Colors::Pair(attrs, back, fore); // invert + wattr_set(w, attrs, pair, nullptr); for (int i = scrollBarHPos; i < scrollBarHPos + scrollBarWidth; i++) mvwaddch(w, maxy - 1, i, ACS_HLINE); } @@ -404,7 +418,13 @@ void ScintillaCurses::CreateCallTipWindow(PRectangle rc) { surface->Init(wid); dynamic_cast(surface.get())->isCallTip = true; ct.PaintCT(surface.get()); - wattr_set(_WINDOW(wid), 0, Colors::Pair(Colors::White, Colors::Black), nullptr); + const ColourRGBA &fore = Colors::GetDefaultFore() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultFore()) : Colors::White; + const ColourRGBA &back = Colors::GetDefaultBack() >= 0 ? + ColourRGBA::FromRGB(Colors::GetDefaultBack()) : Colors::Black; + attr_t attrs = 0; + short pair = Colors::Pair(attrs, fore, back); + wattr_set(_WINDOW(wid), attrs, pair, nullptr); box(_WINDOW(wid), '|', '-'); wnoutrefresh(_WINDOW(wid)); } @@ -704,4 +724,8 @@ void scintilla_disable_color_palette() { Scintilla::Internal::Colors::DisablePal void scintilla_set_color_offsets(int color_offset, int pair_offset) { Scintilla::Internal::Colors::SetOffsets(color_offset, pair_offset); } + +void scintilla_set_default_colors(int fg, int bg) { + Scintilla::Internal::Colors::SetDefaultColors(fg, bg); +} } diff --git a/ScintillaCurses.h b/ScintillaCurses.h index 98a38c2..4ab9f62 100644 --- a/ScintillaCurses.h +++ b/ScintillaCurses.h @@ -130,6 +130,17 @@ void scintilla_disable_color_palette(void); */ void scintilla_set_color_offsets(int color_offset, int pair_offset); +/** + * Configure colors which will be mapped to the terminal's default colors + * when used as the given foreground or background color. + * Default colors might depend on the emulator's color scheme. + * This might not be supported in all curses implementations. + * Use -1 to disable a default foreground or background color. + * You must still call first `start_color()`, then `use_default_colors()` + * or `assume_default_colors()` for this to work. + */ +void scintilla_set_default_colors(int fg, int bg); + #define IMAGE_MAX 31 #define SCM_PRESS 1 diff --git a/docs/scinterm.luadoc b/docs/scinterm.luadoc index b7cb1a1..1710a54 100644 --- a/docs/scinterm.luadoc +++ b/docs/scinterm.luadoc @@ -98,3 +98,13 @@ -- @param color_offset The offset for Scinterm's calls to `init_color()`. -- @param pair_offset The offset for Scinterm's calls to `init_pair()`. -- @function scintilla_set_color_offsets + +--- Configure colors which will be mapped to the terminal's default colors +-- when used as the given foreground or background color. +-- Default colors might depend on the emulator's color scheme. +-- This might not be supported in all curses implementations. +-- You must still call first `start_color()`, then `use_default_colors()` +-- or `assume_default_colors()` for this to work. +-- @param fg Foreground color in Scintilla's "0xBBGGRR" format or -1 to disable. +-- @param bg Background color in Scintilla's "0xBBGGRR" format or -1 to disable. +-- @function scintilla_set_default_colors