LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   [C++] Linux API - get Console Font Color (https://www.linuxquestions.org/questions/programming-9/%5Bc-%5D-linux-api-get-console-font-color-887303/)

TheGuiTarJokeR 06-20-2011 06:24 AM

[C++] Linux API - get Console Font Color
 
Hi Folks,

I've coma across a problem I have not been able to solve myself. Is there a function in the linux API similar to GetConsoleScreenBufferInfo() on Windows?
refer to: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

I only need to get the current color settings of the active terminal.

thanks,

TJ

konsolebox 06-20-2011 06:42 AM

can't give much details but you can refer to linux/fb.h for that: http://lxr.free-electrons.com/source/include/linux/fb.h

perhaps you can take a look at linux/vt.h as well.

---- edit ----

i think you can start with the structure fb_info and these functions:

struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
void framebuffer_release(struct fb_info *info);
int fb_init_device(struct fb_info *fb_info);
void fb_cleanup_device(struct fb_info *head);

TheGuiTarJokeR 06-20-2011 08:40 AM

Holy shit!
I's gonna take me some time to read through these. I'll drop a comment here, when I found what I need.
thanks :)

Nominal Animal 06-21-2011 01:40 AM

Reading virtual terminal contents is AFAIK impossible. Size and current cursor position, however, is rather easy. Using the ncurses library:
Code:

#include <ncurses.h>
#include <stdio.h>

int main(void)
{
        int        rows, cols, row, col;

        WINDOW *w = initscr();
        getmaxyx(w, rows, cols);
        getyx(w, row, col);
        endwin();

        printf("Row %d of %d, column %d of %d.\n",
              1+row, rows, 1+col, cols);
        return 0;
}

If you do not want to add another library dependence, you can use the Linux-specific lower-level interfaces. See man tty_ioctl and man console_ioctl.

TIOCGWINSZ ioctl to the controlling terminal (stdout or stderr, whichever is a tty) will fill in a struct winsize, which contains the number of rows and columns in the terminal at that point. Install a SIGWINCH signal handler which does that ioctl again, if you want to be notified of changes.

ANSI escape sequence \033[6n (4 bytes) to the controlling terminal should inject the cursor position as \033[row;colR into standard input. In order to hide that sequence from the terminal, you'll need to manipulate the terminal attributes.

Here is a program which seems to work. I just threw it together, so there may be bugs lurking in it.
Code:

#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>

#include <stdio.h>

int terminal_specs(int *const cols, int *const rows,
                  int *const col,  int *const row)
{
        int                in, out, result;
        char                buffer[16];
        struct winsize        ws;
        struct termios        t1, t2;

        /* Initialize zeros (unknown) */
        if (cols) *cols = 0;
        if (rows) *rows = 0;
        if (col)  *col  = 0;
        if (row)  *row  = 0;

        /* Open controlling tty for input. */
        do {
                in = open("/dev/tty", O_RDONLY | O_NONBLOCK);
        } while (in == -1 && errno == EINTR);
        if (in == -1)
                return errno;

        /* Reopen TTY for output. */
        do {
                out = open("/dev/tty", O_WRONLY);
        } while (out == -1 && errno == EINTR);
        if (out == -1) {
                int const saved_errno = errno;
                do {
                        result = close(in);
                } while (result == -1 && errno == EINTR);
                return saved_errno;
        }

        /* Determine terminal size. */
        if (!ioctl(out, TIOCGWINSZ, &ws)) {
                if (cols) *cols = ws.ws_col;
                if (rows) *rows = ws.ws_row;
        }

        /* Save current terminal settings. */
        tcgetattr(out, &t1);
        tcgetattr(out, &t2);

        /* Disable echo and signals for now. */
        t2.c_iflag &= ~( IGNBRK | IGNPAR );
        t2.c_oflag &= ~( OFILL );
        t2.c_oflag |=    ONOCR;
        t2.c_lflag &= ~( ISIG | ICANON | ECHO );
        tcsetattr(out, TCSANOW, &t2);

        /* Query cursor location. */
        if (row || col) {

                if (write(out, "\033[6n", 4) == 4) {
                        do {
                                result = read(in, buffer, sizeof(buffer) - 1);
                        } while (result == -1 && (errno == EINTR || errno == EWOULDBLOCK));
                        if (result > 0 && buffer[result - 1] == 'R') {
                                char *p = buffer;
                                int  nr = 0;
                                int  nc = 0;

                                buffer[result - 1] = 0;

                                /* parse [^0-9]*([0-9]*)[^0-9]*([0-9]*) */
                                while (*p && !(*p >= '0' && *p <= '9')) p++;
                                while (*p >= '0' && *p <= '9')
                                        nr = nr * 10 + (*(p++) - '0');
                                while (*p && !(*p >= '0' && *p <= '9')) p++;
                                while (*p >= '0' && *p <= '9')
                                        nc = nc * 10 + (*(p++) - '0');

                                if (row) *row = nr;
                                if (col) *col = nc;
                        }
                }
        }
               
        /* Restore terminal settings. */
        tcsetattr(out, TCSANOW, &t1);

        /* Close descriptors. */
        do {
                result = close(in);
        } while (result == -1 && errno == EINTR);
        do {
                result = close(out);
        } while (result == -1 && errno == EINTR);

        return 0;
}

int main(void)
{
        int        cols, rows, col, row;

        terminal_specs(&cols, &rows, &col, &row);

        if (cols > 0 && rows > 0 && col > 0 && row > 0)
                printf("Row %d of %d, column %d of %d\n", row, rows, col, cols);
        else
        if (cols > 0 && rows > 0)
                printf("%d rows, %d columns\n", rows, cols);
        else
        if (col > 0 && row > 0)
                printf("Row %d, column %d\n", row, col);

        return 0;
}

Note that I wrote the terminal_specs() function so that it does not need stdio at all. (I could have used sscanf(), but this way it's independent.)

If you call terminal_specs() first, before reading from standard input, standard input should be kept untouched.

Hope this helps.


All times are GMT -5. The time now is 09:03 PM.