NCURSES - colors in pad - c

I am writing an application in ncurses and I am dealing with colour displaying in pads. I add some text into pad p with colour attribute on like this:
if(has_colors())
start_color();
init_pair(0, COLOR_GREEN, COLOR_BLACK);
attron(COLOR_PAIR(0));
while( (ch=fgetc(f)) != EOF){
waddch(p,ch);
}
attroff(COLOR_PAIR(0));
fclose(f);
But then when I display part of the tab with prefresh(p,0, 0, 0,0, LINES-1,COLS-1); the text is printed without any change. (only the background is a bit different because I started colour mode). I am afraid that when the text is copied from the pad to screen, it does not copy the formatting, is that right? If so, is there any way how to accomplish that?
Thanks!
|||-----EDIT------|||
So even when I cahnge the key to something different than zero, it doesn't work. I am printing into the pad with this:
init_pair(3,COLOR_RED,COLOR_CYAN);
attron(COLOR_PAIR(3));
for (i=0;i<str.length();i++){
waddch(p,str[i]);
}
attroff(COLOR_PAIR(3));
and the text after prefresh is displayed as normal.

Color pair 0 is special, because (referring to the manual page) it is always the default foreground and background colors:
Color pair 0 is assumed to be white on black, but is
actually whatever the terminal implements before color
is initialized. It cannot be modified by the application.
There are three components of color pairs which combine to form a cell's color (see manual page):
background character
window attribute set via wattron, etc.
video attributes (including COLOR_PAIR value) passed in the parameter to waddch.
The last two affect the result if a nonzero color-pair is passed; otherwise they do not (and the preceding item on the list is used). These are all window operations. The functions attron/attron apply to stdscr, not to the pad or window p. If those were changed to wattron(p,COLOR_PAIR(3));, etc., the result would be improved.

this excerpt from the man pages for ncurses indicates the problem is using color pair 0.
The init_pair routine changes the definition of a color-pair. It takes three arguments: the number of the color-pair to be changed, the foreground color number, and the background color number. For portable applications:
The value of the first argument must be between 1 and COLOR_PAIRS-1, except that if default colors are used (see use_default_colors) the upper limit is adjusted to allow for extra pairs which use a default color in foreground and/or background. " emphasis mine

Related

Is ncurses possible to change only foreground color?

Below code can change only attribute with leaving colors.
init_color(1, 255);
init_color(2, 1);
init_pair(1, 1, 2);
attron(COLOR_PAIR(1)); // only change the pair of foreground and background color
addstr("aaa");
attron(A_BOLD); // only change the attribute
addstr("aaa");
attrset(COLOR_PAIR(1)|A_BOLD); // change both
I want to know if we can change only foreground color, but leave background color.
attron_fg(BACKGROUND_YELLOW); // only change the foreground color
addstr("aaa");
No, you can't.
Ncurses is based on a model where each screen position has a colour pair. The possible colour pairs are in an indexed array, and it's the array index which ncurses stores in its screen representation. So you can only specify a colour pair.
Furthermore, since everything is based on indexed arrays, changing the definition of a colour or a colour pair will probably change the displayed colour of previously painted characters.
That model can be a bit annoying but its fundamental to the design of ncurses, so if you want to use ncurses, you need to adapt to the model.
Historically, there were hardware terminals based on the same model for essentially the same reason (limited memory). These days, such terminals are mostly confined to museums, but ncurses and the rest of the unix terminal handling infrastructure continues to cater to a world in which a diversity of external terminals each presented their own unique facilities and limitations.
These days, the same model is used to compensate for the differing implementations of terminal control sequences by a variety of different terminal emulators. But it also still works (or could work) with consoles connected to embedded devices.
That's an explanation, neither an excuse nor a justification.

Color one cell ncurses

