"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.1/src/color.c" (12 Oct 2016, 8680 Bytes) of archive /linux/misc/tin-2.4.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "color.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.0_vs_2.4.1.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : color.c
    4  *  Original  : Olaf Kaluza <olaf@criseis.ruhr.de>
    5  *  Author    : Roland Rosenfeld <roland@spinnaker.rhein.de>
    6  *              Giuseppe De Marco <gdm@rebel.net> (light-colors)
    7  *              Julien Oster <fuzzy@cu8.cum.de> (word highlighting)
    8  *              T.Dickey <dickey@invisible-island.net> (curses support)
    9  *  Created   : 1995-06-02
   10  *  Updated   : 2015-10-09
   11  *  Notes     : This are the basic function for ansi-color
   12  *              and word highlighting
   13  *
   14  * Copyright (c) 1995-2017 Roland Rosenfeld <roland@spinnaker.rhein.de>
   15  * All rights reserved.
   16  *
   17  * Redistribution and use in source and binary forms, with or without
   18  * modification, are permitted provided that the following conditions
   19  * are met:
   20  * 1. Redistributions of source code must retain the above copyright
   21  *    notice, this list of conditions and the following disclaimer.
   22  * 2. Redistributions in binary form must reproduce the above copyright
   23  *    notice, this list of conditions and the following disclaimer in the
   24  *    documentation and/or other materials provided with the distribution.
   25  * 3. The name of the author may not be used to endorse or promote
   26  *    products derived from this software without specific prior written
   27  *    permission.
   28  *
   29  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   30  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   31  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   33  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   35  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   37  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   38  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   40  */
   41 
   42 #ifndef TIN_H
   43 #   include "tin.h"
   44 #endif /* !TIN_H */
   45 #ifndef TCURSES_H
   46 #   include "tcurses.h"
   47 #endif /* !TCURSES_H */
   48 #ifndef included_trace_h
   49 #   include "trace.h"
   50 #endif /* !included_trace_h */
   51 
   52 #ifdef HAVE_COLOR
   53 
   54 #   define MIN_COLOR -1 /* -1 is default, otherwise 0-7 or 0-15 */
   55 
   56 int default_fcol = 7;
   57 int default_bcol = 0;
   58 
   59 #   ifdef USE_CURSES
   60     static int current_fcol = 7;
   61     static struct LIST {
   62         struct LIST *link;
   63         int pair;
   64         int fg;
   65         int bg;
   66     } *list;
   67 #   endif /* USE_CURSES */
   68 static int current_bcol = 0;
   69 
   70 
   71 /*
   72  * local prototypes
   73  */
   74 #   ifdef USE_CURSES
   75     static void set_colors(int fcolor, int bcolor);
   76 #   endif /* USE_CURSES */
   77 
   78 
   79 #   ifdef USE_CURSES
   80 static void
   81 set_colors(
   82     int fcolor,
   83     int bcolor)
   84 {
   85     static int nextpair;
   86 
   87 #       ifndef HAVE_USE_DEFAULT_COLORS
   88     if (fcolor < 0)
   89         fcolor = default_fcol;
   90     if (bcolor < 0)
   91         bcolor = default_bcol;
   92 #       endif /* !HAVE_USE_DEFAULT_COLORS */
   93     if (cmd_line || !use_color || !has_colors()) {
   94         current_fcol = default_fcol;
   95         current_bcol = default_bcol;
   96     } else if (COLORS > 1 && COLOR_PAIRS > 1) {
   97         chtype attribute = A_NORMAL;
   98         int pair = 0;
   99 
  100         TRACE(("set_colors(%d, %d)", fcolor, bcolor));
  101 
  102         /*
  103          * fcolor/bcolor may be negative, if we're using ncurses
  104          * function use_default_colors().
  105          */
  106         if (fcolor > COLORS - 1) {
  107             attribute |= A_BOLD;
  108             fcolor %= COLORS;
  109         }
  110         if (bcolor > 0)
  111             bcolor %= COLORS;
  112 
  113         if (fcolor != default_fcol || bcolor != default_bcol) {
  114             struct LIST *p;
  115             t_bool found = FALSE;
  116 
  117             for (p = list; p != NULL; p = p->link) {
  118                 if (p->fg == fcolor && p->bg == bcolor) {
  119                     found = TRUE;
  120                     break;
  121                 }
  122             }
  123             if (found) {
  124                 pair = p->pair;
  125             } else if (++nextpair < COLOR_PAIRS) {
  126                 p = my_malloc(sizeof(struct LIST));
  127                 p->fg = fcolor;
  128                 p->bg = bcolor;
  129                 p->pair = pair = nextpair;
  130                 p->link = list;
  131                 list = p;
  132                 init_pair(pair, fcolor, bcolor);
  133             } else {
  134                 pair = 0;
  135             }
  136         }
  137 
  138         bkgdset(attribute | COLOR_PAIR(pair) | ' ');
  139     }
  140 }
  141 
  142 
  143 void
  144 refresh_color(
  145     void)
  146 {
  147     set_colors(current_fcol, current_bcol);
  148 }
  149 
  150 
  151 void
  152 reset_color(
  153     void)
  154 {
  155     current_fcol = default_fcol;
  156     current_bcol = default_bcol;
  157     refresh_color();
  158 }
  159 
  160 
  161 void
  162 free_color_pair_arrays(
  163     void)
  164 {
  165     struct LIST *p, *q;
  166 
  167     for (p = list; p != NULL; p = q) {
  168         q = p->link;
  169         free(p);
  170     }
  171 }
  172 #   endif /* USE_CURSES */
  173 
  174 
  175 /* setting foreground-color */
  176 void
  177 fcol(
  178     int color)
  179 {
  180     if (color < MIN_COLOR || color > MAX_COLOR)
  181         color = default_fcol;
  182 
  183     TRACE(("fcol(%d) %s", color, txt_colors[color - MIN_COLOR]));
  184 
  185     if (use_color) {
  186 #   ifdef USE_CURSES
  187         set_colors(color, current_bcol);
  188         current_fcol = color;
  189 #   else
  190         int bold;
  191 
  192         if (cmd_line)
  193             return;
  194         if (color < 0)
  195             color = default_fcol;
  196         bold = (color >> 3); /* bitwise operation on signed value? ouch */
  197         my_printf("\033[%d;%dm", bold, ((color & 7) + 30));
  198         if (!bold)
  199             bcol(current_bcol);
  200 #   endif /* USE_CURSES */
  201     }
  202 #   ifdef USE_CURSES
  203     else
  204         set_colors(default_fcol, default_bcol);
  205 #   endif /* USE_CURSES */
  206 }
  207 
  208 
  209 /* setting background-color */
  210 void
  211 bcol(
  212     int color)
  213 {
  214     if (color < MIN_COLOR || color > MAX_COLOR)
  215         color = default_bcol;
  216 
  217     TRACE(("bcol(%d) %s", color, txt_colors[color - MIN_COLOR]));
  218 
  219     if (use_color) {
  220 #   ifdef USE_CURSES
  221         set_colors(current_fcol, color);
  222 #   else
  223         if (color < 0)
  224             color = default_bcol;
  225         my_printf("\033[%dm", (color + 40));
  226 #   endif /* USE_CURSES */
  227         current_bcol = color;
  228     }
  229 #   ifdef USE_CURSES
  230     else
  231         set_colors(default_fcol, default_bcol);
  232 #   endif /* USE_CURSES */
  233 }
  234 #endif /* HAVE_COLOR */
  235 
  236 
  237 /*
  238  * Output a line of text to the screen with colour if needed
  239  * word highlights, signatures etc will be highlighted
  240  */
  241 void
  242 draw_pager_line(
  243     const char *str,
  244     int flags,
  245     t_bool raw_data)
  246 {
  247 #ifdef HAVE_COLOR
  248 
  249     if (use_color) {
  250         if (flags & C_SIG) {
  251             fcol(tinrc.col_signature);
  252         } else if (flags & (C_HEADER | C_ATTACH | C_UUE)) {
  253             fcol(tinrc.col_newsheaders);
  254         } else { /* keep order in sync with cook.c:process_text_body_part() */
  255             if (flags & C_VERBATIM) {
  256                 fcol(tinrc.col_verbatim);
  257             } else if (flags & C_QUOTE3) {
  258                 fcol(tinrc.col_quote3);
  259             } else if (flags & C_QUOTE2) {
  260                 fcol(tinrc.col_quote2);
  261             } else if (flags & C_EXTQUOTE) {
  262                 fcol(tinrc.col_extquote);
  263             } else if (flags & C_QUOTE1) {
  264                 fcol(tinrc.col_quote);
  265             } else
  266                 fcol(tinrc.col_text);
  267         }
  268     }
  269 
  270 #endif /* HAVE_COLOR */
  271     if (!raw_data) {
  272 #if defined(HAVE_LIBICUUC) && defined(MULTIBYTE_ABLE) && defined(HAVE_UNICODE_UBIDI_H) && !defined(NO_LOCALE)
  273         /*
  274          * BiDi support
  275          */
  276         /* don't run it on empty lines and lines containing only one char (which must be an ASCII one) */
  277         if (tinrc.render_bidi && IS_LOCAL_CHARSET("UTF-8") && strlen(str) > 1) {
  278             char *line;
  279             t_bool is_rtl;
  280 
  281             if ((line = render_bidi(str, &is_rtl)) != NULL) {
  282                 if (is_rtl) { /* RTL */
  283                     /* determine visual length and pad out so that line is right-aligned */
  284                     wchar_t *wline;
  285 
  286                     if ((wline = char2wchar_t(line)) != NULL) {
  287                         int visual_len;
  288 
  289                         wconvert_to_printable(wline, FALSE);
  290                         visual_len = wcswidth(wline, wcslen(wline) + 1);
  291                         free(wline);
  292 
  293                         if (visual_len > 0) {
  294                             int i;
  295 
  296                             for (i = 0; i < cCOLS - visual_len - 1; i++)
  297                                 my_fputc(' ', stdout);
  298                         }
  299                         my_fputs(line, stdout);
  300                     } else /* fallback */
  301                         my_fputs(line, stdout);
  302 
  303                 } else  /* LTR */
  304                     my_fputs(line, stdout);
  305 
  306                 free(line);
  307             } else
  308                 my_fputs(str, stdout);
  309         } else
  310 #endif /* HAVE_LIBICUUC && MULTIBYTE_ABLE && HAVE_UNICODE_UBIDI_H && !NO_LOCALE */
  311             my_fputs(str, stdout);
  312     } else {
  313         /* in RAW-mode (show_all_headers) display non-printable chars as octals */
  314         const char *c;
  315         char octal[5];
  316 
  317         c = str;
  318         while (*c) {
  319 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  320             int num_bytes;
  321             wchar_t wc;
  322 
  323             num_bytes = mbtowc(&wc, c, MB_CUR_MAX);
  324             if (num_bytes != -1 && iswprint(wc)) {
  325                 my_fputwc((wint_t) wc, stdout);
  326                 c += num_bytes;
  327             }
  328 #else
  329             if (my_isprint((unsigned char) *c)) {
  330                 my_fputc((int) *c, stdout);
  331                 c++;
  332             }
  333 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  334             else if (IS_LOCAL_CHARSET("Big5") && (unsigned char) *c >= 0xa1 && (unsigned char) *c <= 0xfe && *(c + 1)) {
  335                 /*
  336                  * Big5: ASCII chars are handled by the normal code
  337                  * check only for 2-byte chars
  338                  * TODO: should we also check if the second byte is also valid?
  339                  */
  340                 my_fputc((int) *c, stdout);
  341                 c++;
  342                 my_fputc((int) *c, stdout);
  343                 c++;
  344             } else {
  345                 /*
  346                  * non-printable char
  347                  * print as an octal value
  348                  */
  349                 snprintf(octal, sizeof(octal), "\\%03o", (unsigned int) (*c & 0xff));
  350                 my_fputs(octal, stdout);
  351                 c++;
  352             }
  353         }
  354     }
  355 
  356 #ifndef USE_CURSES
  357     my_fputs(cCRLF, stdout);
  358 #endif /* !USE_CURSES */
  359 }