1 // Written in the D programming language.
2 module BearLibTerminal;
3 
4 private import std.string: toStringz, format;
5 private import std.array: join;
6 
7 public alias color_t = uint;
8 
9 private extern (C) {
10 	public struct dimensions_t { int width, height; }
11 	int terminal_open();
12 	void terminal_close();
13 	int terminal_set8(const char*);
14 	char *terminal_get8(const char*, const char*);
15 	void terminal_color(color_t);
16 	void terminal_bkcolor(color_t);
17 	void terminal_composition(int);
18 	void terminal_font8(const char*);
19 	void terminal_layer(int);
20 	void terminal_clear();
21 	void terminal_clear_area(int, int, int, int);
22 	void terminal_crop(int, int, int, int);
23 	void terminal_refresh();
24 	void terminal_put(int, int, int);
25 	int terminal_pick(int, int, int);
26 	color_t terminal_pick_color(int, int, int);
27 	color_t terminal_pick_bkcolor(int, int);
28 	void terminal_put_ext(int, int, int, int, int, color_t*);
29 	void terminal_print_ext8(int, int, int, int, int, const char*, int*, int*);
30 	void terminal_measure_ext8(int, int, const char*, int*, int*);
31 	int terminal_state(int);
32 	int terminal_check(int);
33 	int terminal_has_input();
34 	int terminal_read();
35 	int terminal_peek();
36 	color_t terminal_read_str8(int, int, char*, int);
37 	void terminal_delay(int);
38 	color_t color_from_name8(const char*);
39 	color_t color_from_argb(byte, byte, byte, byte);
40 }
41 
42 // namespace called "terminal"
43 pragma(inline, true) { struct terminal { static {
44 
45 
46 	// Has to be inline, for now
47 	enum keycode {
48 		a = 0x04,
49 		b = 0x05,
50 		c = 0x06,
51 		d = 0x07,
52 		e = 0x08,
53 		f = 0x09,
54 		g = 0x0a,
55 		h = 0x0b,
56 		i = 0x0c,
57 		j = 0x0d,
58 		k = 0x0e,
59 		l = 0x0f,
60 		m = 0x10,
61 		n = 0x11,
62 		o = 0x12,
63 		p = 0x13,
64 		q = 0x14,
65 		r = 0x15,
66 		s = 0x16,
67 		t = 0x17,
68 		u = 0x18,
69 		v = 0x19,
70 		w = 0x1a,
71 		x = 0x1b,
72 		y = 0x1c,
73 		z = 0x1d,
74 		K_1 = 0x1E,
75 		K_2 = 0x1F,
76 		K_3 = 0x20,
77 		K_4 = 0x21,
78 		K_5 = 0x22,
79 		K_6 = 0x23,
80 		K_7 = 0x24,
81 		K_8 = 0x25,
82 		K_9 = 0x26,
83 		K_0 = 0x27,
84 		enter = 0x28,
85 		escape = 0x29,
86 		backspace = 0x2a,
87 		tab = 0x2b,
88 		space = 0x2c,
89 		minus = 0x2d /*  -  */,
90 		equals = 0x2e /*  =  */,
91 		lbracket = 0x2f /*  [  */,
92 		rbracket = 0x30 /*  ]  */,
93 		backslash = 0x31 /*  \  */,
94 		semicolon = 0x33 /*  ,  */,
95 		apostrophe = 0x34 /*  '  */,
96 		grave = 0x35 /*  `  */,
97 		comma = 0x36 /*  ,  */,
98 		period = 0x37 /*  .  */,
99 		slash = 0x38 /*  /  */,
100 		F1 = 0x3A,
101 		F2 = 0x3B,
102 		F3 = 0x3C,
103 		F4 = 0x3D,
104 		F5 = 0x3E,
105 		F6 = 0x3F,
106 		F7 = 0x40,
107 		F8 = 0x41,
108 		F9 = 0x42,
109 		F10 = 0x43,
110 		F11 = 0x44,
111 		F12 = 0x45,
112 		pause = 0x48 /* Pause/Break */,
113 		insert = 0x49,
114 		home = 0x4a,
115 		pageup = 0x4b,
116 		K_delete = 0x4c,
117 		end = 0x4d,
118 		pagedown = 0x4e,
119 		right = 0x4F /* Right arrow */,
120 		left = 0x50 /* Left arrow */,
121 		down = 0x51 /* Down arrow */,
122 		up = 0x52 /* Up arrow */,
123 		KP_divide = 0x54 /* '/' on numpad */,
124 		KP_multiply = 0x55 /* '*' on numpad */,
125 		KP_minus = 0x56 /* '-' on numpad */,
126 		KP_plus = 0x57 /* '+' on numpad */,
127 		KP_enter = 0x58,
128 		KP_1 = 0x59,
129 		KP_2 = 0x5A,
130 		KP_3 = 0x5B,
131 		KP_4 = 0x5C,
132 		KP_5 = 0x5D,
133 		KP_6 = 0x5E,
134 		KP_7 = 0x5F,
135 		KP_8 = 0x60,
136 		KP_9 = 0x61,
137 		KP_0 = 0x62,
138 		kp_period = 0x63 /* '.' on numpad */,
139 		shift = 0x70,
140 		control = 0x71,
141 		ctrl = 0x71, // the same
142 		alt = 0x72,
143 
144 		/*
145 		 * Mouse events/states
146 		 */
147 		mouse_left = 0x80 /* Buttons */,
148 		mouse_right = 0x81,
149 		mouse_middle = 0x82,
150 		mouse_x1 = 0x83,
151 		mouse_x2 = 0x84,
152 		mouse_move = 0x85 /* Movement event */,
153 		mouse_scroll = 0x86 /* Mouse scroll event */,
154 		mouse_x = 0x87 /* Cusor position in cells */,
155 		mouse_y = 0x88,
156 		mouse_pixel_x = 0x89 /* Cursor position in pixels */,
157 		mouse_pixel_y = 0x8A,
158 		mouse_wheel = 0x8B /* Scroll direction and amount */,
159 		mouse_clicks = 0x8C /* Number of consecutive clicks */,
160 
161 		/*
162 		 * If key was released instead of pressed, it's code will be OR'ed with key_released:
163 		 * a) pressed 'A': 0x04
164 		 * b) released 'A': 0x04|terminal.keycodes.key_released = 0x104
165 		 */
166 		key_released = 0x100,
167 
168 		/*
169 		 * Virtual key-codes for internal terminal states/variables.
170 		 * These can be accessed via terminal_state function.
171 		 */
172 		width = 0xC0 /* Terminal window size in cells */,
173 		height = 0xC1,
174 		cell_width = 0xC2 /* Character cell size in pixels */,
175 		cell_height = 0xC3,
176 		color = 0xC4 /* Current foregroung color */,
177 		colour = 0xC4,
178 		bkcolor = 0xC5 /* Current background color */,
179 		bkcolour = 0xC5,
180 		layer = 0xC6 /* Current layer */,
181 		composition = 0xC7 /* Current composition state */,
182 		character = 0xC8 /* Translated ANSI code of last produced character */,
183 		wcharacter = 0xC9 /* Unicode codepoint of last produced character */,
184 		event = 0xCA /* Last dequeued event */,
185 		fullscreen = 0xCB /* Fullscreen state */,
186 
187 		/*
188 		 * Other events
189 		 */
190 		close = 0xe0,
191 		resized = 0xe1,
192 
193 		/*
194 		 * Generic mode enum.
195 		 * Right now it is used for composition option only.
196 		 */
197 		off = 0,
198 		on = 1,
199 
200 		// Input result codes for the terminal_read function.
201 		input_none = 0,
202 		input_cancelled = -1,
203 
204 		// Text printing alignment
205 		align_default = 0,
206 		align_left = 1,
207 		align_right = 2,
208 		align_center = 3,
209 		align_centre = 3,
210 		align_top = 4,
211 		align_bottom = 8,
212 		align_middle = 12
213 	}
214 	alias keycodes = keycode;
215 
216 	int open(string title="BearLibTerminal") { int c = terminal_open(); setf("window.title=%s", title); return c; };
217 	void close() { terminal_close(); };
218 	int set(string[] s...) { return terminal_set8(toStringz(join(s))); };
219 	string get(string key, string defaultval) { import std.conv: to; return to!string(terminal_get8(toStringz(key), toStringz(defaultval))); }
220 	int setf(T...)(string s, T args) { return terminal_set8(toStringz(format(s, args))); }
221 
222 	void color(color_t clr) { terminal_color(clr); };
223 	void color(string clr) { terminal_color(color_from_name(clr)); }
224 	alias colour = color;
225 
226 	void bkcolor(color_t clr) { terminal_bkcolor(clr); };
227 	void bkcolor(string clr) { terminal_bkcolor(color_from_name(clr)); };
228 	alias bkcolour = bkcolor;
229 
230 	void composition(int mode) { terminal_composition(mode); };
231 
232 	void font(string name) { terminal_font8(toStringz(name)); }
233 	void layer(int lyr) { terminal_layer(lyr); };
234 	void clear() { terminal_clear(); };
235 	void clear_area(int x, int y, int w, int h) { terminal_clear_area(x, y, w, h); };
236 	void crop(int x, int y, int w, int h) { terminal_crop(x, y, w, h); };
237 	void refresh() { terminal_refresh(); };
238 	void put(int x, int y, int code) { terminal_put(x, y, code); };
239 	int pick(int x, int y, int index) { return terminal_pick(x, y, index); };
240 	color_t pick_color(int x, int y, int index) { return terminal_pick_color(x, y, index); };
241 	color_t pick_bkcolor(int x, int y) { return terminal_pick_bkcolor(x, y); };
242 	alias pick_colour = pick_color;
243 	alias pick_bkcolour = pick_bkcolor;
244 
245 	void put_ext(int x, int y, int dx, int dy, int code) { terminal_put_ext(x, y, dx, dy, code, null); };
246 	void put_ext(int x, int y, int dx, int dy, int code, color_t[4] corners) { terminal_put_ext(x, y, dx, dy, code, corners.ptr); };
247 
248 	dimensions_t print_ext(int x, int y, int w, int h, int alignment, string[] s...) {
249 		dimensions_t tmp;
250 		terminal_print_ext8(x, y, w, h, alignment, toStringz(join(s)), &tmp.width, &tmp.height);
251 		return tmp;
252 	}
253 	dimensions_t printf_ext(T...)(int x, int y, int w, int h, int alignment, string s, T args) { return print_ext(x, y, w, h, alignment, format(s, args)); }
254 	dimensions_t print(int x, int y, string[] s...) {
255 		return print_ext(x, y, 0, 0, 0, join(s));
256 	};
257 	dimensions_t printf(T...)(int x, int y, string s, T args) { return print(x, y, format(s, args)); };
258 
259 	dimensions_t measure_ext(int w, int h, string[] s...) {
260 		dimensions_t tmp;
261 		terminal_measure_ext8(w, h, toStringz(join(s)), &tmp.width, &tmp.height);
262 		return tmp;
263 	}
264 	dimensions_t measuref_ext(T...)(int w, in h, string s, T args) { return measure_ext(w, h, format(s, args)); }
265 	dimensions_t measure(string[] s...) { return measure_ext(0, 0, s); };
266 	dimensions_t measuref(T...)(string s, T args) { return measure(format(s, args)); };
267 	
268 	int state(int slot) { return terminal_state(slot); };
269 	bool check(int slot) { return terminal_state(slot) > 0; };
270 	int has_input() { return terminal_has_input(); };
271 	keycode read() { return cast(keycode)terminal_read(); };
272 	int peek() { return terminal_peek(); };
273 	string read_str(int x, int y, int max, string prompt="") {
274 		assert (prompt.length <= max);
275 		import std.conv: to;
276 		import core.stdc.stdlib: malloc, free;
277 
278 		print(x, y, prompt);
279 
280 		char[] buf = new char[](max);
281 		buf[] = 0;
282 
283 		string tmp;
284 
285 		terminal_read_str8(x+cast(int)prompt.length, y, buf.ptr, max);
286 		tmp = to!string(buf);
287 		delete buf;
288 		return tmp;
289 	};
290 	void delay(int period) { terminal_delay(period); };
291 	uint color_from_name(string name) { return color_from_name8(toStringz(name)); };
292 	alias colour_from_name = color_from_name;
293 
294 	pure uint color_from_argb(ubyte a, ubyte r, ubyte g, ubyte b) { return (a << 24) | (r << 16) | (g << 8) | b; }
295 	pure uint color_from_rgb(ubyte r, ubyte g, ubyte b) { return (255 << 24) | (r << 16) | (g << 8) | b; }
296 	alias colour_from_argb = color_from_argb;
297 	alias colour_from_rgb = color_from_rgb;
298 
299 }}}