curses and colors

Pages: 12
I've been playing with the CURSES library pdcurses to be exact and C++. Although I am trying to write a function that will evaluate everything that is to be printed to the screen, scan it for any COLOR codes, apply that color and print it on the screen. I've been successful although I've added a step and I can't get it to work properly. Here's the code so far.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <curses.h>

void send_out( WINDOW *win, char *fmt, ...)
{
    short int clr_text, clr_bgk;
    char InStr[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(InStr, fmt, args);
    va_end(args);
    int x, y = 0;
    char OutStr[1024];
    bool found;

    pair_content( 1, &clr_text, &clr_bgk );

    if ( win == NULL )
      win = stdscr;

     for ( x = 0; x <= 1024; x++ )
     {
         if ( InStr[x] == '\0' )
         {
              OutStr[y] = '\0';
              wprintw( win, OutStr );
              break;
         }
         else if ( InStr[x] != '&' )
         {
             OutStr[y] = InStr[x];
             ++y;
         }
         else if ( InStr[x] == '&' )
         {
              OutStr[y] = '\0';
              wprintw( win, OutStr );
              y = 0;
              ++x;
              if ( InStr[x] == 'C' )
              {
                  found = true;
                  clr_text = COLOR_CYAN;
              }
              if ( InStr[x] == 'K' )
              {
                  found = true;
                  clr_text = COLOR_BLACK;
              }
              if ( found )
              {
                init_pair( 1, clr_text, clr_bgk );
                wattrset( win, COLOR_PAIR(1) );
              }
         }
     }
}


int main()
{
	initscr();			/* Start curses mode 		  */
	start_color();
	refresh();

    init_pair(1, COLOR_GREEN, COLOR_WHITE );
    bkgd( COLOR_PAIR(1) ); // Green Text on a White Screen

    send_out( stdscr, "This text should be GREEN on a WHITE screen.\n\n" );
    refresh();

    send_out( stdscr, "&KThis text should be BLACK on a WHITE screen.\n\n" );
    refresh();

    send_out( stdscr, "&CThis text should be CYAN on a WHITE screen.\n\n" );
    refresh();

    send_out( stdscr, "&CCyan &KBlack &CDifferent &KColors.\n\n" );
    refresh();

	getch();
	endwin();

	return 0;
}


All text ends up being whatever color I choose last. In this case &C (Cyan). The good thing about the function is that in can process and print an entire string of colors in a single input.

The problem I am running into is that they all will use COLOR_PAIR(1). I'm not sure how to go about fixing this problem. I need this function to be able to interpret the current color of the text AND the background -

i.e. If the text was currently RED text on a BLUE background, I want to be able to freely change the RED text to another color, but keep the BLUE background through this function. Any ideas?
Last edited on
Interesting idea. Perhaps I'll post mine shortly... :-)


You are correct: the problem is that you keep changing COLOR_PAIR(1) -- don't do that. When you wrefresh(), all instances of that color pair will be changed to reflect the new colors. That is to say, each character in the window has associated with it a specific color pair. Change the definition of the color pair and all associated characters will change color.

Perhaps your application can parse "&1" as color pair 1, "&2" as color pair 2, etc.
Then all you have to do is initialize the color pairs at startup. You cannot expect to be able to use every combination possible at once, so your initialization should be careful to set up for the colors your application needs.

There is one other caveat: the actual "brightness" of the foreground and background colors is dependant on the A_BOLD and A_BLINK attributes, respectively. However, they are added outside the COLOR_PAIR(n) selector. Make sure to give http://linux.die.net/man/3/init_color a careful read. Also, don't forget that you actually need to turn attributes on before using them. (See [w]attron() below.) On PDCurses it doesn't make much difference, but in NCurses it makes a great deal of difference.

Here is your code modified to do what you wanted...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <curses.h>
#include <cstdarg>
using namespace std;

void send_out( WINDOW *win, const char *fmt, ...)
{
    char InStr[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(InStr, fmt, args);
    va_end(args);
    int x, y = 0;
    char OutStr[1024];

    if ( win == NULL )
      win = stdscr;

     for ( x = 0; x <= 1024; x++ )
     {
         if ( InStr[x] == '\0' )
         {
              OutStr[y] = '\0';
              wprintw( win, OutStr );
              break;
         }
         else if ( InStr[x] != '&' )
         {
             OutStr[y] = InStr[x];
             ++y;
         }
         else if ( InStr[x] == '&' )
         {
              OutStr[y] = '\0';
              wprintw( win, OutStr );
              y = 0;
              ++x;
              if ( InStr[x] == 'C' )
              {
                  wattron( win, COLOR_PAIR(3) | A_BLINK );
                  wattrset( win, COLOR_PAIR(3) | A_BLINK );
              }
              if ( InStr[x] == 'K' )
              {
                  wattron( win, COLOR_PAIR(2) | A_BLINK );
                  wattrset( win, COLOR_PAIR(2) | A_BLINK );
              }
         }
     }
}


int main()
{
    initscr();
    start_color();

    init_pair(1, COLOR_GREEN, COLOR_WHITE );
    init_pair(2, COLOR_BLACK, COLOR_WHITE );
    init_pair(3, COLOR_CYAN,  COLOR_WHITE );

    attron( COLOR_PAIR(1) | A_BLINK );
    bkgd(   COLOR_PAIR(1) | A_BLINK ); // Green Text on a White Screen

    send_out( stdscr, "This text should be GREEN on a WHITE screen.\n\n" );
    send_out( stdscr, "&KThis text should be BLACK on a WHITE screen.\n\n" );
    send_out( stdscr, "&CThis text should be CYAN on a WHITE screen.\n\n" );
    send_out( stdscr, "&CCyan &KBlack &CDifferent &KColors.\n\n" );

    refresh();

    getch();
    endwin();

    return 0;
}

BTW, I haven't fixed all problems with the code... I only made it do what you wanted... (sort of)

Hmm... that ought to do it. Hope this helps.
Last edited on
As Duoas pointed out, the problem is that you are only using one COLOR_PAIR index. If you change it, then anything previously written with that color index will change to the new colors. There are 256 indices. One possibility is to initialize the COLOR_PAIRs to all possible color combinations in some logical way, the simplest being:

1
2
3
4
5
6
void init_color_pairs() {
    short f, b;
    for( f = 0; f < COLORS; ++f )
        for( b = 0; b < COLORS; ++b )
            init_pair( f * COLORS + b, f, b );
}

Then you can access COLOR_PAIR like a pseudo-2D array:

 
COLOR_PAIR( f * COLORS + b );


And OutStr is not necessary. Instead, output the string char by char. That will simplify things a little.

With the above in mind, here's a quick rewrite of your code (no promises that it is not buggy!):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <curses.h>
#include <stdio.h>

void send_out( WINDOW *win, char *fmt, ... )
{
    short color_pair, fore, back;
    char InStr[1024];
    int x;
    va_list args;

    va_start( args, fmt );
    vsprintf( InStr, fmt, args );
    va_end( args );

    if( ! win ) win = stdscr;

    // Get current colors
    wattr_get( win, 0, &color_pair, 0 );
    pair_content( color_pair, &fore, &back );

    for ( x = 0; x < 1024; x++ )
    {
        switch( InStr[x] ) {
        case '\0':
            return;
        case '&':  // To set foreground color
        case '^':  // To set background color
            {
            char mode = InStr[x];

            switch( InStr[++x] ) {
            case '\0':
                addch( mode );
                return;
            case 'C':
                if( mode == '&' )  fore = COLOR_CYAN;
                else               back = COLOR_CYAN;
                break;
            case 'K':
                if( mode == '&' )  fore = COLOR_BLACK;
                else               back = COLOR_BLACK;
                break;
            default:
                addch( InStr[x] );
            }

            wattrset( win, COLOR_PAIR( fore * COLORS + back ) );
            }
            break;
        default:
            addch( InStr[x] );
        }
    }
}

void init_color_pairs() {
    short f, b;
    for( f = 0; f < COLORS; ++f )
        for( b = 0; b < COLORS; ++b )
            init_pair( f * COLORS + b, f, b );
}

int main( int argc, char *argv[] )
{
    initscr();
    start_color();
    init_color_pairs();
    assume_default_colors( COLOR_GREEN, COLOR_WHITE );
    printw( "Hello, World!\n" );
    send_out( stdscr, "&KWhat's &C^Kup?" );

    getch();
    endwin();
}

There are 256 indices.

It is unlikely that there are that many... You need to check the COLOR_PAIRS value to see how many color pairs you have to work with. Also, COLOR_PAIR(0) is not typically modifiable -- which is fine, you don't need it.

Personally, I think the curses way of doing colors is really stupid, but there are hysterical raisons that lead to it...

Here's a little C program to display all the color combinations you can get (see caveats following):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <curses.h>

int main()
  {
  int f, b, i;

  initscr();
  start_color();

  for (f = 0; f < 16; f++)
    {
    for (b = 0; b < 16; b++)
      {
      i = ((b %8) *8) +(f %8);
      init_pair( i, f %8, b %8 );
      attrset(
        COLOR_PAIR( i )
        | ((f < 8) ? 0 : A_BOLD)
        | ((b < 8) ? 0 : A_BLINK)
        );
      printw( " A " );
      }
    attrset( COLOR_PAIR( 0 ) );
    printw( "\n" );
    }

  printw( "There are %d colors and %d pairs available.\nPress ENTER...",
    COLORS,
    COLOR_PAIRS
    );
  refresh();

  getch();
  endwin();
  return 0;
  }

This code assumes that there are 64 pairs available...

Notice that there are four times as many color combinations as there are pairs available...

One significant note: some effort must often be exerted in *nix to get the terminal/emulator to use high-intensity background colors instead of causing the text to blink. Whether or not you can get high-intensity colors at all (either foreground or background) is entirely dependant on your user's terminal capabilities and setup.

Win32 uses high-intensity colors by default in the Windows Console when windowed -- but not always when switching to full-screen mode (which can't be done in Vista anyway...).

So no matter what you do -- using colors is something of a gamble. Make sure you provide your users some form of option to control what colors are available... Also, it is fair to assume that people are still using terminals that don't support color. Yep... they've only got black and white, with reverse video and bold text attributes. Your program should ideally be able to run under those circumstances too -- unless color is essential and you can tell such users to move into the modern age.

Hope this helps.
Last edited on

> There are 256 indices
It is unlikely that there are that many

It does seem excessive, but that's the value of COLOR_PAIRS on my system. However, as usual I was forgetting all about portability. :(
yea, 256 indices. The functions worked well and showed me what I needed thanks. I used Hammurabi's function and it works as is, although when I change the assume_default_colors line to use bkgd( ); function or even attrset(); function, it doesn't seem to work any longer.

The reason for not using assume_default_colors function is there is no room to allow for the bitwise operator attribute. A_BOLD, or A_BLINK. Which is a whole nother story of trying to determine if the A_BOLD is active or not. I can safely determine which colors are being used and modify them as-is with the help of Hammurabi's code (only when I set the default color), although I can't find a way to determine which attributes are active, A_BOLD, A_BLINK, (which requires the use of bkgd)

I'm at a loss as to why this line of code no longer works

1
2
3
    // Get current colors
    wattr_get( win, 0, &color_pair, 0 );
    pair_content( color_pair, &fore, &back );


When I simply change this line

1
2
3
4
5
6
7
8
9
10
11
12
13
int main( int argc, char *argv[] )
{
    initscr();
    start_color();
    init_color_pairs();
    // assume_default_colors( COLOR_GREEN, COLOR_WHITE );
    bkgd( COLOR_PAIR(43) | A_BLINK );
    printw( "Hello, World!\n" );
    send_out( stdscr, "&KWhat's &C^Kup?" );

    getch();
    endwin();
}


Any more suggestions on determining if the attributes are active or not
Last edited on
I just spent the afternoon upgrading my Kubuntu from 7.10 to 9.04... and I still can't get high-intensity background colors on the console. But at least the annoying blinking is gone.

dmoore210
I haven't tried it, but it looks like you are trying to take too many shortcuts. Did you check the return value of the function to see if OK or ERR?
Well this a project at work so i don't need this to be portable and this can be very specific to the console I am going to be running it on, and I've finally got it solved. I ultimately had to declare a global stuct to retain all the values, foreground color, background color, if it's A_BOLD and A_BLINK. I didn't save any other attributes because I won't be using them that often and that can be modified manually if need be, but this is all I need. Here's the finished code of what I got to work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <curses.h>

struct COLOR_DATA {
    int pair;
    int fore;
    int back;
    bool bold;
    bool blink;
} COLOR;

void send_out3( WINDOW *win, char *fmt, ...)
{
    char InStr[1024];
    int x, i;
    va_list args;

    va_start( args, fmt );
    vsprintf( InStr, fmt, args );
    va_end( args );

    if( ! win ) win = stdscr;

    for ( x = 0; x < 1024; x++ )
    {
      if ( InStr[x] == '\0' )
        break;
      else if ( InStr[x] == '&' ) // Change the Foreground Color
      {
        ++x;
        if( InStr[x] == 'C' ) { COLOR.fore = COLOR_CYAN; COLOR.bold = true; }
        if( InStr[x] == 'Y' ) { COLOR.fore = COLOR_YELLOW; COLOR.bold = true; }
        if( InStr[x] == 'G' ) { COLOR.fore = COLOR_GREEN; COLOR.bold = true; }
        if( InStr[x] == 'R' ) { COLOR.fore = COLOR_RED; COLOR.bold = true; }
        if( InStr[x] == 'B' ) { COLOR.fore = COLOR_BLUE; COLOR.bold = true; }
        if( InStr[x] == 'W' ) { COLOR.fore = COLOR_WHITE; COLOR.bold = true; }
        if( InStr[x] == 'K' ) { COLOR.fore = COLOR_BLACK; COLOR.bold = true; }
        if( InStr[x] == 'P' ) { COLOR.fore = COLOR_MAGENTA; COLOR.bold = true; }
        if( InStr[x] == 'c' ) { COLOR.fore = COLOR_CYAN; COLOR.bold = false; }
        if( InStr[x] == 'y' ) { COLOR.fore = COLOR_YELLOW; COLOR.bold = false; }
        if( InStr[x] == 'g' ) { COLOR.fore = COLOR_GREEN; COLOR.bold = false; }
        if( InStr[x] == 'r' ) { COLOR.fore = COLOR_RED; COLOR.bold = false; }
        if( InStr[x] == 'b' ) { COLOR.fore = COLOR_BLUE; COLOR.bold = false; }
        if( InStr[x] == 'w' ) { COLOR.fore = COLOR_WHITE; COLOR.bold = false; }
        if( InStr[x] == 'k' ) { COLOR.fore = COLOR_BLACK; COLOR.bold = false; }
        if( InStr[x] == 'p' ) { COLOR.fore = COLOR_MAGENTA; COLOR.bold = false; }

        i = ((COLOR.back %8) *8) +(COLOR.fore %8);
        wattrset( win, COLOR_PAIR(i) | (COLOR.bold ? A_BOLD : 0) | (COLOR.blink ? A_BLINK : 0) );
      }
      else if ( InStr[x] == '^' ) // Background Color
      {
        ++x;
        if( InStr[x] == 'C' ) { COLOR.back = COLOR_CYAN; COLOR.blink = true; }
        if( InStr[x] == 'Y' ) { COLOR.back = COLOR_YELLOW; COLOR.blink = true; }
        if( InStr[x] == 'G' ) { COLOR.back = COLOR_GREEN; COLOR.blink = true; }
        if( InStr[x] == 'R' ) { COLOR.back = COLOR_RED; COLOR.blink = true; }
        if( InStr[x] == 'B' ) { COLOR.back = COLOR_BLUE; COLOR.blink = true; }
        if( InStr[x] == 'W' ) { COLOR.back = COLOR_WHITE; COLOR.blink = true; }
        if( InStr[x] == 'K' ) { COLOR.back = COLOR_BLACK; COLOR.blink = true; }
        if( InStr[x] == 'P' ) { COLOR.back = COLOR_MAGENTA; COLOR.blink = true; }
        if( InStr[x] == 'c' ) { COLOR.back = COLOR_CYAN; COLOR.blink = false; }
        if( InStr[x] == 'y' ) { COLOR.back = COLOR_YELLOW; COLOR.blink = false; }
        if( InStr[x] == 'g' ) { COLOR.back = COLOR_GREEN; COLOR.blink = false; }
        if( InStr[x] == 'r' ) { COLOR.back = COLOR_RED; COLOR.blink = false; }
        if( InStr[x] == 'b' ) { COLOR.back = COLOR_BLUE; COLOR.blink = false; }
        if( InStr[x] == 'w' ) { COLOR.back = COLOR_WHITE; COLOR.blink = false; }
        if( InStr[x] == 'k' ) { COLOR.back = COLOR_BLACK; COLOR.blink = false; }
        if( InStr[x] == 'p' ) { COLOR.back = COLOR_MAGENTA; COLOR.blink = false; }

        i = ((COLOR.back %8) *8) +(COLOR.fore %8);
        wattrset( win, COLOR_PAIR(i) | (COLOR.bold ? A_BOLD : 0) | (COLOR.blink ? A_BLINK : 0) );
      }
      else
        addch( InStr[x] );
    }
}


void init_color_pairs() 
{
    int f, b, i;

    for (f = 0; f < 16; f++)
      for (b = 0; b < 16; b++)
      {
        i = ((b %8) *8) +(f %8);
        init_pair( i, f %8, b %8 ); // Initialize all of the possible color combo's
      }

}
/* This is so we can determine what we are starting with. Save all values to
    the global COLOR struct and work from there */
void my_bkgd( short int f, short int b, bool BOLD, bool BLINK )
{
    int i;

    COLOR.fore = f;
    COLOR.back = b;
    COLOR.bold = BOLD;
    COLOR.blink = BLINK;

    i = ((b %8) *8) +(f %8);
    bkgd( COLOR_PAIR(i) | (BOLD ? A_BOLD : 0) | (BLINK ? A_BLINK : 0) );

}

int main( int argc, char *argv[] )
{
    initscr();
    start_color();
    init_color_pairs();

    my_bkgd( COLOR_WHITE, COLOR_RED, true, false );

    send_out3( stdscr, "Hello, World!\n\n" );
    send_out3( stdscr, "&RRED &BBLUE &GGREEN &PPURPLE &WWHITE &KBLACK &YYELLOW &CCYAN\n" );
    send_out3( stdscr, "&rRED &bBLUE &gGREEN &pPURPLE &wWHITE &kBLACK &yYELLOW &cCYAN\n\n" );
    send_out3( stdscr, "^K&CThis is a test ^W&kOf the different ^b&BColor Combinations.\n\n" );
    send_out3( stdscr, "^r&WBack to Normal.\n" );

    getch();
    endwin();
}


Many thanks to both Duoas and Hammurabi, couldn't have gotten this far without the help of your code -- Mostly the initialization of all the colors using '%' operator.
Yes, but wattr_get() takes an attr_t to get the A_BOLD and A_BLINK attributes.

In any case, glad to have been of help.
I was putting the final touches on the program (I was adding the functionality to set these colors independent per window, rather then global settings of colors, individual windows colors. Like wbkgd(); So I went into curses.h and located the WINDOW stuct, added the int fore, and int background, and bool bold and bool blink, although when I start the program it runs -ok- with some strange characters and crashes when i try to close the program out. Did I miss something?
ok, so everything works. just the last problem. How do you turn OFF A_BLINK and A_BOLD if you've set it through the bkgd function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <curses.h>

int main( )
{
    initscr();
    start_color();
    init_pair( 1, COLOR_WHITE, COLOR_RED );
    bkgd( COLOR_PAIR(1) | A_BLINK | A_BOLD );

    printw( "Bright Colors On\n\n" );
    attroff( A_BLINK | A_BOLD);
    standend( );
    attrset( COLOR_PAIR(1) );
    printw( "Bright Colors Off.\n\n" );

    refresh();
    getch();
    endwin();
}


I am using bkgd because it colors in the entire window with the background color of my choosing, the only problem, I cannot find a way to turn off the A_BLINK attribute!
attroff()

Be sure to use the man pages liberally
http://linux.die.net/man/3/attroff
http://www.manpagez.com/man/3/attroff/

Good job!
Thanks for the reply! In the last example I actually tried attroff -- Doesn't doesn't to work when you use bkgd (which I have to use to get the entire window to change color).

I don't think what I'm trying to do is possible without having to rewrite parts of the curses program which I don't have the experience for.

Thanks for the help though
Alas, I haven't messed with bkgd() enough to know the answer... sorry.
I just wanted to say that this thread's title sounds like something Robin could say. "Curses and colors, Batman!"

Sorry, got nothing useful to add. Carry on.
Last edited on
In my original code, "bold" (or bright?) is all indices > 8. Below is some code that sets the brightness with respect to char case. I've modeled the interface after curses, so there's conout (console output that doesn't need a window arg) and wconout (which takes a window arg).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const char SET_BACK = '&';
const char SET_FORE = '^';
const int MAX_STRING = 1024;

void wsconout( WINDOW* win, char* strIn )
{
    short color_pair, fore, back;
    char* str;

    // Get current colors
    wattr_get( win, 0, &color_pair, 0 );
    pair_content( color_pair, &fore, &back );

    for ( str = strIn; str - strIn < MAX_STRING; ++str )
    {
        switch( *str ) {
        default: // Output all unrecognized chars literally
            waddch( win, *str );
            break;
        case '\0': // End-of-string, done
            return;
        case SET_BACK:
        case SET_FORE:
            {
            char mode = *str++;
            short newColor;

            switch( toupper( *str )) {
            case 'C': newColor = COLOR_CYAN;    break;
            case 'Y': newColor = COLOR_YELLOW;  break;
            case 'G': newColor = COLOR_GREEN;   break;
            case 'R': newColor = COLOR_RED;     break;
            case 'B': newColor = COLOR_BLUE;    break;
            case 'W': newColor = COLOR_WHITE;   break;
            case 'K': newColor = COLOR_BLACK;   break;
            case 'P': newColor = COLOR_MAGENTA; break;
            case '\0': // Output lone mode char if end-of-string
                waddch( win, mode );
                return;
            default: // Print something we don't recognize literally
                waddch( win, mode );
                // Just print one mode char for two in a row
                if( *str != mode ) waddch( win, *str );
                goto SkipIt; // two-level break
            }

            newColor += isupper( *str ) ? 8 : 0; // Set brightness
            if( mode == SET_BACK ) back = newColor;
            else                   fore = newColor;

            wattrset( win, COLOR_PAIR( fore * COLORS + back ));
            }
SkipIt:     ;
            break;
        }
    }
}

void wvconout( WINDOW* win, char* fmt, va_list args )
{
    char str[MAX_STRING];
    vsprintf( str, fmt, args );
    wsconout( win, str );
}

void conout( char *fmt, ... )
{
    va_list args;
    va_start( args, fmt );
    wvconout( stdscr, fmt, args );
    va_end( args );
}

void wconout( WINDOW* win, char* fmt, ... )
{
    va_list args;
    va_start( args, fmt );
    wvconout( win, fmt, args );
    va_end( args );
}

void init_color_pairs() {
    short f, b;
    for( f = 0; f < COLORS; ++f )
        for( b = 0; b < COLORS; ++b )
            init_pair( f * COLORS + b, f, b );
}

int main( int argc, char *argv[] )
{
    initscr();
    start_color();
    init_color_pairs();
    bkgd( COLOR_PAIR( (COLOR_YELLOW + 8) * COLORS + COLOR_BLACK ));
    conout( "Hello world\n" );
    conout( "&k^wHello, &B^WWorld!\n" );
    conout( "&k^cW^Ch^ya^Yt'^gs ^Gu^rp^R?\n" );
    conout( "&k^BCOLORS: %d   \n&b^RCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS );
    getch();
    endwin();
}

Last edited on
Very nice code, looks a bit more neat and compact then my own. kudos on that

Unfortunately, I've discovered that it's inherent with curses the way it executes the bkgd(); command. Although I have looked over that part of the code and didn't see where I could improve it.

Either way, if you change just the main function in your code, you'll see what I mean.

1
2
3
4
5
6
7
8
9
10
11
12
int main( int argc, char *argv[] )
{
    initscr();
    start_color();
    init_color_pairs();
    bkgd( COLOR_PAIR( (COLOR_YELLOW + 8) * COLORS + COLOR_BLACK ) | A_BLINK | A_BOLD );
    conout( "Hello World\n" );
    conout( "^G&KBright Green On Bright Black\n" );
    conout( "^g&kDark Green on Dark Black\n" );
    getch();
    endwin();
}


If you set an "A_BOLD" and/or "A_BLINK" attribute to the bkgd, they can not be turned off without changing the entire background -- which defeats the purpose of the command we're trying to make. So the end result is -- if you want a solid background color with an A_BLINK attribute on it, you won't be able to have text without it having the A_BLINK attribute on it.
I don't suppose anyone ever figured on someone using A_BLINK or A_BOLD in the background attribute... It does seam a bit odd to me.

But then... I'm not everyone... (-:
I don't understand why you are using A_BLINK and A_BOLD. What is the purpose of that?
Well the A_BOLD was just to demonstrate it couldn't be turned off. The A_BLINK is to make the console's background the bright color. For example...

1
2
init_pair(1, COLOR_BLACK, COLOR_WHITE );
bkgd( COLOR_PAIR(1) );


Will give (on Windows Console's -- which is what the only use of this program will be) a gray background. A 'non bright version of COLOR_WHITE'

1
2
init_pair(2, COLOR_BLACK, COLOR_WHITE );
bkgd( COLOR_PAIR(2) | A_BLINK);


This will allow the background of the entire console screen to be a bright white.

That's the only reason why I was trying to determine if there was a way to turn it off, since I wanted the entire background a bright white, but allow for some dim backgrounds to be used as accent's in value's.
Pages: 12