Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* PDCurses */
  2.  
  3. #include <curspriv.h>
  4.  
  5. /*man-start**************************************************************
  6.  
  7. color
  8. -----
  9.  
  10. ### Synopsis
  11.  
  12.     bool has_colors(void);
  13.     int start_color(void);
  14.     int init_pair(short pair, short fg, short bg);
  15.     int pair_content(short pair, short *fg, short *bg);
  16.     bool can_change_color(void);
  17.     int init_color(short color, short red, short green, short blue);
  18.     int color_content(short color, short *red, short *green, short *blue);
  19.  
  20.     int alloc_pair(int fg, int bg);
  21.     int assume_default_colors(int f, int b);
  22.     int find_pair(int fg, int bg);
  23.     int free_pair(int pair);
  24.     int use_default_colors(void);
  25.  
  26.     int PDC_set_line_color(short color);
  27.  
  28. ### Description
  29.  
  30.    To use these routines, first, call start_color(). Colors are always
  31.    used in pairs, referred to as color-pairs. A color-pair is created by
  32.    init_pair(), and consists of a foreground color and a background
  33.    color. After initialization, COLOR_PAIR(n) can be used like any other
  34.    video attribute.
  35.  
  36.    has_colors() reports whether the terminal supports color.
  37.  
  38.    start_color() initializes eight basic colors (black, red, green,
  39.    yellow, blue, magenta, cyan, and white), and two global variables:
  40.    COLORS and COLOR_PAIRS (respectively defining the maximum number of
  41.    colors and color-pairs the terminal is capable of displaying).
  42.  
  43.    init_pair() changes the definition of a color-pair. It takes three
  44.    arguments: the number of the color-pair to be redefined, and the new
  45.    values of the foreground and background colors. The pair number must
  46.    be between 0 and COLOR_PAIRS - 1, inclusive. The foreground and
  47.    background must be between 0 and COLORS - 1, inclusive. If the color
  48.    pair was previously initialized, the screen is refreshed, and all
  49.    occurrences of that color-pair are changed to the new definition.
  50.  
  51.    pair_content() is used to determine what the colors of a given color-
  52.    pair consist of.
  53.  
  54.    can_change_color() indicates if the terminal has the capability to
  55.    change the definition of its colors.
  56.  
  57.    init_color() is used to redefine a color, if possible. Each of the
  58.    components -- red, green, and blue -- is specified in a range from 0
  59.    to 1000, inclusive.
  60.  
  61.    color_content() reports the current definition of a color in the same
  62.    format as used by init_color().
  63.  
  64.    assume_default_colors() and use_default_colors() emulate the ncurses
  65.    extensions of the same names. assume_default_colors(f, b) is
  66.    essentially the same as init_pair(0, f, b) (which isn't allowed); it
  67.    redefines the default colors. use_default_colors() allows the use of
  68.    -1 as a foreground or background color with init_pair(), and calls
  69.    assume_default_colors(-1, -1); -1 represents the foreground or
  70.    background color that the terminal had at startup. If the environment
  71.    variable PDC_ORIGINAL_COLORS is set at the time start_color() is
  72.    called, that's equivalent to calling use_default_colors().
  73.  
  74.    alloc_pair(), find_pair() and free_pair() are also from ncurses.
  75.    free_pair() marks a pair as unused; find_pair() returns an existing
  76.    pair with the specified foreground and background colors, if one
  77.    exists. And alloc_pair() returns such a pair whether or not it was
  78.    previously set, overwriting the oldest initialized pair if there are
  79.    no free pairs.
  80.  
  81.    PDC_set_line_color() is used to set the color, globally, for the
  82.    color of the lines drawn for the attributes: A_UNDERLINE, A_LEFT and
  83.    A_RIGHT. A value of -1 (the default) indicates that the current
  84.    foreground color should be used.
  85.  
  86.    NOTE: COLOR_PAIR() and PAIR_NUMBER() are implemented as macros.
  87.  
  88. ### Return Value
  89.  
  90.    Most functions return OK on success and ERR on error. has_colors()
  91.    and can_change_colors() return TRUE or FALSE. alloc_pair() and
  92.    find_pair() return a pair number, or -1 on error.
  93.  
  94. ### Portability
  95.                              X/Open  ncurses  NetBSD
  96.     has_colors                  Y       Y       Y
  97.     start_color                 Y       Y       Y
  98.     init_pair                   Y       Y       Y
  99.     pair_content                Y       Y       Y
  100.     can_change_color            Y       Y       Y
  101.     init_color                  Y       Y       Y
  102.     color_content               Y       Y       Y
  103.     alloc_pair                  -       Y       -
  104.     assume_default_colors       -       Y       Y
  105.     find_pair                   -       Y       -
  106.     free_pair                   -       Y       -
  107.     use_default_colors          -       Y       Y
  108.     PDC_set_line_color          -       -       -
  109.  
  110. **man-end****************************************************************/
  111.  
  112. #include <stdlib.h>
  113. #include <string.h>
  114.  
  115. int COLORS = 0;
  116. int COLOR_PAIRS = PDC_COLOR_PAIRS;
  117.  
  118. static bool default_colors = FALSE;
  119. static short first_col = 0;
  120. static int allocnum = 0;
  121.  
  122. int start_color(void)
  123. {
  124.     PDC_LOG(("start_color() - called\n"));
  125.  
  126.     if (!SP || SP->mono)
  127.         return ERR;
  128.  
  129.     SP->color_started = TRUE;
  130.  
  131.     PDC_set_blink(FALSE);   /* Also sets COLORS */
  132.  
  133.     if (!default_colors && SP->orig_attr && getenv("PDC_ORIGINAL_COLORS"))
  134.         default_colors = TRUE;
  135.  
  136.     PDC_init_atrtab();
  137.  
  138.     return OK;
  139. }
  140.  
  141. static void _normalize(short *fg, short *bg)
  142. {
  143.     if (*fg == -1)
  144.         *fg = SP->orig_attr ? SP->orig_fore : COLOR_WHITE;
  145.  
  146.     if (*bg == -1)
  147.         *bg = SP->orig_attr ? SP->orig_back : COLOR_BLACK;
  148. }
  149.  
  150. static void _init_pair_core(short pair, short fg, short bg)
  151. {
  152.     PDC_PAIR *p = SP->atrtab + pair;
  153.  
  154.     _normalize(&fg, &bg);
  155.  
  156.     /* To allow the PDC_PRESERVE_SCREEN option to work, we only reset
  157.        curscr if this call to init_pair() alters a color pair created by
  158.        the user. */
  159.  
  160.     if (p->set)
  161.     {
  162.         if (p->f != fg || p->b != bg)
  163.             curscr->_clear = TRUE;
  164.     }
  165.  
  166.     p->f = fg;
  167.     p->b = bg;
  168.     p->count = allocnum++;
  169.     p->set = TRUE;
  170. }
  171.  
  172. int init_pair(short pair, short fg, short bg)
  173. {
  174.     PDC_LOG(("init_pair() - called: pair %d fg %d bg %d\n", pair, fg, bg));
  175.  
  176.     if (!SP || !SP->color_started || pair < 1 || pair >= COLOR_PAIRS ||
  177.         fg < first_col || fg >= COLORS || bg < first_col || bg >= COLORS)
  178.         return ERR;
  179.  
  180.     _init_pair_core(pair, fg, bg);
  181.  
  182.     return OK;
  183. }
  184.  
  185. bool has_colors(void)
  186. {
  187.     PDC_LOG(("has_colors() - called\n"));
  188.  
  189.     return SP ? !(SP->mono) : FALSE;
  190. }
  191.  
  192. int init_color(short color, short red, short green, short blue)
  193. {
  194.     PDC_LOG(("init_color() - called\n"));
  195.  
  196.     if (!SP || color < 0 || color >= COLORS || !PDC_can_change_color() ||
  197.         red < -1 || red > 1000 || green < -1 || green > 1000 ||
  198.         blue < -1 || blue > 1000)
  199.         return ERR;
  200.  
  201.     SP->dirty = TRUE;
  202.  
  203.     return PDC_init_color(color, red, green, blue);
  204. }
  205.  
  206. int color_content(short color, short *red, short *green, short *blue)
  207. {
  208.     PDC_LOG(("color_content() - called\n"));
  209.  
  210.     if (color < 0 || color >= COLORS || !red || !green || !blue)
  211.         return ERR;
  212.  
  213.     if (PDC_can_change_color())
  214.         return PDC_color_content(color, red, green, blue);
  215.     else
  216.     {
  217.         /* Simulated values for platforms that don't support palette
  218.            changing */
  219.  
  220.         short maxval = (color & 8) ? 1000 : 680;
  221.  
  222.         *red = (color & COLOR_RED) ? maxval : 0;
  223.         *green = (color & COLOR_GREEN) ? maxval : 0;
  224.         *blue = (color & COLOR_BLUE) ? maxval : 0;
  225.  
  226.         return OK;
  227.     }
  228. }
  229.  
  230. bool can_change_color(void)
  231. {
  232.     PDC_LOG(("can_change_color() - called\n"));
  233.  
  234.     return PDC_can_change_color();
  235. }
  236.  
  237. int pair_content(short pair, short *fg, short *bg)
  238. {
  239.     PDC_LOG(("pair_content() - called\n"));
  240.  
  241.     if (pair < 0 || pair >= COLOR_PAIRS || !fg || !bg)
  242.         return ERR;
  243.  
  244.     *fg = SP->atrtab[pair].f;
  245.     *bg = SP->atrtab[pair].b;
  246.  
  247.     return OK;
  248. }
  249.  
  250. int assume_default_colors(int f, int b)
  251. {
  252.     PDC_LOG(("assume_default_colors() - called: f %d b %d\n", f, b));
  253.  
  254.     if (f < -1 || f >= COLORS || b < -1 || b >= COLORS)
  255.         return ERR;
  256.  
  257.     if (SP->color_started)
  258.         _init_pair_core(0, f, b);
  259.  
  260.     return OK;
  261. }
  262.  
  263. int use_default_colors(void)
  264. {
  265.     PDC_LOG(("use_default_colors() - called\n"));
  266.  
  267.     default_colors = TRUE;
  268.     first_col = -1;
  269.  
  270.     return assume_default_colors(-1, -1);
  271. }
  272.  
  273. int PDC_set_line_color(short color)
  274. {
  275.     PDC_LOG(("PDC_set_line_color() - called: %d\n", color));
  276.  
  277.     if (!SP || color < -1 || color >= COLORS)
  278.         return ERR;
  279.  
  280.     SP->line_color = color;
  281.  
  282.     return OK;
  283. }
  284.  
  285. void PDC_init_atrtab(void)
  286. {
  287.     PDC_PAIR *p = SP->atrtab;
  288.     short i, fg, bg;
  289.  
  290.     if (SP->color_started && !default_colors)
  291.     {
  292.         fg = COLOR_WHITE;
  293.         bg = COLOR_BLACK;
  294.     }
  295.     else
  296.         fg = bg = -1;
  297.  
  298.     _normalize(&fg, &bg);
  299.  
  300.     for (i = 0; i < PDC_COLOR_PAIRS; i++)
  301.     {
  302.         p[i].f = fg;
  303.         p[i].b = bg;
  304.         p[i].set = FALSE;
  305.     }
  306. }
  307.  
  308. int free_pair(int pair)
  309. {
  310.     if (pair < 1 || pair >= PDC_COLOR_PAIRS || !(SP->atrtab[pair].set))
  311.         return ERR;
  312.  
  313.     SP->atrtab[pair].set = FALSE;
  314.     return OK;
  315. }
  316.  
  317. int find_pair(int fg, int bg)
  318. {
  319.     int i;
  320.     PDC_PAIR *p = SP->atrtab;
  321.  
  322.     for (i = 0; i < PDC_COLOR_PAIRS; i++)
  323.         if (p[i].set && p[i].f == fg && p[i].b == bg)
  324.             return i;
  325.  
  326.     return -1;
  327. }
  328.  
  329. static int _find_oldest()
  330. {
  331.     int i, lowind = 0, lowval = 0;
  332.     PDC_PAIR *p = SP->atrtab;
  333.  
  334.     for (i = 1; i < PDC_COLOR_PAIRS; i++)
  335.     {
  336.         if (!p[i].set)
  337.             return i;
  338.  
  339.         if (!lowval || (p[i].count < lowval))
  340.         {
  341.             lowind = i;
  342.             lowval = p[i].count;
  343.         }
  344.     }
  345.  
  346.     return lowind;
  347. }
  348.  
  349. int alloc_pair(int fg, int bg)
  350. {
  351.     int i = find_pair(fg, bg);
  352.  
  353.     if (-1 == i)
  354.     {
  355.         i = _find_oldest();
  356.  
  357.         if (ERR == init_pair(i, fg, bg))
  358.             return -1;
  359.     }
  360.  
  361.     return i;
  362. }
  363.