Home | History | Annotate | Download | only in sys
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 2009 Erwan Velu - All Rights Reserved
      4  *
      5  *   Permission is hereby granted, free of charge, to any person
      6  *   obtaining a copy of this software and associated documentation
      7  *   files (the "Software"), to deal in the Software without
      8  *   restriction, including without limitation the rights to use,
      9  *   copy, modify, merge, publish, distribute, sublicense, and/or
     10  *   sell copies of the Software, and to permit persons to whom
     11  *   the Software is furnished to do so, subject to the following
     12  *   conditions:
     13  *
     14  *   The above copyright notice and this permission notice shall
     15  *   be included in all copies or substantial portions of the Software.
     16  *
     17  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     19  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     21  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     22  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  *   OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  * -----------------------------------------------------------------------
     27  *  Ansi Sequences can be found here :
     28  *  http://ascii-table.com/ansi-escape-sequences-vt-100.php
     29  *  http://en.wikipedia.org/wiki/ANSI_escape_code
     30  */
     31 
     32 #include <stdlib.h>
     33 #include <stdio.h>
     34 #include <string.h>
     35 #include <stdbool.h>
     36 #include <stdint.h>
     37 
     38 #include "libansi.h"
     39 
     40 void display_cursor(bool status)
     41 {
     42 	if (status == true) {
     43 		fputs(CSI "?25h", stdout);
     44 	} else {
     45 		fputs(CSI "?25l", stdout);
     46 	}
     47 }
     48 
     49 void clear_end_of_line(void)
     50 {
     51 	fputs(CSI "0K", stdout);
     52 }
     53 
     54 void move_cursor_left(int count)
     55 {
     56 	char buffer[10];
     57 	memset(buffer,0,sizeof(buffer));
     58 	sprintf(buffer,CSI "%dD",count);
     59 	fputs(buffer, stdout);
     60 }
     61 
     62 void move_cursor_right(int count)
     63 {
     64 	char buffer[10];
     65 	memset(buffer,0,sizeof(buffer));
     66 	sprintf(buffer, CSI "%dC", count);
     67 	fputs(buffer, stdout);
     68 }
     69 
     70 void set_cursor_blink(bool status) {
     71 	if (status == true)
     72 		fputs("\033[05m",stdout);
     73 	else
     74 		fputs("\033[0m",stdout);
     75 }
     76 
     77 void clear_line(void)
     78 {
     79 	fputs(CSI "2K", stdout);
     80 }
     81 
     82 void clear_beginning_of_line(void)
     83 {
     84 	fputs(CSI "1K", stdout);
     85 }
     86 
     87 void move_cursor_to_column(int count)
     88 {
     89 	char buffer[10];
     90         memset(buffer,0,sizeof(buffer));
     91 	sprintf(buffer, CSI "%dG", count);
     92 	fputs(buffer, stdout);
     93 }
     94 
     95 void move_cursor_to_next_line(void)
     96 {
     97 	fputs("\033e", stdout);
     98 }
     99 
    100 void disable_utf8(void)
    101 {
    102 	fputs("\033%@", stdout);
    103 }
    104 
    105 void set_g1_special_char(void){
    106 	fputs("\033)0", stdout);
    107 }
    108 
    109 void set_us_g0_charset(void)
    110 {
    111 	fputs("\033(B\1#0", stdout);
    112 }
    113 
    114 void clear_entire_screen(void)
    115 {
    116 	fputs(CSI "2J", stdout);
    117 }
    118 
    119 /**
    120  * cprint_vga2ansi - given a VGA attribute, print a character
    121  * @chr:	character to print
    122  * @attr:	vga attribute
    123  *
    124  * Convert the VGA attribute @attr to an ANSI escape sequence and
    125  * print it.
    126  * For performance, SGR parameters are cached. To reset them,
    127  * call cprint_vga2ansi('0', '0').
    128  **/
    129 static void cprint_vga2ansi(const char chr, const char attr)
    130 {
    131 	static const char ansi_char[8] = "04261537";
    132 	static uint16_t last_attr = 0x300;
    133 	char buf[16], *p;
    134 
    135     if (chr == '0' && attr == '0') {
    136         last_attr = 0x300;
    137         return;
    138     }
    139 
    140 	if (attr != last_attr) {
    141         bool reset = false;
    142 		p = buf;
    143 		*p++ = '\033';
    144 		*p++ = '[';
    145 
    146 		if (last_attr & ~attr & 0x88) {
    147 			*p++ = '0';
    148 			*p++ = ';';
    149 			/* Reset last_attr to unknown to handle
    150 			 * background/foreground attributes correctly */
    151 			last_attr = 0x300;
    152             reset = true;
    153 		}
    154 		if (attr & 0x08) {
    155 			*p++ = '1';
    156 			*p++ = ';';
    157 		}
    158 		if (attr & 0x80) {
    159 			*p++ = '4';
    160 			*p++ = ';';
    161 		}
    162 		if (reset || (attr ^ last_attr) & 0x07) {
    163 			*p++ = '3';
    164 			*p++ = ansi_char[attr & 7];
    165 			*p++ = ';';
    166 		}
    167 		if (reset || (attr ^ last_attr) & 0x70) {
    168 			*p++ = '4';
    169 			*p++ = ansi_char[(attr >> 4) & 7];
    170 			*p++ = ';';
    171 		}
    172 		p[-1] = 'm';	/* We'll have generated at least one semicolon */
    173 		p[0] = '\0';
    174 
    175 		last_attr = attr;
    176 
    177 		fputs(buf, stdout);
    178 	}
    179 
    180 	putchar(chr);
    181 }
    182 
    183 /*
    184  * cls - clear and initialize the entire screen
    185  *
    186  * Note: when initializing xterm, one has to specify that
    187  * G1 points to the alternate character set (this is not true
    188  * by default). Without the initial printf "\033)0", line drawing
    189  * characters won't be displayed.
    190  */
    191 void cls(void)
    192 {
    193 	fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
    194 
    195     /* Reset SGR parameters cache */
    196     cprint_vga2ansi('0', '0');
    197 }
    198 
    199 void reset_colors(void)
    200 {
    201     csprint(CSI "1D", 0x07);
    202 }
    203 
    204 /**
    205  * cprint - given a VGA attribute, print a single character at cursor
    206  * @chr:	character to print
    207  * @attr:	VGA attribute
    208  * @times:	number of times to print @chr
    209  *
    210  * Note: @attr is a VGA attribute.
    211  **/
    212 void cprint(const char chr, const char attr, unsigned int times)
    213 {
    214 	while (times--)
    215 		cprint_vga2ansi(chr, attr);
    216 }
    217 
    218 /**
    219  * csprint - given a VGA attribute, print a NULL-terminated string
    220  * @str:	string to print
    221  * @attr:	VGA attribute
    222  **/
    223 void csprint(const char *str, const char attr)
    224 {
    225 	while (*str) {
    226 		cprint(*str, attr, 1);
    227 		str++;
    228 	}
    229 }
    230 
    231 /**
    232  * clearwindow - fill a given a region on the screen
    233  * @top, @left, @bot, @right:	coordinates to fill
    234  * @fillchar:			character to use to fill the region
    235  * @fillattr:			character attribute (VGA)
    236  **/
    237 void clearwindow(const char top, const char left, const char bot,
    238 		 const char right, const char fillchar, const char fillattr)
    239 {
    240 	char x;
    241 	for (x = top; x < bot + 1; x++) {
    242 		gotoxy(x, left);
    243 		cprint(fillchar, fillattr, right - left + 1);
    244 	}
    245 }
    246 
    247 
    248