libpayload: Add PDCurses and ncurses' libform/libmenu
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / sdl1 / pdcdisp.c
1 /* Public Domain Curses */
2
3 #include "pdcsdl.h"
4
5 RCSID("$Id: pdcdisp.c,v 1.35 2008/07/14 04:24:52 wmcbrine Exp $")
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #ifdef CHTYPE_LONG
11
12 # define A(x) ((chtype)x | A_ALTCHARSET)
13
14 chtype acs_map[128] =
15 {
16     A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9),
17     A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
18     A(19), A(20), A(21), A(22), A(23), A(24), A(25), A(26), A(27),
19     A(28), A(29), A(30), A(31), ' ', '!', '"', '#', '$', '%', '&',
20     '\'', '(', ')', '*',
21
22     A(0x1a), A(0x1b), A(0x18), A(0x19),
23
24     '/',
25
26     0xdb,
27
28     '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
29     '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
30     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
31     'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
32
33     A(0x04), 0xb1,
34
35     'b', 'c', 'd', 'e',
36
37     0xf8, 0xf1, 0xb0, A(0x0f), 0xd9, 0xbf, 0xda, 0xc0, 0xc5, 0x2d,
38     0x2d, 0xc4, 0x2d, 0x5f, 0xc3, 0xb4, 0xc1, 0xc2, 0xb3, 0xf3,
39     0xf2, 0xe3, 0xd8, 0x9c, 0xf9,
40
41     A(127)
42 };
43
44 # undef A
45
46 #endif
47
48 Uint32 pdc_lastupdate = 0;
49
50 #define MAXRECT 200     /* maximum number of rects to queue up before
51                            an update is forced; the number was chosen
52                            arbitrarily */
53
54 static SDL_Rect uprect[MAXRECT];       /* table of rects to update */
55 static chtype oldch = (chtype)(-1);    /* current attribute */
56 static int rectcount = 0;              /* index into uprect */
57 static short foregr = -2, backgr = -2; /* current foreground, background */
58
59 /* do the real updates on a delay */
60
61 void PDC_update_rects(void)
62 {
63     if (rectcount)
64     {
65         /* if the maximum number of rects has been reached, we're 
66            probably better off doing a full screen update */
67
68         if (rectcount == MAXRECT)
69             SDL_Flip(pdc_screen);
70         else
71             SDL_UpdateRects(pdc_screen, rectcount, uprect);
72
73         pdc_lastupdate = SDL_GetTicks();
74         rectcount = 0;
75     }
76 }
77
78 /* set the font colors to match the chtype's attribute */
79
80 static void _set_attr(chtype ch)
81 {
82     ch &= (A_COLOR|A_BOLD|A_BLINK|A_REVERSE);
83
84     if (oldch != ch)
85     {
86         short newfg, newbg;
87
88         if (SP->mono)
89             return;
90
91         PDC_pair_content(PAIR_NUMBER(ch), &newfg, &newbg);
92
93         newfg |= (ch & A_BOLD) ? 8 : 0;
94         newbg |= (ch & A_BLINK) ? 8 : 0;
95
96         if (ch & A_REVERSE)
97         {
98             short tmp = newfg;
99             newfg = newbg;
100             newbg = tmp;
101         }
102
103         if (newfg != foregr)
104         {
105             SDL_SetPalette(pdc_font, SDL_LOGPAL, 
106                            pdc_color + newfg, pdc_flastc, 1);
107             foregr = newfg;
108         }
109
110         if (newbg != backgr)
111         {
112             if (newbg == -1)
113                 SDL_SetColorKey(pdc_font, SDL_SRCCOLORKEY, 0);
114             else
115             {
116                 if (backgr == -1)
117                     SDL_SetColorKey(pdc_font, 0, 0);
118
119                 SDL_SetPalette(pdc_font, SDL_LOGPAL,
120                                pdc_color + newbg, 0, 1);
121             }
122
123             backgr = newbg;
124         }
125
126         oldch = ch;
127     }
128 }
129
130 /* draw a cursor at (y, x) */
131
132 void PDC_gotoyx(int row, int col)
133 {
134     SDL_Rect src, dest;
135     chtype ch;
136     int oldrow, oldcol;
137
138     PDC_LOG(("PDC_gotoyx() - called: row %d col %d from row %d col %d\n",
139              row, col, SP->cursrow, SP->curscol));
140
141     if (SP->mono)
142         return;
143
144     oldrow = SP->cursrow;
145     oldcol = SP->curscol;
146
147     /* clear the old cursor */
148
149     PDC_transform_line(oldrow, oldcol, 1, curscr->_y[oldrow] + oldcol);
150
151     if (!SP->visibility)
152         return;
153
154     /* draw a new cursor by overprinting the existing character in 
155        reverse, either the full cell (when visibility == 2) or the 
156        lowest quarter of it (when visibility == 1) */
157
158     ch = curscr->_y[row][col] ^ A_REVERSE;
159
160     _set_attr(ch);
161
162 #ifdef CHTYPE_LONG
163     if (ch & A_ALTCHARSET && !(ch & 0xff80))
164         ch = acs_map[ch & 0x7f];
165 #endif
166     src.h = (SP->visibility == 1) ? pdc_fheight >> 2 : pdc_fheight;
167     src.w = pdc_fwidth;
168
169     dest.y = (row + 1) * pdc_fheight - src.h + pdc_yoffset;
170     dest.x = col * pdc_fwidth + pdc_xoffset;
171
172     src.x = (ch & 0xff) % 32 * pdc_fwidth;
173     src.y = (ch & 0xff) / 32 * pdc_fheight + (pdc_fheight - src.h);
174
175     SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest);
176
177     if (oldrow != row || oldcol != col)
178     {
179         if (rectcount == MAXRECT)
180             PDC_update_rects();
181
182         uprect[rectcount++] = dest;
183     }
184 }
185
186 /* handle the A_*LINE attributes */
187
188 static void _highlight(SDL_Rect *src, SDL_Rect *dest, chtype ch)
189 {
190     short col = SP->line_color;
191
192     if (SP->mono)
193         return;
194
195     if (ch & A_UNDERLINE)
196     {
197         if (col != -1)
198             SDL_SetPalette(pdc_font, SDL_LOGPAL,
199                            pdc_color + col, pdc_flastc, 1);
200
201         src->x = '_' % 32 * pdc_fwidth;
202         src->y = '_' / 32 * pdc_fheight;
203
204         if (backgr != -1)
205             SDL_SetColorKey(pdc_font, SDL_SRCCOLORKEY, 0);
206
207         SDL_BlitSurface(pdc_font, src, pdc_screen, dest);
208
209         if (backgr != -1)
210             SDL_SetColorKey(pdc_font, 0, 0);
211
212         if (col != -1)
213             SDL_SetPalette(pdc_font, SDL_LOGPAL,
214                            pdc_color + foregr, pdc_flastc, 1);
215     }
216
217     if (ch & (A_LEFTLINE|A_RIGHTLINE))
218     {
219         if (col == -1)
220             col = foregr;
221
222         dest->w = 1;
223
224         if (ch & A_LEFTLINE)
225             SDL_FillRect(pdc_screen, dest, pdc_mapped[col]);
226
227         if (ch & A_RIGHTLINE)
228         {
229             dest->x += pdc_fwidth - 1;
230             SDL_FillRect(pdc_screen, dest, pdc_mapped[col]);
231             dest->x -= pdc_fwidth - 1;
232         }
233
234         dest->w = pdc_fwidth;
235     }
236 }
237
238 /* update the given physical line to look like the corresponding line in
239    curscr */
240
241 void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
242 {
243     SDL_Rect src, dest, lastrect;
244     int j;
245
246     PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno));
247
248     if (rectcount == MAXRECT)
249         PDC_update_rects();
250
251     src.h = pdc_fheight;
252     src.w = pdc_fwidth;
253
254     dest.y = pdc_fheight * lineno + pdc_yoffset;
255     dest.x = pdc_fwidth * x + pdc_xoffset;
256     dest.h = pdc_fheight;
257     dest.w = pdc_fwidth * len;
258
259     /* if the previous rect was just above this one, with the same width
260        and horizontal position, then merge the new one with it instead
261        of adding a new entry */
262
263     if (rectcount)
264         lastrect = uprect[rectcount - 1];
265
266     if (rectcount && lastrect.x == dest.x && lastrect.w == dest.w)
267     {
268         if (lastrect.y + lastrect.h == dest.y)
269             uprect[rectcount - 1].h = lastrect.h + pdc_fheight;
270         else
271             if (lastrect.y != dest.y)
272                 uprect[rectcount++] = dest;
273     } 
274     else
275         uprect[rectcount++] = dest;
276
277     dest.w = pdc_fwidth;
278
279     for (j = 0; j < len; j++)
280     {
281         chtype ch = srcp[j];
282
283         _set_attr(ch);
284 #ifdef CHTYPE_LONG
285         if (ch & A_ALTCHARSET && !(ch & 0xff80))
286             ch = (ch & (A_ATTRIBUTES ^ A_ALTCHARSET)) | acs_map[ch & 0x7f];
287 #endif
288         if (backgr == -1)
289             SDL_LowerBlit(pdc_tileback, &dest, pdc_screen, &dest);
290
291         src.x = (ch & 0xff) % 32 * pdc_fwidth;
292         src.y = (ch & 0xff) / 32 * pdc_fheight;
293
294         SDL_LowerBlit(pdc_font, &src, pdc_screen, &dest);
295
296         if (ch & (A_UNDERLINE|A_LEFTLINE|A_RIGHTLINE))
297             _highlight(&src, &dest, ch);
298
299         dest.x += pdc_fwidth;
300     }
301 }