Thread: Flashing Text in Linux Terminal

  1. #1
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373

    Flashing Text in Linux Terminal

    I know its not portable either in terms of OS or CPU speed, but I want to learn some
    basic graphic functionality in Windows and Linux before moving on to consider cross
    -platform API's. So I'm really just interested in how I can create flashing text in
    the Linux terminal window using escape codes.

    In Windows the move from static to dynamic was trivial and I ended up creating a
    naff flashing "Merry Xmas" sign, which I would like to replicate in Linux.

    In Windows all I really needed to do was print a bright character,pause then
    print its dimmer companion,pause then keep looping.

    In Linux that just doesn't work,I get weird synchronisation effects and white versions
    of the characters appearing instead of the coloured ones that are supposed to etc.

    The only half-clue garnered from the internet was a small sentence that said "blink"
    doesn't work in a terminal emulator. Which I understand is the type of terminal I am
    using in a GUI Linux like the Puppy Linux I'm using.

    Well I'm not using the blink attribute but it makes me think that maybe it just can't
    cope with this kind of graphic switching?

    The code here just prints 2 of the characters, and because I've got a white terminal
    window background I first create a black background for the minimised window.

    Anyone any ideas?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <unistd.h>
    
    #define ALL_NORMAL "\033[0m"
    #define BG_BLACK   "\033[40m"
    #define BLACKBACK BG_BLACK " " ALL_NORMAL
    #define REVERSE "\033[7m"
    
    #define FG_RED         "\033[1;31;40m"           // bright red black bg
    #define FG_MAROON      "\033[2;31;40m"        // dark red black bg
    #define FG_YELLOW    "\033[1;33;40m"           // bright yellow black bg
    #define FG_DYELLOW      "\033[2;33;40m"        // dark yellow black bg
    
    #define BRIGHT_RED_M FG_RED "M" ALL_NORMAL
    #define DIM_RED_M FG_MAROON "M" ALL_NORMAL
    #define BRIGHT_YELLOW_R FG_YELLOW "R" ALL_NORMAL
    #define DIM_YELLOW_R FG_DYELLOW "R" ALL_NORMAL
    
    void set_coord(int x, int y);
    void plot_char(int x,int y,char *char_string);
    
    int main(void)
    {
        int x,y,timer;
        
        system("clear");
        
        
        for(x=0;x<80;x++)                    //set background black 
        {
            for(y=0;y<25;y++)
            {
                plot_char(x,y,BLACKBACK);
                                        
            }
        }
        
        
        while(1)
        {    
            plot_char(20,10,BRIGHT_RED_M);
            plot_char(22,10,BRIGHT_YELLOW_R);
            
            timer = 0;
            while(timer < 10000000)
            {
                timer++;
            }
            
            plot_char(20,10,DIM_RED_M);
            plot_char(22,10,DIM_YELLOW_R);
            
            timer = 0;
            while(timer < 1000000)
            {
                timer++;
            }        
        }    
        return 0;
    }
    
    void set_coord(int x, int y)
    {    
        printf("\033[%d;%dH",y,x);    // move cursor (row x, col y) 
    }
    
    void plot_char(int x,int y,char *char_string)
    {
        set_coord(x,y);
        fputs(char_string,stdout);
        //printf("%s",char_string);
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    If I just throw in a
    printf("\033[?25l");
    at the start, to turn the cursor off, it looks fine here (Ubuntu, Gnome terminal)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    As far as I can tell it has no effect at all, unfortunately.

    However, I've posted on the Puppy forum for a method of disabling
    the cursor, and if I get a solution I'll post it back here.

  4. #4
    Registered User
    Join Date
    Nov 2012
    Location
    Some rock floating in space...
    Posts
    32
    If you just want to blink text, the following will work

    Code:
        /* note: This doesn't work properly in gnome-terminal 
         * but color codes etc. do oddly enough */
        printf("\033[5;32;40m"); /* set green on black and blinking */
       /* notes: the first parm: 5 tells it to blink... the second parm: 32 tells it green text... the third parm: 40 tells it black background */
        printf("Blinking green on black background...\n");
        printf("\033[m"); /* stop blinking attribute from further text */
    Every terminal emulator is different... blinking doesn't always work
    Last edited by twiki; 12-19-2012 at 09:19 PM. Reason: Added note

  5. #5
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    There was no solution at the Puppy forum.

    I might have missed something but I also tried gnome and there were still
    synchronisation/code problems.

    Part of the reason for doing the program was to use threads in Linux so I went
    ahead and created a 2nd thread in the program anyway, expecting a complete mess,
    only to find all the previous problems magically disappeared!
    (In rxvt and gnome.)

    Its also possible to have synchronised flashing text only by creating a 2nd thread
    that just prints a character the same colour as the background at screen position
    (0,0) for example.

    So I guess I've ended up with a hack rather than an actual solution.

    Its still naff, but this is tweaked for gnome:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <time.h>
    #include <unistd.h>
    #include <string.h>
    
    #define  ALL_NORMAL "\033[0m"
    
    #define  FG_BLACK   "\033[22;30m"    // dark colours
    #define  FG_MAROON  "\033[22;31m"     
    #define  FG_GREEN   "\033[22;32m"
    #define  FG_OLIVE   "\033[22;33m"     
    #define  FG_NAVY    "\033[22;34m"     
    #define  FG_PURPLE  "\033[22;35m"
    #define  FG_TEAL    "\033[22;36m"     
    #define  FG_SILVER  "\033[22;37m"     
    
    #define  FG_GRAY    "\033[1;30m"     // light colours
    #define  FG_RED     "\033[1;31m"      
    #define  FG_LIME    "\033[1;32m"      
    #define  FG_YELLOW  "\033[1;33m"
    #define  FG_BLUE    "\033[1;34m"
    #define  FG_FUCHSIA "\033[1;35m"      
    #define  FG_AQUA    "\033[1;36m"      
    #define  FG_WHITE   "\033[1;37m"
    
    #define  BG_BLACK   "\033[40m"
    
    #define BLACKBACK BG_BLACK " " ALL_NORMAL
    #define MAGENTA  FG_FUCHSIA BG_BLACK "#" ALL_NORMAL
    #define CYAN    FG_TEAL BG_BLACK "#" ALL_NORMAL
    #define RED     FG_RED BG_BLACK "#" ALL_NORMAL
    #define YELLOW  FG_YELLOW BG_BLACK "#" ALL_NORMAL
    
    #define BRIGHT_RED BG_BLACK FG_RED "M" ALL_NORMAL
    #define BRIGHT_GREEN BG_BLACK FG_LIME "E" ALL_NORMAL
    #define BRIGHT_YELLOW BG_BLACK FG_YELLOW "R" ALL_NORMAL
    #define BRIGHT_BLUE BG_BLACK FG_BLUE "R" ALL_NORMAL
    #define BRIGHT_MAGENTA BG_BLACK FG_FUCHSIA "Y" ALL_NORMAL
    #define BRIGHT_MAGENTA2 BG_BLACK FG_FUCHSIA "X" ALL_NORMAL
    #define BRIGHT_CYAN BG_BLACK FG_AQUA "M" ALL_NORMAL
    #define BRIGHT_WHITE BG_BLACK FG_WHITE "A" ALL_NORMAL
    #define BRIGHT_RED2 BG_BLACK FG_RED "S" ALL_NORMAL
    
    #define DIM_RED BG_BLACK FG_MAROON "M" ALL_NORMAL
    #define DIM_GREEN BG_BLACK FG_GREEN "E" ALL_NORMAL
    #define DIM_YELLOW BG_BLACK FG_OLIVE "R" ALL_NORMAL
    #define DIM_BLUE BG_BLACK FG_NAVY "R" ALL_NORMAL
    #define DIM_MAGENTA BG_BLACK FG_PURPLE "Y" ALL_NORMAL
    #define DIM_MAGENTA2 BG_BLACK FG_PURPLE "X" ALL_NORMAL
    #define DIM_CYAN BG_BLACK FG_TEAL "M" ALL_NORMAL
    #define DIM_WHITE BG_BLACK FG_SILVER "A" ALL_NORMAL
    #define DIM_RED2 BG_BLACK FG_MAROON "S" ALL_NORMAL
    
    /********************************************************/
    /*                                                      */
    /*                  Flashing XMAS Sign.                 */
    /*                                                      */
    /*                                                      */
    /*                                                      */
    /*                                                      */
    /*                                                      */
    /*             gemera            24th Dec 2012          */
    /*                                                      */
    /********************************************************/
    
    #define COLS 80
    #define ROWS 25
    
    #define START_X 8                   // x start position of sign
    #define START_Y 9                     // y start position of sign
    
    void set_coord(int x, int y);
    void plot_char(int x,int y,char *colour);
    void* tinsel_func(void * id);
    void sleep_seconds(long seconds);
    
    pthread_mutex_t mutex1;
    
    int main(void)
    {
        int x,y;
        pthread_t thread1;
        
        pthread_mutex_init(&mutex1,NULL);
    
        srand(time(NULL));
       
        system("clear");
        system("setterm -cursor off");
    
        pthread_create(&thread1,NULL,&tinsel_func,NULL);
    
        while(1)
        {
            pthread_mutex_lock(&mutex1);
    
            plot_char(START_X,START_Y,BRIGHT_RED);
            plot_char(START_X+16,START_Y,BRIGHT_GREEN);
            plot_char(START_X+32,START_Y,BRIGHT_YELLOW);
            plot_char(START_X+48,START_Y,BRIGHT_BLUE);
            plot_char(START_X+64,START_Y,BRIGHT_MAGENTA);
            plot_char(START_X+8,START_Y+6,BRIGHT_MAGENTA2);
            plot_char(START_X+24,START_Y+6,BRIGHT_CYAN);
            plot_char(START_X+40,START_Y+6,BRIGHT_WHITE);
            plot_char(START_X+56,START_Y+6,BRIGHT_RED2);
    
            pthread_mutex_unlock(&mutex1);
            
            sleep_seconds(1);
            
            pthread_mutex_lock(&mutex1);
            
            plot_char(START_X,START_Y,DIM_RED);        
            plot_char(START_X+16,START_Y,DIM_GREEN);
            plot_char(START_X+32,START_Y,DIM_YELLOW);
            plot_char(START_X+48,START_Y,DIM_BLUE);
            plot_char(START_X+64,START_Y,DIM_MAGENTA);
            plot_char(START_X+8,START_Y+6,DIM_MAGENTA2);
            plot_char(START_X+24,START_Y+6,DIM_CYAN);
            plot_char(START_X+40,START_Y+6,DIM_WHITE);
            plot_char(START_X+56,START_Y+6,DIM_RED2);      
            
            /*plot_char(START_X,START_Y,BLACKBACK);        //alternate 
    
            plot_char(START_X+16,START_Y,BLACKBACK);
            plot_char(START_X+32,START_Y,BLACKBACK);
            plot_char(START_X+48,START_Y,BLACKBACK);
            plot_char(START_X+64,START_Y,BLACKBACK);
            plot_char(START_X+8,START_Y+6,BLACKBACK);
            plot_char(START_X+24,START_Y+6,BLACKBACK);
            plot_char(START_X+40,START_Y+6,BLACKBACK);
            plot_char(START_X+56,START_Y+6,BLACKBACK);*/
    
            pthread_mutex_unlock(&mutex1);
            
            sleep_seconds(1);
        }
            
            return 0;
    }
    
    void set_coord(int x, int y)
    {    
        printf("\033[%d;%dH",y,x);    /* move cursor (row y, col x) */
    }
    
    void plot_char(int x,int y,char * colour)
    {
        set_coord(x,y);
        
        fputs(colour,stdout);
    }
    
    void* tinsel_func(void *id)
    {
        int x,y,i;
        char *tinsel_colour[] = {MAGENTA,CYAN,RED,YELLOW};
        
        while(1)
        {
            pthread_mutex_lock(&mutex1);
    
            // plot_char(0,0,FG_BLACK BG_BLACK "." ALL_NORMAL); for flashing sign only
        
            i = rand() % 4;        // to access random colour for tinsel
        
            y = 3;
            x = rand() % COLS;
            plot_char(x,y,tinsel_colour[i]);    
    
            y = 22;
            x = rand() % COLS;
            plot_char(x,y,tinsel_colour[i]);    
    
            pthread_mutex_unlock(&mutex1);
        }
    
        return NULL;
    }
    
    void sleep_seconds(long seconds)
    {
        clock_t limit,now  = clock();
        
        limit = now + seconds * CLOCKS_PER_SEC;
        
        while(limit > now)
        {
            now = clock();
        }
    }

  6. #6
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    btw I neglected to comment that the sleep_seconds function is a portable delay function from the FAQ here.

  7. #7
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    Also , the mutex could have been passed via pthread_create instead of being declared globally.

  8. #8
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    Portable doesn't mean recommended. Using a delay function such as this will result in no other process being able to use the CPU during the "sleep" period....which completely defeats the purpose of a process "sleeping".

    I would recommend using the delay function provided by the platform (usleep() probably good choice in this case)

  9. #9
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    Quote Originally Posted by nonpuz View Post
    Portable doesn't mean recommended. Using a delay function such as this will result in no other process being able to use the CPU during the "sleep" period....which completely defeats the purpose of a process "sleeping".

    I would recommend using the delay function provided by the platform (usleep() probably good choice in this case)
    Just saw this,

    I would have thought whether to use a delay or a sleep would have been a design issue not a programming issue in this instance. i.e do I want the second thread to have free reign or do I want to slow it down a bit.

    I was intentionally using CPU intensive routines, which can be seen from my first post as well.

    Eitherwise, it's sold as seen, and we don't give refunds here.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How do I use a text terminal as a bitmap?
    By PedroTuga in forum C Programming
    Replies: 5
    Last Post: 12-08-2012, 06:05 PM
  2. Getting screen size - unix/linux terminal
    By enok in forum C++ Programming
    Replies: 3
    Last Post: 11-21-2009, 04:56 AM
  3. Flashing text
    By Queatrix in forum C++ Programming
    Replies: 5
    Last Post: 04-10-2005, 09:32 PM
  4. flashing text in c++
    By tetraflare in forum C++ Programming
    Replies: 4
    Last Post: 11-27-2002, 07:06 PM
  5. Is it possible to create flashing text?
    By wolzi in forum C++ Programming
    Replies: 2
    Last Post: 05-07-2002, 08:53 PM