10 void settitle(string title
);
11 void mvaddch(dchar ch
, uint y
, uint x
, RGBColour fg
= RGBColour(0xffffff), RGBColour bg
= RGBColour(0x000000), bool bold
= false, bool italic
= false, bool underline
= false, bool reverse
= false);
14 final void printext(string text
, uint y
, uint x
, RGBColour fg
= RGBColour(0xffffff), RGBColour bg
= RGBColour(0x000000), bool bold
= false, bool italic
= false, bool underline
= false, bool reverse
= false) {
15 import std
.conv
: dtext
;
16 foreach (ch
; dtext(text
)) {
17 mvaddch(ch
, y
, x
++ /* no wrapping, just go off the edge of the screen */, fg
, bg
, bold
, italic
, underline
, reverse
);
23 class SDL0
: CharGfx0
{
24 import derelict
.sdl2
.image
, derelict
.sdl2
.sdl
, derelict
.sdl2
.ttf
, derelict
.sdl2
.mixer
;
26 SDL_Renderer
*renderer
;
27 SDL_Window
*sdl_window
;
29 SDL_Texture
*[] tileset
;
30 SDL_Texture
*[] tileset_italic
;
31 SDL_Texture
*[] tileset_italicbold
;
32 SDL_Texture
*[] tileset_bold
;
35 enum tile_height
= tile_width
* 2;
37 private void sdlerror() {
38 import std
.string
: fromStringz
;
39 throw new Exception(cast(string
)("Error from SDL. SDL says: " ~ fromStringz(SDL_GetError())));
43 private bool loadfont(string fpath
, ushort height
, ref SDL_Texture
*[] target
) {
44 import std
.string
: toStringz
;
46 TTF_Font
*font
= TTF_OpenFont(toStringz(fpath
), height
);
49 SDL_Color white
= SDL_Color(255, 255, 255, 0);
55 TTF_SetFontHinting(font
, TTF_HINTING_NONE
);
56 TTF_SetFontKerning(font
, 0);
60 target
= new SDL_Texture
*[65536];
62 foreach (ushort i
; 0 .. 65536) {
63 if (TTF_GlyphIsProvided(font
, i
)) {
65 surface
= TTF_RenderUNICODE_Blended(font
, text
.ptr
, white
);
66 target
[i
] = SDL_CreateTextureFromSurface(renderer
, surface
);
67 SDL_FreeSurface(surface
);
81 version (dynamic_sdl2
) {
83 DerelictSDL2Image
.load();
84 DerelictSDL2TTF
.load();
85 DerelictSDL2Mixer
.load();
88 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_AUDIO
) == -1) {
92 if (TTF_Init() == -1) {
96 // Title, bunch of stuff, resolution, borderless fullscreen
97 // SDL_WINDOW_FULLSCREEN actually changes the video mode
98 sdl_window
= SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED
, SDL_WINDOWPOS_UNDEFINED
, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP
);
99 // sdl_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP);
100 renderer
= SDL_CreateRenderer(sdl_window
, -1, SDL_RENDERER_ACCELERATED
);
102 if (!loadfont("assets/font/dvsm.ttf", 36, tileset
)) { sdlerror(); }
103 if (!loadfont("assets/font/dvsm-italic.ttf", 36, tileset_italic
)) { sdlerror(); }
104 if (!loadfont("assets/font/dvsm-bolditalic.ttf", 36, tileset_italicbold
)) { sdlerror(); }
105 if (!loadfont("assets/font/dvsm-bold.ttf", 36, tileset_bold
)) { sdlerror(); }
108 if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT
, 2, 2048) < 0) {
111 // no thanks for the formatting, though, you lazy foo!
115 // Blit it to the screen. No magic happening here, just some x11 (or win32 or cocoa or what-have-you) calls
116 SDL_RenderPresent(renderer
);
121 SDL_GetCurrentDisplayMode(0, &dm
);
127 SDL_GetCurrentDisplayMode(0, &dm
);
133 import std
.string
: fromStringz
;
137 SDL_StartTextInput();
139 if (SDL_WaitEvent(&e
) == 1) {
140 if (e
.type
== SDL_TEXTINPUT
) {
141 //return to!dchar(e.text.text);
142 return e
.text
.text
[0];
143 // gained focus, so we need to redraw. IDK why
144 } else if (e
.type
== SDL_WINDOWEVENT
) {
153 void settitle(string title
) { } // TODO
154 void mvaddch(dchar ch
, uint y
, uint x
, RGBColour fg
= RGBColour(0xffffff), RGBColour bg
= RGBColour(0x000000), bool bold
= false, bool italic
= false, bool underline
= false, bool reverse
= false) {
155 SDL_Texture
*renderedchar
;
157 if (ch
> wchar.max
) {
160 writefln("Character %s large, must fit into a wchar (this is an SDL limitation)", ch
);
164 SDL_Texture
*[][][] tilesetset
= [[tileset
, tileset_italic
], [tileset_bold
, tileset_italicbold
]];
165 SDL_Texture
*[] tiles
= tilesetset
[bold
][italic
];
167 // NULL means there's no glyph so fall back to '?'
168 if (tileset
[ch
] is null) {
169 renderedchar
= tileset
['?'];
171 renderedchar
= tileset
[ch
];
174 // We just draw a square with colour bg, then draw the char on top of
175 // it, but with transparency so we see the bg.
179 tile
.y
= y
* tile_height
;
180 tile
.x
= x
* tile_width
;
182 tile
.h
= tile_height
;
184 // Set the colour to draw with
185 SDL_SetRenderDrawColor(renderer
, bg
.r
, bg
.g
, bg
.b
, 255);
188 SDL_RenderFillRect(renderer
, &tile
);
190 // Colourize the letter itself. The parts that aren't the letter will
191 // also get colourized, but that doesn't matter because they have alpha
193 SDL_SetTextureColorMod(renderedchar
, fg
.r
, fg
.g
, fg
.b
);
195 // And finally, copy everything over to the actual renderer
196 SDL_RenderCopy(renderer
, renderedchar
, null, &tile
);
200 foreach (tilesets
; [tileset
, tileset_bold
, tileset_italic
, tileset_italicbold
]) {
201 foreach (ref texture
; tilesets
) {
202 SDL_DestroyTexture(texture
);
206 SDL_DestroyRenderer(renderer
);
207 SDL_DestroyWindow(sdl_window
);
208 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_AUDIO
);
216 class NCurses0
: CharGfx0
{
217 import deimos
.ncurses
;
219 import core
.stdc
.locale
: setlocale
, LC_ALL
;
221 setlocale(LC_ALL
, "en_US.UTF-8");
227 keypad(stdscr
, true);
231 void close() { endwin(); }
233 void refresh() { refresh(); }
239 uint maxx() { return COLS
; }
240 uint maxy() { return LINES
; }
241 void settitle(string title
) {}
243 void mvaddch(dchar ch
, uint y
, uint x
, RGBColour fg
, RGBColour bg
, bool bold
, bool italic
, bool underline
, bool reverse
) {
244 import std
.conv
: text
;
245 import std
.string
: toStringz
;
247 static ushort[ubyte[2]] clrmap
;
248 static ushort maxclrindex
;
250 ubyte[2] clrs
= [get256colour(fg
), get256colour(bg
)];
251 if (clrs
!in clrmap
) {
252 init_pair(maxclrindex
, clrs
[0], clrs
[1]);
253 clrmap
[clrs
] = maxclrindex
++;
257 return (bold ? A_BOLD
: 0) |
/*(italic ? A_ITALIC : 0) | */ (underline ? A_UNDERLINE
: 0) |
(reverse ? A_REVERSE
: 0);
260 attron(attrs() |
COLOR_PAIR(*(clrs
in clrmap
)));
262 mvprintw(y
, x
, toStringz(text(ch
))); // TODO
264 attroff(attrs() |
COLOR_PAIR(*(clrs
in clrmap
)));
271 class BLT0
: CharGfx0
{
272 import BearLibTerminal
;
275 terminal
.set("input.cursor-blink-rate=2147483647");
276 terminal
.set("input.cursor-symbol=0x2588");
278 terminal
.set("font: assets/font/dvsm.ttf, size=12");
279 terminal
.set("default font: assets/font/dvsm.ttf, size=12");
280 terminal
.set("italic font: assets/font/dvsm-italic.ttf, size=12");
281 terminal
.set("bold font: assets/font/dvsm-bold.ttf, size=12");
282 terminal
.set("bolditalic font: assets/font/dvsm-bolditalic.ttf, size=12");
284 // terminal.set("font: use-box-drawing=false, use-block-elements=false");
285 terminal
.set("window.resizeable=true");
287 void close() { terminal
.close(); }
289 void refresh() { terminal
.refresh(); }
291 uint maxx() { return terminal
.state(terminal
.keycode
.width
); }
292 uint maxy() { return terminal
.state(terminal
.keycode
.height
); }
294 void settitle(string title
) {
295 terminal
.setf("window.title=%s", title
);
298 void mvaddch(dchar ch
, uint y
, uint x
, RGBColour fg
, RGBColour bg
, bool bold
, bool italic
, bool underline
, bool reverse
) {
304 terminal
.colour(fg
.toint
);
305 terminal
.bkcolour(bg
.toint
);
308 // it's not beautiful, and it's unclear there even exists an
309 // idiomatic way. But this is the most performant way, and this
310 // is a function that gets called thousands of times per refresh
311 static immutable string
[2][2] fontab
= [["default", "italic"], ["bold", "bolditalic"]];
312 terminal
.font(fontab
[bold
][italic
]);
314 // TODO implement bold and italic (have to load alternate fonts)
315 terminal
.put(x
, y
, ch
);
319 terminal
.put(x
, y
, '▁');
321 terminal
.put(x
, y
, ' ');
325 terminal
.font("default");
330 dchar[terminal
.keycode
] keycode2char
= [terminal
.keycode
.a
: 'a',
331 terminal
.keycode
.b
: 'b',
332 terminal
.keycode
.c
: 'c',
333 terminal
.keycode
.d
: 'd',
334 terminal
.keycode
.e
: 'e',
335 terminal
.keycode
.f
: 'f',
336 terminal
.keycode
.g
: 'g',
337 terminal
.keycode
.h
: 'h',
338 terminal
.keycode
.i
: 'i',
339 terminal
.keycode
.j
: 'j',
340 terminal
.keycode
.k
: 'k',
341 terminal
.keycode
.l
: 'l',
342 terminal
.keycode
.m
: 'm',
343 terminal
.keycode
.n
: 'n',
344 terminal
.keycode
.o
: 'o',
345 terminal
.keycode
.p
: 'p',
346 terminal
.keycode
.q
: 'q',
347 terminal
.keycode
.r
: 'r',
348 terminal
.keycode
.s
: 's',
349 terminal
.keycode
.t
: 't',
350 terminal
.keycode
.u
: 'u',
351 terminal
.keycode
.v
: 'v',
352 terminal
.keycode
.w
: 'w',
353 terminal
.keycode
.x
: 'x',
354 terminal
.keycode
.y
: 'y',
355 terminal
.keycode
.z
: 'z',
356 terminal
.keycode
.KP_1
: '1',
357 terminal
.keycode
.KP_2
: '2',
358 terminal
.keycode
.KP_3
: '3',
359 terminal
.keycode
.KP_4
: '4',
360 terminal
.keycode
.KP_5
: '5',
361 terminal
.keycode
.KP_6
: '6',
362 terminal
.keycode
.KP_7
: '7',
363 terminal
.keycode
.KP_8
: '8',
364 terminal
.keycode
.KP_9
: '9',
365 terminal
.keycode
.KP_0
: '0',
366 terminal
.keycode
.enter: '\n',
367 terminal
.keycode
.escape
: '\033',
368 terminal
.keycode
.backspace
: '\b',
369 terminal
.keycode
.tab
: '\t',
370 terminal
.keycode
.space
: ' ',
371 terminal
.keycode
.minus
: '-',
372 terminal
.keycode
.equals
: '=',
373 terminal
.keycode
.lbracket
: '[',
374 terminal
.keycode
.rbracket
: ']',
375 terminal
.keycode
.backslash
: '\\',
376 terminal
.keycode
.semicolon
: ';',
377 terminal
.keycode
.apostrophe
: '\'',
378 terminal
.keycode
.grave
: '`',
379 terminal
.keycode
.comma
: ',',
380 terminal
.keycode
.period
: '.',
381 terminal
.keycode
.slash
: '/',
394 pause = 0x48 /* Pause/Break */,
401 right = 0x4F /* Right arrow */,
402 left = 0x50 /* Left arrow */,
403 down = 0x51 /* Down arrow */,
404 up = 0x52 /* Up arrow */,
406 terminal
.keycode
.KP_divide
: '/',
407 terminal
.keycode
.KP_multiply
: '*',
408 terminal
.keycode
.KP_minus
: '-',
409 terminal
.keycode
.KP_plus
: '+',
410 terminal
.keycode
.KP_enter
: '\n',
411 terminal
.keycode
.KP_1
: '1',
412 terminal
.keycode
.KP_2
: '2',
413 terminal
.keycode
.KP_3
: '3',
414 terminal
.keycode
.KP_4
: '4',
415 terminal
.keycode
.KP_5
: '5',
416 terminal
.keycode
.KP_6
: '6',
417 terminal
.keycode
.KP_7
: '7',
418 terminal
.keycode
.KP_8
: '8',
419 terminal
.keycode
.KP_9
: '9',
420 terminal
.keycode
.KP_0
: '0',
421 terminal
.keycode
.KP_period
: '.',
427 mouse_left = 0x80 /* Buttons */,
432 mouse_move = 0x85 /* Movement event */,
433 mouse_scroll = 0x86 /* Mouse scroll event */,
434 mouse_x = 0x87 /* Cusor position in cells */,
436 mouse_pixel_x = 0x89 /* Cursor position in pixels */,
437 mouse_pixel_y = 0x8A,
438 mouse_wheel = 0x8B /* Scroll direction and amount */,
439 mouse_clicks = 0x8C /* Number of consecutive clicks */,
443 while ((k
= terminal
.read()) !in keycode2char
) {}
444 return keycode2char
[k
];