⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Conversation

@egmontkob
Copy link
Contributor

What would you guys think of a color handling refactoring along these lines?

The current code does the resolution from the role (e.g. "dialog's title color") to the ncurses/slang color pair id as soon as possible.

A significant drawback of this design is that initializing some color constant (e.g. the ones used for normal, error, listbox and help dialogs), or later adjusting these values upon a runtime skin change are pretty cumbersome. Either some locally used colors need to be defined in a much more global context (pointed out as unfortunate design twice during code review: #4916 (comment) and #4976 (comment)), or the code that switches the skin needs to dig deep down into the territory of individual widgets to change the color they use.

My idea is to instead carry the color role identifier for as long as possible, and only resolve to the actual color when it comes to painting. This way only the color cache needs to be updated from the new skin; widget's idea on which color (i.e. color role) to use remains the same.

We have those 80-ish uppercase variables like CORE_NORMAL_COLOR etc. Currently it's pretty counterintuitive that despite the uppercase naming, these are variables and do change at a skin change. Yet, for some reason, they aren't declared as individual variables but as members of an array, so we have to maintain their indexing and manually renumber every time a new item is added.

With my suggestion, these become constants (actually enum values) as their name suggests, and we no longer have to manually index them.

Now, due to having two places in mc that bypass these variables, namely file highligthing and editor syntax highlighting, the story becomes a bit more complex. Sometimes we know the color role id, yet to be resolved to an ncurses/slang color pair id, but sometimes the latter one is the only thing we have.

Might not be the cleanest design per se, but I just distinguish these two based on how large the value is: if the value is low then it refers directly to the ncurses/slang color pair id; if the value is large (above the arbitrarily picked 4096) then it's a color role id which still needs a hop to resolve. This sort of pattern already exists in mc's file highlighting code where negative vs. positive values have different roles, although it looks to me it's legacy leftover because both are just color pair id, the negative ones will simply be flipped to positive (and, by the way, due to two faulty ret > 0 checks rather than ret >= 0, color pair id 0 (i.e. the terminal's default colors) can't be used for file highlighting; something that probably nobody cares about). I've ported this negative vs. positive split to the new ranges.

No more conceptual tty_setcolor() vs. tty_lowlevel_setcolor() separation (although it was probably a legacy anyway, they were identical, except for a & 0x7F mask in slang that I don't understand), now by design there's a single method only which decides based on the value (small vs. large) how to handle it.

As you can see, the initialization of command_colors etc. becomes compile-time rather than runtime, no need to reinitialize at skin change, and easy to move all of them where they really belong.

I've moved CORE_NORMAL_COLOR etc. from the upper level skin layer to the lower level tty layer because tty_setcolor() now needs to know about them, and I didn't want tty to know about skin. This is debatable where it should really go, what the new variables / types / etc. should be named, and so on, suggestions welcome.

Let me know please how you like the overall direction.

@egmontkob egmontkob requested review from mc-worker and zyv February 5, 2026 16:53
@github-actions github-actions bot added needs triage Needs triage by maintainers prio: medium Has the potential to affect progress labels Feb 5, 2026
@github-actions github-actions bot added this to the Future Releases milestone Feb 5, 2026
@egmontkob egmontkob force-pushed the color-handling-refactor branch 2 times, most recently from 85b624c to ac6cacb Compare February 5, 2026 17:19
Copy link
Member

@zyv zyv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had a look at it, and mechanically your rework definitively seems like a much better way to achieve the same goal. My understanding of the whole system, however, is so limited that I can't judge if this approach introduces some new problems or not, and if there is an even better way to do it. I'm sorry, but I would like to defer to Andrew on this...

Copy link
Contributor

@mc-worker mc-worker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Thank you very much!

/*
* Helper for mc_skin_color_cache_init ()
*/
static void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

/* --------------------------------------------------------------------------------------------- */

int
tty_maybe_map_color (int color)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move it to color-internal.[ch].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously, that's a much better place. I didn't realize we had such a file :) Done.

{
if (color >= COLOR_MAP_OFFSET)
return tty_color_role_to_pair[color - COLOR_MAP_OFFSET];
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else after return is unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@mc-worker mc-worker mentioned this pull request Feb 7, 2026
5 tasks
…dget

Signed-off-by: Egmont Koblinger <egmont@gmail.com>
Variables referring to a color pair may now contain either the lowlevel color
pair id, or an identifier of the color role, the latter to be looked up in a
map according to the skin.

By using the color role id for as long as we can, rather than the resolved
color pair id, initializing colors and later changing skins becomes much more
straightforward.

Signed-off-by: Egmont Koblinger <egmont@gmail.com>
*/
#define COLOR_MAP_OFFSET 4096

enum
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the lib/tty layer should not know which basic widgets and "applications" (editor, viewer, ...) are implemented. Let's move color definitions and related macros back to lib/skin.

@zyv zyv added area: skin Theming support and skin files and removed needs triage Needs triage by maintainers labels Feb 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: skin Theming support and skin files prio: medium Has the potential to affect progress

Development

Successfully merging this pull request may close these issues.

3 participants