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