1 /*
2 GUILIB: An example GUI framework library for use with SDL
3 */
4
5 /* A simple dumb terminal scrollable widget */
6
7 #include <stdarg.h>
8 #include <string.h>
9 #include <ctype.h>
10
11 #include "GUI_termwin.h"
12 #include "GUI_loadimage.h"
13
14 #define KEYREPEAT_TIME 100 /* Repeat every 100 ms */
15
GUI_TermWin(int x,int y,int w,int h,SDL_Surface * Font,void (* KeyProc)(SDLKey key,Uint16 unicode),int scrollback)16 GUI_TermWin:: GUI_TermWin(int x, int y, int w, int h, SDL_Surface *Font,
17 void (*KeyProc)(SDLKey key, Uint16 unicode), int scrollback)
18 : GUI_Scrollable(NULL, x, y, w, h)
19 {
20 /* The font surface should be a 16x16 character pixmap */
21 if ( Font == NULL ) {
22 font = GUI_DefaultFont();
23 } else {
24 font = Font;
25 }
26 charh = font->h/16;
27 charw = font->w/16;
28 rows = h/(charh-1); /* Bottom row in font is not displayed */
29 cols = w/charw;
30 if ( scrollback == 0 ) {
31 scrollback = rows;
32 }
33 total_rows = scrollback;
34
35 /* Allocate and clear the character buffer */
36 vscreen = new Uint8[total_rows*cols];
37 Clear();
38
39 /* Set the user-defined keyboard handler */
40 keyproc = KeyProc;
41 repeat_key = SDLK_UNKNOWN;
42 repeat_unicode = 0;
43
44 /* Set key event translation on */
45 translated = SDL_EnableUNICODE(1);
46 }
47
~GUI_TermWin()48 GUI_TermWin:: ~GUI_TermWin()
49 {
50 delete[] vscreen;
51
52 /* Reset key event translation */
53 SDL_EnableUNICODE(translated);
54 }
55
56 void
Display(void)57 GUI_TermWin:: Display(void)
58 {
59 int row, i, j;
60 Uint8 ch;
61 SDL_Rect src;
62 SDL_Rect dst;
63
64 row = first_row+scroll_row;
65 if ( row < 0 ) {
66 row = total_rows+row;
67 }
68 src.w = charw;
69 src.h = charh-1;
70 dst.w = charw;
71 dst.h = charh-1;
72 for ( i=0; i<rows; ++i ) {
73 for ( j=0; j<cols; ++j ) {
74 ch = vscreen[row*cols+j];
75 src.x = (ch%16)*charw;
76 src.y = (ch/16)*charh;
77 dst.x = area.x+j*charw;
78 dst.y = area.y+i*(charh-1);
79 SDL_BlitSurface(font, &src, screen, &dst);
80 }
81 row = (row+1)%total_rows;
82 }
83 changed = 0;
84 }
85
86 int
Scroll(int amount)87 GUI_TermWin:: Scroll(int amount)
88 {
89 if ( amount ) {
90 scroll_row += amount;
91 if ( scroll_row < scroll_min ) {
92 scroll_row = scroll_min;
93 } else
94 if ( scroll_row > scroll_max ) {
95 scroll_row = scroll_max;
96 }
97 changed = 1;
98 }
99 return(scroll_row);
100 }
101
102 void
Range(int & first,int & last)103 GUI_TermWin:: Range(int &first, int &last)
104 {
105 first = scroll_min; last = scroll_max;
106 }
107
108 GUI_status
KeyDown(SDL_keysym key)109 GUI_TermWin:: KeyDown(SDL_keysym key)
110 {
111 GUI_status status;
112
113 status = GUI_PASS;
114 if ( keyproc ) {
115 keyproc(key.sym, key.unicode);
116 repeat_key = key.sym;
117 repeat_unicode = key.unicode;
118 repeat_next = SDL_GetTicks()+5*KEYREPEAT_TIME;
119 status = GUI_YUM;
120 }
121 return(status);
122 }
123
124 GUI_status
KeyUp(SDL_keysym key)125 GUI_TermWin:: KeyUp(SDL_keysym key)
126 {
127 repeat_key = SDLK_UNKNOWN;
128 return(GUI_PASS);
129 }
130
131 void
NewLine(void)132 GUI_TermWin:: NewLine(void)
133 {
134 if ( cur_row == (rows-1) ) {
135 int newrow;
136
137 first_row = (first_row+1)%total_rows;
138 newrow = (first_row+rows-1)%total_rows;
139 memset(&vscreen[newrow*cols], ' ', cols);
140 } else {
141 cur_row += 1;
142 }
143 cur_col = 0;
144 }
145
146 void
AddText(const char * text,int len)147 GUI_TermWin:: AddText(const char *text, int len)
148 {
149 int row;
150
151 while ( len-- ) {
152 switch (*text) {
153 case '\b': {
154 /* Backspace */
155 if ( cur_col > 0 ) {
156 --cur_col;
157 row = (first_row+cur_row)%total_rows;
158 vscreen[row*cols+cur_col] = ' ';
159 }
160 }
161 break;
162
163 case '\r':
164 /* Skip '\n' in "\r\n" sequence */
165 if ( (len > 0) && (*(text+1) == '\n') ) {
166 --len; ++text;
167 }
168 /* Fall through to newline */
169 case '\n': {
170 NewLine();
171 }
172 break;
173
174 default: { /* Put characters on screen */
175 if ( cur_col == cols ) {
176 NewLine();
177 }
178 row = (first_row+cur_row)%total_rows;
179 vscreen[row*cols+cur_col] = *text;
180 cur_col += 1;
181 }
182 break;
183 }
184 ++text;
185 }
186 /* Reset any scrolling, and mark us for update on idle */
187 scroll_row = 0;
188 changed = 1;
189 }
190
191 void
AddText(const char * fmt,...)192 GUI_TermWin:: AddText(const char *fmt, ...)
193 {
194 char text[1024]; /* Caution! Buffer overflow!! */
195 va_list ap;
196
197 va_start(ap, fmt);
198 vsprintf(text, fmt, ap);
199 AddText(text, strlen(text));
200 va_end(ap);
201 }
202
203 void
Clear(void)204 GUI_TermWin:: Clear(void)
205 {
206 /* Clear the virtual screen */
207 memset(vscreen, ' ', total_rows*cols);
208
209 /* Set the first row in buffer, display row in buffer, and
210 current cursor offset.
211 */
212 first_row = total_rows-rows; /* Actual address */
213 scroll_min = -(total_rows-rows); /* Virtual address */
214 scroll_row = 0; /* Virtual address */
215 scroll_max = 0; /* Virtual address */
216 cur_row = 0; /* Virtual address */
217 cur_col = 0; /* Virtual address */
218
219 /* Mark the display for update */
220 changed = 1;
221 }
222
223 int
Changed(void)224 GUI_TermWin:: Changed(void)
225 {
226 return(changed);
227 }
228
229 GUI_status
Idle(void)230 GUI_TermWin:: Idle(void)
231 {
232 GUI_status status;
233
234 status = GUI_PASS;
235
236 /* Perform any necessary key repeat */
237 if ( repeat_key && keyproc ) {
238 if ( repeat_next <= SDL_GetTicks() ) {
239 keyproc(repeat_key, repeat_unicode);
240 repeat_next = SDL_GetTicks()+KEYREPEAT_TIME;
241 }
242 }
243
244 /* Check to see if display contents have changed */
245 if ( changed ) {
246 status = GUI_REDRAW;
247 changed = 0;
248 }
249 return(status);
250 }
251
252 /* change FG/BG colors and transparency */
SetColoring(Uint8 fr,Uint8 fg,Uint8 fb,int bg_opaque,Uint8 br,Uint8 bg,Uint8 bb)253 void GUI_TermWin::SetColoring(Uint8 fr,Uint8 fg,Uint8 fb, int bg_opaque,
254 Uint8 br, Uint8 bg, Uint8 bb)
255 {
256 SDL_Color colors[3]={{br,bg,bb,0},{fr,fg,fb,0}};
257 if (bg_opaque)
258 {
259 SDL_SetColors(font,colors,0,2);
260 SDL_SetColorKey(font,0,0);
261 }
262 else
263 {
264 SDL_SetColors(font,&colors[1],1,1);
265 SDL_SetColorKey(font,SDL_SRCCOLORKEY,0);
266 }
267 }
268