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