1 /* Public Domain Curses */
2
3 #include "pdcsdl.h"
4
5 #include <stdlib.h>
6 #ifndef PDC_WIDE
7 #include "deffont.h"
8 #endif
9 #include "deficon.h"
10
11 #ifdef PDC_WIDE
12 # ifndef PDC_FONT_PATH
13 # ifdef _WIN32
14 #define PDC_FONT_PATH "C:/Windows/Fonts/lucon.ttf"
15 # elif defined(__APPLE__)
16 #define PDC_FONT_PATH "/Library/Fonts/Courier New.ttf"
17 # else
18 #define PDC_FONT_PATH "/usr/share/fonts/truetype/freefont/FreeMono.ttf"
19 # endif
20 # endif
21 TTF_Font *pdc_ttffont = NULL;
22 int pdc_font_size = 18;
23 #endif
24
25 SDL_Surface *pdc_screen = NULL, *pdc_font = NULL, *pdc_icon = NULL,
26 *pdc_back = NULL, *pdc_tileback = NULL;
27 int pdc_sheight = 0, pdc_swidth = 0, pdc_yoffset = 0, pdc_xoffset = 0;
28
29 SDL_Color pdc_color[256];
30 Uint32 pdc_mapped[256];
31 int pdc_fheight, pdc_fwidth, pdc_flastc;
32 bool pdc_own_screen;
33
34 static int max_height, max_width;
35
36 /* COLOR_PAIR to attribute encoding table. */
37
38 static struct {short f, b;} atrtab[PDC_COLOR_PAIRS];
39
_clean(void)40 static void _clean(void)
41 {
42 #ifdef PDC_WIDE
43 if (pdc_ttffont)
44 {
45 TTF_CloseFont(pdc_ttffont);
46 TTF_Quit();
47 }
48 #endif
49 SDL_FreeSurface(pdc_tileback);
50 SDL_FreeSurface(pdc_back);
51 SDL_FreeSurface(pdc_icon);
52 SDL_FreeSurface(pdc_font);
53
54 SDL_Quit();
55 }
56
PDC_retile(void)57 void PDC_retile(void)
58 {
59 if (pdc_tileback)
60 SDL_FreeSurface(pdc_tileback);
61
62 pdc_tileback = SDL_DisplayFormat(pdc_screen);
63 if (pdc_tileback == NULL)
64 return;
65
66 if (pdc_back)
67 {
68 SDL_Rect dest;
69
70 dest.y = 0;
71
72 while (dest.y < pdc_tileback->h)
73 {
74 dest.x = 0;
75
76 while (dest.x < pdc_tileback->w)
77 {
78 SDL_BlitSurface(pdc_back, 0, pdc_tileback, &dest);
79 dest.x += pdc_back->w;
80 }
81
82 dest.y += pdc_back->h;
83 }
84
85 SDL_BlitSurface(pdc_tileback, 0, pdc_screen, 0);
86 }
87 }
88
PDC_scr_close(void)89 void PDC_scr_close(void)
90 {
91 PDC_LOG(("PDC_scr_close() - called\n"));
92 }
93
PDC_scr_free(void)94 void PDC_scr_free(void)
95 {
96 if (SP)
97 free(SP);
98 }
99
_initialize_colors(void)100 static void _initialize_colors(void)
101 {
102 int i, r, g, b;
103
104 for (i = 0; i < 8; i++)
105 {
106 pdc_color[i].r = (i & COLOR_RED) ? 0xc0 : 0;
107 pdc_color[i].g = (i & COLOR_GREEN) ? 0xc0 : 0;
108 pdc_color[i].b = (i & COLOR_BLUE) ? 0xc0 : 0;
109
110 pdc_color[i + 8].r = (i & COLOR_RED) ? 0xff : 0x40;
111 pdc_color[i + 8].g = (i & COLOR_GREEN) ? 0xff : 0x40;
112 pdc_color[i + 8].b = (i & COLOR_BLUE) ? 0xff : 0x40;
113 }
114
115 /* 256-color xterm extended palette: 216 colors in a 6x6x6 color
116 cube, plus 24 shades of gray */
117
118 for (i = 16, r = 0; r < 6; r++)
119 for (g = 0; g < 6; g++)
120 for (b = 0; b < 6; b++, i++)
121 {
122 pdc_color[i].r = (r ? r * 40 + 55 : 0);
123 pdc_color[i].g = (g ? g * 40 + 55 : 0);
124 pdc_color[i].b = (b ? b * 40 + 55 : 0);
125 }
126
127 for (i = 232; i < 256; i++)
128 pdc_color[i].r = pdc_color[i].g = pdc_color[i].b = (i - 232) * 10 + 8;
129
130 for (i = 0; i < 256; i++)
131 pdc_mapped[i] = SDL_MapRGB(pdc_screen->format, pdc_color[i].r,
132 pdc_color[i].g, pdc_color[i].b);
133 }
134
135 /* open the physical screen -- allocate SP, miscellaneous intialization */
136
PDC_scr_open(int argc,char ** argv)137 int PDC_scr_open(int argc, char **argv)
138 {
139 PDC_LOG(("PDC_scr_open() - called\n"));
140
141 SP = calloc(1, sizeof(SCREEN));
142
143 if (!SP)
144 return ERR;
145
146 pdc_own_screen = !pdc_screen;
147
148 if (pdc_own_screen)
149 {
150 if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0)
151 {
152 fprintf(stderr, "Could not start SDL: %s\n", SDL_GetError());
153 return ERR;
154 }
155
156 atexit(_clean);
157 }
158
159 #ifdef PDC_WIDE
160 if (!pdc_ttffont)
161 {
162 const char *ptsz, *fname;
163
164 if (TTF_Init() == -1)
165 {
166 fprintf(stderr, "Could not start SDL_TTF: %s\n", SDL_GetError());
167 return ERR;
168 }
169
170 ptsz = getenv("PDC_FONT_SIZE");
171 if (ptsz != NULL)
172 pdc_font_size = atoi(ptsz);
173 if (pdc_font_size <= 0)
174 pdc_font_size = 18;
175
176 fname = getenv("PDC_FONT");
177 pdc_ttffont = TTF_OpenFont(fname ? fname : PDC_FONT_PATH,
178 pdc_font_size);
179 }
180
181 if (!pdc_ttffont)
182 {
183 fprintf(stderr, "Could not load font\n");
184 return ERR;
185 }
186
187 TTF_SetFontKerning(pdc_ttffont, 0);
188 TTF_SetFontHinting(pdc_ttffont, TTF_HINTING_MONO);
189
190 SP->mono = FALSE;
191 #else
192 if (!pdc_font)
193 {
194 const char *fname = getenv("PDC_FONT");
195 pdc_font = SDL_LoadBMP(fname ? fname : "pdcfont.bmp");
196 }
197
198 if (!pdc_font)
199 pdc_font = SDL_LoadBMP_RW(SDL_RWFromMem(deffont, sizeof(deffont)), 0);
200
201 if (!pdc_font)
202 {
203 fprintf(stderr, "Could not load font\n");
204 return ERR;
205 }
206
207 SP->mono = !pdc_font->format->palette;
208 #endif
209
210 if (!SP->mono && !pdc_back)
211 {
212 const char *bname = getenv("PDC_BACKGROUND");
213 pdc_back = SDL_LoadBMP(bname ? bname : "pdcback.bmp");
214 }
215
216 if (!SP->mono && (pdc_back || !pdc_own_screen))
217 {
218 SP->orig_attr = TRUE;
219 SP->orig_fore = COLOR_WHITE;
220 SP->orig_back = -1;
221 }
222 else
223 SP->orig_attr = FALSE;
224
225 #ifdef PDC_WIDE
226 TTF_SizeText(pdc_ttffont, "W", &pdc_fwidth, &pdc_fheight);
227 #else
228 pdc_fheight = pdc_font->h / 8;
229 pdc_fwidth = pdc_font->w / 32;
230
231 if (!SP->mono)
232 pdc_flastc = pdc_font->format->palette->ncolors - 1;
233 #endif
234
235 if (pdc_own_screen && !pdc_icon)
236 {
237 const char *iname = getenv("PDC_ICON");
238 pdc_icon = SDL_LoadBMP(iname ? iname : "pdcicon.bmp");
239
240 if (!pdc_icon)
241 pdc_icon = SDL_LoadBMP_RW(SDL_RWFromMem(deficon,
242 sizeof(deficon)), 0);
243
244 if (pdc_icon)
245 SDL_WM_SetIcon(pdc_icon, NULL);
246 }
247
248 if (pdc_own_screen)
249 {
250 const SDL_VideoInfo *info = SDL_GetVideoInfo();
251 max_height = info->current_h;
252 max_width = info->current_w;
253
254 const char *env = getenv("PDC_LINES");
255 pdc_sheight = (env ? atoi(env) : 25) * pdc_fheight;
256
257 env = getenv("PDC_COLS");
258 pdc_swidth = (env ? atoi(env) : 80) * pdc_fwidth;
259
260 pdc_screen = SDL_SetVideoMode(pdc_swidth, pdc_sheight, 0,
261 SDL_SWSURFACE|SDL_ANYFORMAT|SDL_RESIZABLE);
262 }
263 else
264 {
265 if (!pdc_sheight)
266 pdc_sheight = pdc_screen->h - pdc_yoffset;
267
268 if (!pdc_swidth)
269 pdc_swidth = pdc_screen->w - pdc_xoffset;
270 }
271
272 if (!pdc_screen)
273 {
274 fprintf(stderr, "Couldn't create a surface: %s\n", SDL_GetError());
275 return ERR;
276 }
277
278 if (SP->orig_attr)
279 PDC_retile();
280
281 _initialize_colors();
282
283 SDL_EnableUNICODE(1);
284
285 PDC_mouse_set();
286
287 if (pdc_own_screen)
288 PDC_set_title(argc ? argv[0] : "PDCurses");
289
290 SP->lines = PDC_get_rows();
291 SP->cols = PDC_get_columns();
292
293 SP->mouse_wait = PDC_CLICK_PERIOD;
294 SP->audible = FALSE;
295
296 #ifdef PDC_WIDE
297 SP->termattrs = A_COLOR | A_ITALIC | A_PROTECT | A_REVERSE;
298 #else
299 SP->termattrs = A_COLOR | A_PROTECT | A_REVERSE;
300 #endif
301
302 PDC_reset_prog_mode();
303
304 return OK;
305 }
306
307 /* the core of resize_term() */
308
PDC_resize_screen(int nlines,int ncols)309 int PDC_resize_screen(int nlines, int ncols)
310 {
311 if (!pdc_own_screen)
312 return ERR;
313
314 if (nlines && ncols)
315 {
316 while (nlines * pdc_fheight > max_height)
317 nlines--;
318 pdc_sheight = nlines * pdc_fheight;
319 while (ncols * pdc_fwidth > max_width)
320 ncols--;
321 pdc_swidth = ncols * pdc_fwidth;
322 }
323
324 SDL_FreeSurface(pdc_screen);
325
326 pdc_screen = SDL_SetVideoMode(pdc_swidth, pdc_sheight, 0,
327 SDL_SWSURFACE|SDL_ANYFORMAT|SDL_RESIZABLE);
328
329 if (pdc_tileback)
330 PDC_retile();
331
332 SP->resized = FALSE;
333 SP->cursrow = SP->curscol = 0;
334
335 return OK;
336 }
337
PDC_reset_prog_mode(void)338 void PDC_reset_prog_mode(void)
339 {
340 PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
341
342 PDC_flushinp();
343 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
344 }
345
PDC_reset_shell_mode(void)346 void PDC_reset_shell_mode(void)
347 {
348 PDC_LOG(("PDC_reset_shell_mode() - called.\n"));
349
350 SDL_EnableKeyRepeat(0, 0);
351 PDC_flushinp();
352 }
353
PDC_restore_screen_mode(int i)354 void PDC_restore_screen_mode(int i)
355 {
356 }
357
PDC_save_screen_mode(int i)358 void PDC_save_screen_mode(int i)
359 {
360 }
361
PDC_init_pair(short pair,short fg,short bg)362 void PDC_init_pair(short pair, short fg, short bg)
363 {
364 atrtab[pair].f = fg;
365 atrtab[pair].b = bg;
366 }
367
PDC_pair_content(short pair,short * fg,short * bg)368 int PDC_pair_content(short pair, short *fg, short *bg)
369 {
370 *fg = atrtab[pair].f;
371 *bg = atrtab[pair].b;
372
373 return OK;
374 }
375
PDC_can_change_color(void)376 bool PDC_can_change_color(void)
377 {
378 return TRUE;
379 }
380
PDC_color_content(short color,short * red,short * green,short * blue)381 int PDC_color_content(short color, short *red, short *green, short *blue)
382 {
383 *red = DIVROUND(pdc_color[color].r * 1000, 255);
384 *green = DIVROUND(pdc_color[color].g * 1000, 255);
385 *blue = DIVROUND(pdc_color[color].b * 1000, 255);
386
387 return OK;
388 }
389
PDC_init_color(short color,short red,short green,short blue)390 int PDC_init_color(short color, short red, short green, short blue)
391 {
392 pdc_color[color].r = DIVROUND(red * 255, 1000);
393 pdc_color[color].g = DIVROUND(green * 255, 1000);
394 pdc_color[color].b = DIVROUND(blue * 255, 1000);
395
396 pdc_mapped[color] = SDL_MapRGB(pdc_screen->format, pdc_color[color].r,
397 pdc_color[color].g, pdc_color[color].b);
398
399 wrefresh(curscr);
400
401 return OK;
402 }
403