/* PDCurses */ #include "pdcsdl.h" #include #ifndef PDC_WIDE # include "../common/font437.h" #endif #include "../common/iconbmp.h" #ifdef PDC_WIDE # ifndef PDC_FONT_PATH # ifdef _WIN32 # define PDC_FONT_PATH "C:/Windows/Fonts/consola.ttf" # elif defined(__APPLE__) # define PDC_FONT_PATH "/System/Library/Fonts/Menlo.ttc" # else # define PDC_FONT_PATH "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf" # endif # endif TTF_Font *pdc_ttffont = NULL; int pdc_font_size = # ifdef _WIN32 16; # else 17; # endif #endif SDL_Window *pdc_window = NULL; SDL_Surface *pdc_screen = NULL, *pdc_font = NULL, *pdc_icon = NULL, *pdc_back = NULL, *pdc_tileback = NULL; int pdc_sheight = 0, pdc_swidth = 0, pdc_yoffset = 0, pdc_xoffset = 0; SDL_Color pdc_color[PDC_MAXCOL]; Uint32 pdc_mapped[PDC_MAXCOL]; int pdc_fheight, pdc_fwidth, pdc_fthick, pdc_flastc; bool pdc_own_window; static void _clean(void) { #ifdef PDC_WIDE if (pdc_ttffont) { TTF_CloseFont(pdc_ttffont); TTF_Quit(); } #endif SDL_FreeSurface(pdc_tileback); SDL_FreeSurface(pdc_back); SDL_FreeSurface(pdc_icon); SDL_FreeSurface(pdc_font); SDL_DestroyWindow(pdc_window); SDL_Quit(); } void PDC_retile(void) { if (pdc_tileback) SDL_FreeSurface(pdc_tileback); pdc_tileback = SDL_ConvertSurface(pdc_screen, pdc_screen->format, 0); if (pdc_tileback == NULL) return; if (pdc_back) { SDL_Rect dest; dest.y = 0; while (dest.y < pdc_tileback->h) { dest.x = 0; while (dest.x < pdc_tileback->w) { SDL_BlitSurface(pdc_back, 0, pdc_tileback, &dest); dest.x += pdc_back->w; } dest.y += pdc_back->h; } SDL_BlitSurface(pdc_tileback, 0, pdc_screen, 0); } } void PDC_scr_close(void) { PDC_LOG(("PDC_scr_close() - called\n")); } void PDC_scr_free(void) { } static void _initialize_colors(void) { int i, r, g, b; for (i = 0; i < 8; i++) { pdc_color[i].r = (i & COLOR_RED) ? 0xc0 : 0; pdc_color[i].g = (i & COLOR_GREEN) ? 0xc0 : 0; pdc_color[i].b = (i & COLOR_BLUE) ? 0xc0 : 0; pdc_color[i + 8].r = (i & COLOR_RED) ? 0xff : 0x40; pdc_color[i + 8].g = (i & COLOR_GREEN) ? 0xff : 0x40; pdc_color[i + 8].b = (i & COLOR_BLUE) ? 0xff : 0x40; } /* 256-color xterm extended palette: 216 colors in a 6x6x6 color cube, plus 24 shades of gray */ for (i = 16, r = 0; r < 6; r++) for (g = 0; g < 6; g++) for (b = 0; b < 6; b++, i++) { pdc_color[i].r = (r ? r * 40 + 55 : 0); pdc_color[i].g = (g ? g * 40 + 55 : 0); pdc_color[i].b = (b ? b * 40 + 55 : 0); } for (i = 232; i < 256; i++) pdc_color[i].r = pdc_color[i].g = pdc_color[i].b = (i - 232) * 10 + 8; for (i = 0; i < 256; i++) pdc_mapped[i] = SDL_MapRGB(pdc_screen->format, pdc_color[i].r, pdc_color[i].g, pdc_color[i].b); } /* find the display where the mouse pointer is */ int _get_displaynum(void) { SDL_Rect size; int i, xpos, ypos, displays; displays = SDL_GetNumVideoDisplays(); if (displays > 1) { SDL_GetGlobalMouseState(&xpos, &ypos); for (i = 0; i < displays; i++) { SDL_GetDisplayBounds(i, &size); if (size.x <= xpos && xpos < size.x + size.w && size.y <= ypos && ypos < size.y + size.h) return i; } } return 0; } /* open the physical screen -- miscellaneous initialization */ int PDC_scr_open(void) { SDL_Event event; int displaynum = 0; PDC_LOG(("PDC_scr_open() - called\n")); pdc_own_window = !pdc_window; if (pdc_own_window) { if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS) < 0) { fprintf(stderr, "Could not start SDL: %s\n", SDL_GetError()); return ERR; } atexit(_clean); displaynum = _get_displaynum(); } #ifdef PDC_WIDE if (!pdc_ttffont) { const char *ptsz, *fname; if (TTF_Init() == -1) { fprintf(stderr, "Could not start SDL_TTF: %s\n", SDL_GetError()); return ERR; } ptsz = getenv("PDC_FONT_SIZE"); if (ptsz != NULL) pdc_font_size = atoi(ptsz); if (pdc_font_size <= 0) pdc_font_size = 18; fname = getenv("PDC_FONT"); pdc_ttffont = TTF_OpenFont(fname ? fname : PDC_FONT_PATH, pdc_font_size); } if (!pdc_ttffont) { fprintf(stderr, "Could not load font\n"); return ERR; } TTF_SetFontKerning(pdc_ttffont, 0); TTF_SetFontHinting(pdc_ttffont, TTF_HINTING_MONO); SP->mono = FALSE; #else if (!pdc_font) { const char *fname = getenv("PDC_FONT"); pdc_font = SDL_LoadBMP(fname ? fname : "pdcfont.bmp"); } if (!pdc_font) pdc_font = SDL_LoadBMP_RW(SDL_RWFromMem(font437, sizeof(font437)), 0); if (!pdc_font) { fprintf(stderr, "Could not load font\n"); return ERR; } SP->mono = !pdc_font->format->palette; #endif if (!SP->mono && !pdc_back) { const char *bname = getenv("PDC_BACKGROUND"); pdc_back = SDL_LoadBMP(bname ? bname : "pdcback.bmp"); } if (!SP->mono && (pdc_back || !pdc_own_window)) { SP->orig_attr = TRUE; SP->orig_fore = COLOR_WHITE; SP->orig_back = -1; } else SP->orig_attr = FALSE; #ifdef PDC_WIDE TTF_SizeText(pdc_ttffont, "W", &pdc_fwidth, &pdc_fheight); pdc_fthick = pdc_font_size / 20 + 1; #else pdc_fheight = pdc_font->h / 8; pdc_fwidth = pdc_font->w / 32; pdc_fthick = 1; if (!SP->mono) pdc_flastc = pdc_font->format->palette->ncolors - 1; #endif if (pdc_own_window && !pdc_icon) { const char *iname = getenv("PDC_ICON"); pdc_icon = SDL_LoadBMP(iname ? iname : "pdcicon.bmp"); if (!pdc_icon) pdc_icon = SDL_LoadBMP_RW(SDL_RWFromMem(iconbmp, sizeof(iconbmp)), 0); } if (pdc_own_window) { const char *env = getenv("PDC_LINES"); pdc_sheight = (env ? atoi(env) : 25) * pdc_fheight; env = getenv("PDC_COLS"); pdc_swidth = (env ? atoi(env) : 80) * pdc_fwidth; pdc_window = SDL_CreateWindow("PDCurses", SDL_WINDOWPOS_CENTERED_DISPLAY(displaynum), SDL_WINDOWPOS_CENTERED_DISPLAY(displaynum), pdc_swidth, pdc_sheight, SDL_WINDOW_RESIZABLE); if (pdc_window == NULL) { fprintf(stderr, "Could not open SDL window: %s\n", SDL_GetError()); return ERR; } SDL_SetWindowIcon(pdc_window, pdc_icon); } /* Events must be pumped before calling SDL_GetWindowSurface, or initial modifiers (e.g. numlock) will be ignored and out-of-sync. */ SDL_PumpEvents(); /* Wait until window is exposed before getting surface */ while (SDL_PollEvent(&event)) if (SDL_WINDOWEVENT == event.type && SDL_WINDOWEVENT_EXPOSED == event.window.event) break; if (!pdc_screen) { pdc_screen = SDL_GetWindowSurface(pdc_window); if (!pdc_screen) { fprintf(stderr, "Could not open SDL window surface: %s\n", SDL_GetError()); return ERR; } } if (!pdc_sheight) pdc_sheight = pdc_screen->h - pdc_yoffset; if (!pdc_swidth) pdc_swidth = pdc_screen->w - pdc_xoffset; if (SP->orig_attr) PDC_retile(); _initialize_colors(); SDL_StartTextInput(); PDC_mouse_set(); SP->mouse_wait = PDC_CLICK_PERIOD; SP->audible = FALSE; SP->termattrs = A_COLOR | A_UNDERLINE | A_LEFT | A_RIGHT | A_REVERSE; #ifdef PDC_WIDE SP->termattrs |= A_ITALIC; #endif PDC_reset_prog_mode(); return OK; } /* the core of resize_term() */ int PDC_resize_screen(int nlines, int ncols) { if (!pdc_own_window) return ERR; if (nlines && ncols) { #if SDL_VERSION_ATLEAST(2, 0, 5) SDL_Rect max; int top, left, bottom, right; SDL_GetDisplayUsableBounds(0, &max); SDL_GetWindowBordersSize(pdc_window, &top, &left, &bottom, &right); max.h -= top + bottom; max.w -= left + right; while (nlines * pdc_fheight > max.h) nlines--; while (ncols * pdc_fwidth > max.w) ncols--; #endif pdc_sheight = nlines * pdc_fheight; pdc_swidth = ncols * pdc_fwidth; SDL_SetWindowSize(pdc_window, pdc_swidth, pdc_sheight); pdc_screen = SDL_GetWindowSurface(pdc_window); } if (pdc_tileback) PDC_retile(); return OK; } void PDC_reset_prog_mode(void) { PDC_LOG(("PDC_reset_prog_mode() - called.\n")); PDC_flushinp(); } void PDC_reset_shell_mode(void) { PDC_LOG(("PDC_reset_shell_mode() - called.\n")); PDC_flushinp(); } void PDC_restore_screen_mode(int i) { } void PDC_save_screen_mode(int i) { } bool PDC_can_change_color(void) { return TRUE; } int PDC_color_content(short color, short *red, short *green, short *blue) { *red = DIVROUND(pdc_color[color].r * 1000, 255); *green = DIVROUND(pdc_color[color].g * 1000, 255); *blue = DIVROUND(pdc_color[color].b * 1000, 255); return OK; } int PDC_init_color(short color, short red, short green, short blue) { pdc_color[color].r = DIVROUND(red * 255, 1000); pdc_color[color].g = DIVROUND(green * 255, 1000); pdc_color[color].b = DIVROUND(blue * 255, 1000); pdc_mapped[color] = SDL_MapRGB(pdc_screen->format, pdc_color[color].r, pdc_color[color].g, pdc_color[color].b); return OK; }