I wonder, is that possible to kind of "bake" one cell color using ncurses?
I mean, i want to set one cell color and then, when i use mvprintw with some other color in attron() i want the cell to still be this "baked" color.
//default color
mvprintw(0, 0, my_game_board);
bake(2,4,cell_color);
mvprintw(0, 0, my_game_board); //update game board, and then ONLY 2,4 cell should be cell_color.
.
Its like i want to set color for cell, not for content. (when content change, color shoud be same)
Just using mvpwintw, etc., as illustrated, you cannot. That ultimately resolves into waddch calls (see source), which pay attention to
the window background (see bkgd),
the window attributes (see attr_on) and
the character attributes (see last paragraph in addch).
You could use the panel library to manage the unchanging cell as a separate layer (in its own window), but probably would find it too complicated to use for multiple unchanging cells.

Why we need add 1 to background brush color?

One of member of the WNDCLASS structure is handle to the class background brush.
From description:
This member can be a handle to the physical brush to be used for painting the background, or it can be a color value. A color value must be one of the following standard system colors (the value 1 must be added to the chosen color).
QUESTION:
Why must add 1 to this value?
It may be because the hbrBackground field accept NULL value.
It's for RegisterClass() function to make the difference between COLOR_SCROLLBAR which is 0 and NULL which is an acceptable value.
The hbrBackground member of the WNDCLASS structure has an overloaded meaning. It represents either one of:
A handle to a brush
A standard system color index
When using it to mean a brush handle, NULL (aka 0) is a valid value, meaning that erasing the background of a window is a no-op.
Unfortunately, 0 is also a valid system color index value (COLOR_SCROLLBAR). The consequence of this is that the ranges for the different meanings now overlap, and the system cannot disambiguate between them.
The solution is to offset one of those ranges so that they no longer overlap, and can be uniquely identified by the system. Adding 1 to the system color index does that, so that's why you have to add 1 when using a system color index.
Raymond Chen blogged about this a while ago: Why do I have to add one when setting a class background brush to a system color?

gtk label text center and wrap

I have been experiencing some really weird problems with gtk_label text positioning.
I have a gtk_label positioned on a fixed container, the label has been set to:
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
However when a single word is present in the label, instead of getting centered it gets left aligned.
If I unset gtk_label_set_line_wrap(GTK_LABEL(label), TRUE) to FALSE the word then appears in the center of the label, but I lose wrapping.
How should this be fixed?
From the documentation (emphasis mine):
gtk_label_set_justify ()
Sets the alignment of the lines in the text of the label relative to each other. GTK_JUSTIFY_LEFT is the default value when the widget is first created with gtk_label_new(). If you instead want to set the alignment of the label as a whole, use gtk_misc_set_alignment() instead. gtk_label_set_justify() has no effect on labels containing only a single line.
As suggested in the above quote, you may wish to add a call to the gtk_misc_set_alignment() function, with its xalign parameter set to 0.5, before calling gtk_label_set_justify().

Resizing Labels

I have a chart in WPF with a lot of labels. The text on these labels is dynamically loaded and subject to change. If I set the width just to auto, then these labels may overlap, which makes the text unreadable.
The chart support multiple sizes, so if it gets larger, then the bars are re sized and there is more space for text. Now I want to adjust the text to the space which is available. If it gets too small, I don't want to display the label anymore (a tooltip is available, so the user still gets the required information). Consider the string "Case 1, blah blah", there is probably not enough space to display the whole string, but just the first word. In this case I want the string to be "Case 1..", with .. indicating that there is some more information in the tooltip.
I can determine the length available for the string. But how can I determine the space a single letter will take? Of course I could also just re size the label, but then it would just cut off the string anywhere which is probably not helpful for the user (and looks ugly).
Any ideas?
If you can use TextBlocks instead of labels then they have a TextTrimming property which will do this for you to either the nearest character or the nearest word.
While you seem happy with the TextTrimming property, I'll edit this to add that the TextBox control has a GetRectFromCharacterIndex method that would allow you to find out the size on screen of one or more characters as long as the font settings matched your label. This might be useful if you wanted to trim at specific places in the label rather than the nearest character / word.
Not an expert in WPF, but I would think that you'll need to do this in code rather than XAML.
Start by obtaining the actual pixel width of the space available for the text.
Then look at the character set, dot pitch etc. utilised on the XAML front end and from there calculate the pixel width required per character.
You could also look at changing the character sizes as well as reducing the label length.

Resources