1 /* Public Domain Curses */
2
3 #include "pdcsdl.h"
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #ifdef CHTYPE_LONG
9
10 #ifdef PDC_WIDE
11 #define USE_UNICODE_ACS_CHARS 1
12 #else
13 #define USE_UNICODE_ACS_CHARS 0
14 #endif
15
16 #include "acs_defs.h"
17
18 #endif
19
20 Uint32 pdc_lastupdate = 0;
21
22 #define MAXRECT 200 /* maximum number of rects to queue up before
23 an update is forced; the number was chosen
24 arbitrarily */
25
26 static SDL_Rect uprect[MAXRECT]; /* table of rects to update */
27 static chtype oldch = (chtype)(-1); /* current attribute */
28 static int rectcount = 0; /* index into uprect */
29 static short foregr = -2, backgr = -2; /* current foreground, background */
30
31 /* do the real updates on a delay */
32
PDC_update_rects(void)33 void PDC_update_rects(void)
34 {
35 if (rectcount)
36 {
37 /* if the maximum number of rects has been reached, we're
38 probably better off doing a full screen update */
39
40 if (rectcount == MAXRECT)
41 SDL_Flip(pdc_screen);
42 else
43 SDL_UpdateRects(pdc_screen, rectcount, uprect);
44
45 pdc_lastupdate = SDL_GetTicks();
46 rectcount = 0;
47 }
48 }
49
50 /* set the font colors to match the chtype's attribute */
51
_set_attr(chtype ch)52 static void _set_attr(chtype ch)
53 {
54 ch &= (A_COLOR|A_BOLD|A_BLINK|A_REVERSE);
55
56 if (oldch != ch)
57 {
58 short newfg, newbg;
59
60 if (SP->mono)
61 return;
62
63 PDC_pair_content(PAIR_NUMBER(ch), &newfg, &newbg);
64
65 newfg |= (ch & A_BOLD) ? 8 : 0;
66 newbg |= (ch & A_BLINK) ? 8 : 0;
67
68 if (ch & A_REVERSE)
69 {
70 short tmp = newfg;
71 newfg = newbg;
72 newbg = tmp;
73 }
74
75 if (newfg != foregr)
76 {
77 #ifndef PDC_WIDE
78 SDL_SetPalette(pdc_font, SDL_LOGPAL,
79 pdc_color + newfg, pdc_flastc, 1);
80 #endif
81 foregr = newfg;
82 }
83
84 if (newbg != backgr)
85 {
86 #ifndef PDC_WIDE
87 if (newbg == -1)
88 SDL_SetColorKey(pdc_font, SDL_SRCCOLORKEY, 0);
89 else
90 {
91 if (backgr == -1)
92 SDL_SetColorKey(pdc_font, 0, 0);
93
94 SDL_SetPalette(pdc_font, SDL_LOGPAL,
95 pdc_color + newbg, 0, 1);
96 }
97 #endif
98 backgr = newbg;
99 }
100
101 oldch = ch;
102 }
103 }
104
105 /* draw a cursor at (y, x) */
106
PDC_gotoyx(int row,int col)107 void PDC_gotoyx(int row, int col)
108 {
109 SDL_Rect src, dest;
110 chtype ch;
111 int oldrow, oldcol;
112 #ifdef PDC_WIDE
113 Uint16 chstr[2] = {0, 0};
114 #endif
115
116 PDC_LOG(("PDC_gotoyx() - called: row %d col %d from row %d col %d\n",
117 row, col, SP->cursrow, SP->curscol));
118
119 if (SP->mono)
120 return;
121
122 oldrow = SP->cursrow;
123 oldcol = SP->curscol;
124
125 /* clear the old cursor */
126
127 PDC_transform_line(oldrow, oldcol, 1, curscr->_y[oldrow] + oldcol);
128
129 if (!SP->visibility)
130 return;
131
132 /* draw a new cursor by overprinting the existing character in
133 reverse, either the full cell (when visibility == 2) or the
134 lowest quarter of it (when visibility == 1) */
135
136 ch = curscr->_y[row][col] ^ A_REVERSE;
137
138 _set_attr(ch);
139
140 #ifdef CHTYPE_LONG
141 if (ch & A_ALTCHARSET && !(ch & 0xff80))
142 ch = acs_map[ch & 0x7f];
143 #endif
144 src.h = (SP->visibility == 1) ? pdc_fheight >> 2 : pdc_fheight;
145 src.w = pdc_fwidth;
146
147 dest.y = (row + 1) * pdc_fheight - src.h + pdc_yoffset;
148 dest.x = col * pdc_fwidth + pdc_xoffset;
149
150 #ifdef PDC_WIDE
151 chstr[0] = ch & A_CHARTEXT;
152
153 pdc_font = TTF_RenderUNICODE_Solid(pdc_ttffont, chstr, pdc_color[foregr]);
154 if (pdc_font)
155 {
156 dest.h = src.h;
157 dest.w = src.w;
158 src.x = 0;
159 src.y = 0;
160 SDL_SetColorKey(pdc_font, 0, 0);
161 SDL_SetPalette(pdc_font, SDL_LOGPAL, pdc_color + backgr, 0, 1);
162 SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
163 SDL_FreeSurface(pdc_font);
164 pdc_font = NULL;
165 }
166 #else
167
168 src.x = (ch & 0xff) % 32 * pdc_fwidth;
169 src.y = (ch & 0xff) / 32 * pdc_fheight + (pdc_fheight - src.h);
170
171 SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
172 #endif
173
174 if (oldrow != row || oldcol != col)
175 {
176 if (rectcount == MAXRECT)
177 PDC_update_rects();
178
179 uprect[rectcount++] = dest;
180 }
181 }
182
183 /* handle the A_*LINE attributes */
184
_highlight(SDL_Rect * src,SDL_Rect * dest,chtype ch)185 static void _highlight(SDL_Rect *src, SDL_Rect *dest, chtype ch)
186 {
187 short col = SP->line_color;
188 #ifdef PDC_WIDE
189 Uint16 chstr[2] = {'_', 0};
190 #endif
191
192 if (SP->mono)
193 return;
194
195 if (ch & (A_UNDERLINE | A_OVERLINE | A_STRIKEOUT))
196 {
197 #ifdef PDC_WIDE
198 if (col == -1)
199 col = foregr;
200
201 pdc_font = TTF_RenderUNICODE_Solid(pdc_ttffont, chstr, pdc_color[col]);
202 if (pdc_font)
203 {
204 src->x = 0;
205 src->y = 0;
206
207 if (backgr != -1)
208 SDL_SetColorKey(pdc_font, SDL_SRCCOLORKEY, 0);
209
210 if( ch & A_UNDERLINE)
211 SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
212 if( ch & A_OVERLINE)
213 {
214 dest->y -= pdc_fheight - 1;
215 SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
216 dest->y += pdc_fheight - 1;
217 }
218 if( ch & A_STRIKEOUT)
219 {
220 dest->y -= pdc_fheight / 2;
221 SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
222 dest->y += pdc_fheight / 2;
223 }
224 SDL_FreeSurface(pdc_font);
225 pdc_font = NULL;
226 }
227 #else
228 if (col != -1)
229 SDL_SetPalette(pdc_font, SDL_LOGPAL,
230 pdc_color + col, pdc_flastc, 1);
231
232 src->x = '_' % 32 * pdc_fwidth;
233 src->y = '_' / 32 * pdc_fheight;
234
235 if (backgr != -1)
236 SDL_SetColorKey(pdc_font, SDL_SRCCOLORKEY, 0);
237
238 if( ch & A_UNDERLINE)
239 SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
240 if( ch & A_OVERLINE)
241 {
242 dest->y -= pdc_fheight - 1;
243 SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
244 dest->y += pdc_fheight - 1;
245 }
246 if( ch & A_STRIKEOUT)
247 {
248 dest->y -= pdc_fheight / 2;
249 SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
250 dest->y += pdc_fheight / 2;
251 }
252
253 if (backgr != -1)
254 SDL_SetColorKey(pdc_font, 0, 0);
255
256 if (col != -1)
257 SDL_SetPalette(pdc_font, SDL_LOGPAL,
258 pdc_color + foregr, pdc_flastc, 1);
259 #endif
260 }
261
262 if (ch & (A_LEFTLINE|A_RIGHTLINE))
263 {
264 if (col == -1)
265 col = foregr;
266
267 dest->w = 1;
268
269 if (ch & A_LEFTLINE)
270 SDL_FillRect(pdc_screen, dest, pdc_mapped[col]);
271
272 if (ch & A_RIGHTLINE)
273 {
274 dest->x += pdc_fwidth - 1;
275 SDL_FillRect(pdc_screen, dest, pdc_mapped[col]);
276 dest->x -= pdc_fwidth - 1;
277 }
278
279 dest->w = pdc_fwidth;
280 }
281 }
282
283 /* update the given physical line to look like the corresponding line in
284 curscr */
285
PDC_transform_line(int lineno,int x,int len,const chtype * srcp)286 void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
287 {
288 SDL_Rect src, dest, lastrect;
289 int j;
290 #ifdef PDC_WIDE
291 Uint16 chstr[2] = {0, 0};
292 #endif
293
294 PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno));
295
296 if (rectcount == MAXRECT)
297 PDC_update_rects();
298
299 src.h = pdc_fheight;
300 src.w = pdc_fwidth;
301
302 dest.y = pdc_fheight * lineno + pdc_yoffset;
303 dest.x = pdc_fwidth * x + pdc_xoffset;
304 dest.h = pdc_fheight;
305 dest.w = pdc_fwidth * len;
306
307 /* if the previous rect was just above this one, with the same width
308 and horizontal position, then merge the new one with it instead
309 of adding a new entry */
310
311 if (rectcount)
312 lastrect = uprect[rectcount - 1];
313
314 if (rectcount && lastrect.x == dest.x && lastrect.w == dest.w)
315 {
316 if (lastrect.y + lastrect.h == dest.y)
317 uprect[rectcount - 1].h = lastrect.h + pdc_fheight;
318 else
319 if (lastrect.y != dest.y)
320 uprect[rectcount++] = dest;
321 }
322 else
323 uprect[rectcount++] = dest;
324
325 dest.w = pdc_fwidth;
326
327 #ifdef PDC_WIDE
328 src.x = 0;
329 src.y = 0;
330 #endif
331
332 for (j = 0; j < len; j++)
333 {
334 chtype ch = srcp[j];
335
336 _set_attr(ch);
337 #ifdef CHTYPE_LONG
338 if (ch & A_ALTCHARSET && !(ch & 0xff80))
339 ch = (ch & (A_ATTRIBUTES ^ A_ALTCHARSET)) | acs_map[ch & 0x7f];
340 #endif
341 if (backgr == -1)
342 SDL_LowerBlit(pdc_tileback, &dest, pdc_screen, &dest);
343
344 #ifdef PDC_WIDE
345 chstr[0] = ch & A_CHARTEXT;
346 pdc_font = TTF_RenderUNICODE_Solid(pdc_ttffont, chstr,
347 pdc_color[foregr]);
348
349 if (pdc_font)
350 {
351 if (backgr != -1)
352 {
353 SDL_SetColorKey(pdc_font, 0, 0);
354 SDL_SetPalette(pdc_font, SDL_LOGPAL,
355 pdc_color + backgr, 0, 1);
356 }
357 SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
358 SDL_FreeSurface(pdc_font);
359 pdc_font = NULL;
360 }
361 #else
362 src.x = (ch & 0xff) % 32 * pdc_fwidth;
363 src.y = (ch & 0xff) / 32 * pdc_fheight;
364
365 SDL_LowerBlit(pdc_font, &src, pdc_screen, &dest);
366 #endif
367
368 if (ch & (A_UNDERLINE|A_LEFTLINE|A_RIGHTLINE|A_OVERLINE|A_STRIKEOUT))
369 _highlight(&src, &dest, ch);
370
371 dest.x += pdc_fwidth;
372 }
373 }
374