Design question: A little C++ header for colorizing text in Linux -- Comments/Ideas

Discussion in 'C++' started by Slash, Nov 11, 2003.

  1. Slash

    Slash Guest

    I often do a lot of text-mode programming in Linux and wanted to use
    colors in text mode, and found the ncurses library needlessly complex
    for small applications. So I wrote my own little header to handle
    colors in C++. (The code follows.)

    This allows me to write code like

    cout << gotoxy(10, 11)
    << color(lightcyan, blue)
    << "some text whatever";

    I'd like to know how I could implement this more efficiently or in a
    better way. Here are some questions I have:

    (1) What exactly is a manipulator and how do I write one? How could a
    manipulator help here?

    (2) All that color and gotoxy do is simply output the corresponding
    ANSI escape sequence string. How could I best make a color pair map
    into its corresponding ANSI escape string?

    (3) Could I selectively output the characters for gotoxy and color
    (they simply output the corresponding ANSI escape sequences) only when
    it is used with cout and not an ofstream object?

    (4) How could I make this more easy to use?

    Thanks in advance :)

    -----------------------------------------------------

    Here's the code:

    //---------------------------------------------
    // color.h
    //---------------------------------------------

    #ifndef COLOR_H
    #define COLOR_H

    #include <iostream>
    using namespace std;

    enum ColorName
    {
    black,
    red,
    green,
    brown,
    blue,
    magenta,
    cyan,
    lightgray,

    darkgray,
    lightred,
    lightgreen,
    yellow,
    lightblue,
    lightmagenta,
    lightcyan,
    white
    };


    struct color
    {
    color(ColorName f = white, ColorName b = black)
    :
    fore(f),
    back(b)
    {}


    ColorName fore;
    ColorName back;
    };


    inline ostream& operator<<(ostream& o, const color& c)
    {
    if(c.fore > lightgray) // bold color
    o << "\033[1;3" << c.fore - lightgray - 1 << "m";
    else
    o << "\033[0;3" << c.fore << "m";

    return o << "\033[4" << c.back << "m";
    }


    struct gotoxy
    {
    gotoxy(int x_, int y_)
    :
    x(x_),
    y(y_)
    {}

    int x;
    int y;

    };


    inline ostream& operator<<(ostream& o, const gotoxy& g)
    {
    return o << "\033[" << g.y << ";" << g.x << "f";
    }

    #endif
     
    Slash, Nov 11, 2003
    #1
    1. Advertising

  2. "Slash" <> wrote...
    > I often do a lot of text-mode programming in Linux and wanted to use
    > colors in text mode, and found the ncurses library needlessly complex
    > for small applications. So I wrote my own little header to handle
    > colors in C++. (The code follows.)
    >
    > This allows me to write code like
    >
    > cout << gotoxy(10, 11)
    > << color(lightcyan, blue)
    > << "some text whatever";
    >
    > I'd like to know how I could implement this more efficiently or in a
    > better way.


    I think your implementation is good enough. What inefficiencies do
    you see in it? What is not good about it, in your opinion?

    > Here are some questions I have:
    >
    > (1) What exactly is a manipulator and how do I write one? How could a
    > manipulator help here?


    You have successfully written two manipulators. Why are you asking
    about how to write them?

    > (2) All that color and gotoxy do is simply output the corresponding
    > ANSI escape sequence string. How could I best make a color pair map
    > into its corresponding ANSI escape string?


    What don't you like about the way you do it now? I can see only one
    marginally acceptable improvement: a table of ANSI strings instead
    of the calculation. Still, to prove that it's an improvement, one
    would need to profile both versions.

    > (3) Could I selectively output the characters for gotoxy and color
    > (they simply output the corresponding ANSI escape sequences) only when
    > it is used with cout and not an ofstream object?


    No, for all intents and purposes 'std::cout' _could_ be a file. It
    is impossible to tell without being platform-specific, AFAIK.

    >
    > (4) How could I make this more easy to use?


    It's easy as it is. How much easier do you expect it to get?

    Keep in mind, though, that your code is NOT going to work on systems
    that do not have ANSI terminals (and those are quite a few).

    Victor
     
    Victor Bazarov, Nov 11, 2003
    #2
    1. Advertising

  3. Slash

    Roger Leigh Guest

    Re: Design question: A little C++ header for colorizing text inLinux -- Comments/Ideas

    (Slash) writes:

    > I often do a lot of text-mode programming in Linux and wanted to use
    > colors in text mode, and found the ncurses library needlessly complex
    > for small applications. So I wrote my own little header to handle
    > colors in C++. (The code follows.)
    >
    > This allows me to write code like
    >
    > cout << gotoxy(10, 11)
    > << color(lightcyan, blue)
    > << "some text whatever";
    >
    > I'd like to know how I could implement this more efficiently or in a
    > better way. Here are some questions I have:


    You still need libncurses, or libslang, or terminfo. If you don't,
    you can't cope with non-ANSI terminals or output redirection to
    non-terminal destinations.

    ncurses isn't /that/ difficult. Your existing API is quite good, and
    should wrap ncurses with little difficulty. You could have a base
    object representing a window, and do

    window << color(blue, yellow) << message;

    and have this wrap printw() et. al..

    > (1) What exactly is a manipulator and how do I write one? How could a
    > manipulator help here?


    Do you mean in the sense of <iomanip>? These are used to control
    formatting of numbers, field widths, alignment etc. I don't think you
    need to use them in your header, but users of the header would use
    them to format their output appropriately.

    If you output to your own class (rather than a std::eek:stream) you could
    use your own custom manipulators to set the colours, coordinates,
    etc..

    > (2) All that color and gotoxy do is simply output the corresponding
    > ANSI escape sequence string. How could I best make a color pair map
    > into its corresponding ANSI escape string?


    I'd use ncurses and a defined set of COLOR_PAIRs: use an enum for the
    defined values (it looks like you are already doing this).

    > (4) How could I make this more easy to use?


    Personally, I'd prefer to use an ncurses-based toolkit that provided a
    higher-level abstraction of terminal I/O, providing widgets, input
    focus, container-based widget alignment and sizing etc.. Essentially,
    I mean an object-oriented toolkit after the likes of GTK+/Gtkmm or
    Swing.


    --
    Roger Leigh

    Printing on GNU/Linux? http://gimp-print.sourceforge.net/
    GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
     
    Roger Leigh, Nov 11, 2003
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marcus
    Replies:
    3
    Views:
    409
    Marcus
    May 3, 2005
  2. Maciej Dziardziel

    xml colorizing

    Maciej Dziardziel, May 5, 2004, in forum: Python
    Replies:
    0
    Views:
    327
    Maciej Dziardziel
    May 5, 2004
  3. mlt
    Replies:
    2
    Views:
    907
    Jean-Marc Bourguet
    Jan 31, 2009
  4. Replies:
    0
    Views:
    257
  5. Roy Smith
    Replies:
    4
    Views:
    318
    Chris Angelico
    Nov 18, 2012
Loading...

Share This Page