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 display_cursor(bool status)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 clear_end_of_line(void)49 void clear_end_of_line(void) 50 { 51 fputs(CSI "0K", stdout); 52 } 53 move_cursor_left(int count)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 move_cursor_right(int count)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 set_cursor_blink(bool status)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 clear_line(void)77 void clear_line(void) 78 { 79 fputs(CSI "2K", stdout); 80 } 81 clear_beginning_of_line(void)82 void clear_beginning_of_line(void) 83 { 84 fputs(CSI "1K", stdout); 85 } 86 move_cursor_to_column(int count)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 move_cursor_to_next_line(void)95 void move_cursor_to_next_line(void) 96 { 97 fputs("\033e", stdout); 98 } 99 disable_utf8(void)100 void disable_utf8(void) 101 { 102 fputs("\033%@", stdout); 103 } 104 set_g1_special_char(void)105 void set_g1_special_char(void){ 106 fputs("\033)0", stdout); 107 } 108 set_us_g0_charset(void)109 void set_us_g0_charset(void) 110 { 111 fputs("\033(B\1#0", stdout); 112 } 113 clear_entire_screen(void)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 **/ cprint_vga2ansi(const char chr,const char attr)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 */ cls(void)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 reset_colors(void)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 **/ cprint(const char chr,const char attr,unsigned int times)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 **/ csprint(const char * str,const char attr)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 **/ clearwindow(const char top,const char left,const char bot,const char right,const char fillchar,const char fillattr)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