Subversion Repositories Krakow BASIC

Rev

Rev 39 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 39 Rev 40
Line 1... Line 1...
1
/* $Id: x11.c 39 2024-09-06 12:56:29Z nishi $ */
1
/* $Id: x11.c 40 2024-09-06 14:17:50Z nishi $ */
2
 
2
 
3
#include <stdbool.h>
3
#include <stdbool.h>
4
#include <stddef.h>
4
#include <stddef.h>
5
#include <stdint.h>
5
#include <stdint.h>
-
 
6
#include <stdio.h>
-
 
7
#include <pthread.h>
-
 
8
#include <string.h>
-
 
9
#include <ctype.h>
-
 
10
#include <stdlib.h>
6
 
11
 
7
#include <X11/Xlib.h>
12
#include <X11/Xlib.h>
8
#include <X11/Xutil.h>
13
#include <X11/Xutil.h>
9
 
14
 
10
bool stop = false;
15
bool stop = false;
11
bool dorender = false;
16
bool dorender = false;
-
 
17
bool renderall = false;
12
 
18
 
-
 
19
XExposeEvent ex;
-
 
20
 
-
 
21
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
 
22
 
13
const int fontwidth = 7;
23
#define FONTWIDTH 7
14
const int fontheight = 14;
24
#define FONTHEIGHT 14
15
const int textwidth = 80;
25
#define TEXTWIDTH 80
16
const int textheight = 25;
26
#define TEXTHEIGHT 25
17
int width;
27
int width;
18
int height;
28
int height;
19
 
29
 
-
 
30
uint8_t tram[TEXTWIDTH * TEXTHEIGHT];
-
 
31
uint8_t old_tram[TEXTWIDTH * TEXTHEIGHT];
-
 
32
 
20
GC gc;
33
GC gc;
21
Window w;
34
Window w;
22
Display* d;
35
Display* d;
-
 
36
XFontStruct* font;
23
 
37
 
24
int bgc = 0;
38
int bgc = 0;
25
int fgc = 15;
39
int fgc = 15;
26
 
40
 
-
 
41
#define RGB(r,g,b) (((r) << 16) | ((g) << 8) | ((b) << 0))
-
 
42
 
27
uint32_t colors[] = {
43
uint32_t colors[] = {
28
	0x000000
44
	RGB(0, 0, 0),
-
 
45
	RGB(170, 0, 0),
-
 
46
	RGB(0, 170, 0),
-
 
47
	RGB(170, 85, 0),
-
 
48
	RGB(0, 0, 170),
-
 
49
	RGB(170, 0, 170),
-
 
50
	RGB(0, 170, 170),
-
 
51
	RGB(170, 170, 170),
-
 
52
	RGB(85, 85, 85),
-
 
53
	RGB(255, 85, 85),
-
 
54
	RGB(85, 255, 85),
-
 
55
	RGB(255, 255, 85),
-
 
56
	RGB(85, 85, 255),
-
 
57
	RGB(255, 85, 255),
-
 
58
	RGB(85, 255, 255),
-
 
59
	RGB(255, 255, 255)
29
};
60
};
30
 
61
 
-
 
62
/* NOTE: Called from outside */
-
 
63
void change_color(int a){
-
 
64
	pthread_mutex_lock(&mutex);
-
 
65
	fgc = (a >> 4) & 0xf;
-
 
66
	bgc = (a & 0xf);
-
 
67
	renderall = true;
-
 
68
	dorender = true;
-
 
69
	pthread_mutex_unlock(&mutex);
-
 
70
}
-
 
71
 
-
 
72
/* NOTE: Called from outside */
-
 
73
void clear(void){
-
 
74
	pthread_mutex_lock(&mutex);
-
 
75
	int i;
-
 
76
	for(i = 0; i < TEXTWIDTH * TEXTHEIGHT; i++){
-
 
77
		tram[i] = 0x20;
-
 
78
	}
-
 
79
	renderall = true;
-
 
80
	dorender = true;
-
 
81
	pthread_mutex_unlock(&mutex);
-
 
82
}
-
 
83
 
-
 
84
int cx = 0;
-
 
85
int cy = 0;
-
 
86
 
-
 
87
void scroll_y(void){
-
 
88
	cy = TEXTHEIGHT - 1;
-
 
89
	int i;
-
 
90
	for(i = TEXTWIDTH; i < TEXTWIDTH * TEXTHEIGHT; i++){
-
 
91
		tram[i - TEXTWIDTH] = tram[i];
-
 
92
	}
-
 
93
	for(i = 0; i < TEXTWIDTH; i++){
-
 
94
		tram[TEXTWIDTH * TEXTHEIGHT - TEXTWIDTH + i] = 0x20;
-
 
95
	}
-
 
96
}
-
 
97
 
-
 
98
#define maxmacro(a,b) ((a) > (b) ? (a) : (b))
-
 
99
#define minmacro(a,b) ((a) < (b) ? (a) : (b))
-
 
100
 
-
 
101
void putstr(const char* n){
-
 
102
	pthread_mutex_lock(&mutex);
-
 
103
	int i;
-
 
104
	ex.x = cx * TEXTWIDTH;
-
 
105
	ex.y = cy * TEXTHEIGHT;
-
 
106
	ex.width = TEXTWIDTH * FONTWIDTH;
-
 
107
	ex.height = 0;
-
 
108
	for(i = 0; n[i] != 0; i++){
-
 
109
		if(n[i] == '\n'){
-
 
110
			cy++;
-
 
111
			cx = 0;
-
 
112
			if(cy == TEXTHEIGHT){
-
 
113
				scroll_y();
-
 
114
				ex.height += FONTHEIGHT;
-
 
115
			}
-
 
116
		}else if(n[i] == 8){
-
 
117
			if(cx > 0) cx--;
-
 
118
		}else{
-
 
119
			tram[cy * TEXTWIDTH + cx++] = n[i];
-
 
120
			if(cx == TEXTWIDTH){
-
 
121
				cx = 0;
-
 
122
				cy++;
-
 
123
				if(cy == TEXTHEIGHT){
-
 
124
					scroll_y();
-
 
125
					ex.height += FONTHEIGHT;
-
 
126
				}
-
 
127
			}
-
 
128
		}
-
 
129
		ex.x = minmacro(ex.x, cx * TEXTWIDTH);
-
 
130
		ex.y = maxmacro(ex.y, cy * TEXTHEIGHT);
-
 
131
	}
-
 
132
	dorender = true;
-
 
133
	pthread_mutex_unlock(&mutex);
-
 
134
}
-
 
135
 
-
 
136
char x11_putchar(char c){
-
 
137
	char cbuf[2];
-
 
138
	cbuf[0] = c;
-
 
139
	cbuf[1] = 0;
-
 
140
	putstr(cbuf);
-
 
141
}
-
 
142
 
-
 
143
void putnum(int n){
-
 
144
	char number[512];
-
 
145
	sprintf(number, "%d", n);
-
 
146
	putstr(number);
-
 
147
}
-
 
148
 
-
 
149
char keybuffer[64];
-
 
150
 
-
 
151
char oggetch(char wait){
-
 
152
	char c;
-
 
153
	if(wait){
-
 
154
		while((c = keybuffer[0]) == 0);
-
 
155
	}else{
-
 
156
		c = keybuffer[0];
-
 
157
		if(c == 0) return 0;
-
 
158
	}
-
 
159
	pthread_mutex_lock(&mutex);
-
 
160
	int i;
-
 
161
	for(i = 1;; i++){
-
 
162
		keybuffer[i - 1] = keybuffer[i];
-
 
163
		if(keybuffer[i] == 0) break;
-
 
164
	}
-
 
165
	pthread_mutex_unlock(&mutex);
-
 
166
	return c;
-
 
167
}
-
 
168
 
31
void render(void){
169
void render(void){
-
 
170
	pthread_mutex_lock(&mutex);
-
 
171
	if(renderall){
32
	XSetForeground(d, gc, colors[bgc]);
172
		XSetForeground(d, gc, colors[bgc]);
33
	XFillRectangle(d, w, gc, 0, 0, width, height);
173
		XFillRectangle(d, w, gc, 0, 0, width, height);
-
 
174
	}
-
 
175
 
-
 
176
 
-
 
177
	int y, x;
-
 
178
	char cbuf[2];
-
 
179
	cbuf[1] = 0;
-
 
180
	for(y = 0; y < TEXTHEIGHT; y++){
-
 
181
		for(x = 0; x < TEXTWIDTH; x++){
-
 
182
			cbuf[0] = tram[y * TEXTWIDTH + x];
-
 
183
			bool rnd = !renderall && old_tram[y * TEXTWIDTH + x] != cbuf[0];
-
 
184
			if(renderall || rnd){
-
 
185
				XSetForeground(d, gc, colors[bgc]);
-
 
186
				XFillRectangle(d, w, gc, x * FONTWIDTH, y * FONTHEIGHT, FONTWIDTH + 2, FONTHEIGHT + 2);
-
 
187
				XSetForeground(d, gc, colors[fgc]);
-
 
188
				XDrawString(d, w, gc, x * FONTWIDTH, y * FONTHEIGHT + FONTHEIGHT, cbuf, 1);
-
 
189
				if(rnd) old_tram[y * TEXTWIDTH + x] = cbuf[0];
-
 
190
			}
-
 
191
		}
-
 
192
	}
-
 
193
 
34
	XFlush(d);
194
	XFlush(d);
-
 
195
	pthread_mutex_unlock(&mutex);
-
 
196
 
-
 
197
	if(renderall) renderall = false;
-
 
198
}
-
 
199
 
-
 
200
void x11_init(void){
-
 
201
	int i;
-
 
202
	for(i = 0; i < TEXTWIDTH * TEXTHEIGHT; i++){
-
 
203
		tram[i] = 0x20;
-
 
204
		old_tram[i] = 0xff;
-
 
205
	}
35
}
206
}
36
 
207
 
37
void* x11_thread(void* arg){
208
void* x11_thread(void* arg){
38
	width = fontwidth * textwidth;
209
	width = FONTWIDTH * TEXTWIDTH;
39
	height = fontheight * textheight;
210
	height = FONTHEIGHT * TEXTHEIGHT;
-
 
211
 
-
 
212
	int i;
-
 
213
	for(i = 0; i < 64; i++) keybuffer[i] = 0;
40
 
214
 
41
	d = XOpenDisplay(NULL);
215
	d = XOpenDisplay(NULL);
42
	w = XCreateSimpleWindow(d, RootWindow(d, 0), 0, 0, width, height, 3, WhitePixel(d, 0), BlackPixel(d, 0));
216
	w = XCreateSimpleWindow(d, RootWindow(d, 0), 0, 0, width, height, 3, WhitePixel(d, 0), BlackPixel(d, 0));
43
	XStoreName(d, w, "Krakow BASIC");
217
	XStoreName(d, w, "Krakow BASIC");
44
 
218
 
Line 47... Line 221...
47
	size->min_width = size->max_width = width;
221
	size->min_width = size->max_width = width;
48
	size->min_height = size->max_height = height;
222
	size->min_height = size->max_height = height;
49
	XSetWMNormalHints(d, w, size);
223
	XSetWMNormalHints(d, w, size);
50
	XFree(size);
224
	XFree(size);
51
 
225
 
-
 
226
	font = XLoadQueryFont(d, "7x14");
-
 
227
 
52
	XEvent ev;
228
	XEvent ev;
53
 
229
 
54
	XSelectInput(d, w, ExposureMask);
230
	XSelectInput(d, w, ExposureMask | KeyPressMask | KeyReleaseMask);
55
	XMapWindow(d, w);
231
	XMapWindow(d, w);
56
	XFlush(d);
232
	XFlush(d);
57
 
233
 
58
	gc = XCreateGC(d, DefaultRootWindow(d), 0, 0);
234
	gc = XCreateGC(d, DefaultRootWindow(d), 0, 0);
-
 
235
	XSetFont(d, gc, font->fid);
59
 
236
 
-
 
237
	renderall = true;
60
	render();
238
	render();
61
 
239
 
62
	while(1){
240
	while(1){
63
		if(dorender){
241
		if(dorender){
64
			render();
242
			render();
65
			dorender = false;
243
			dorender = false;
66
		}else if(XPending(d) > 0){
244
		}else if(XPending(d) > 0){
67
			XNextEvent(d, &ev);
245
			XNextEvent(d, &ev);
68
			if(ev.type == Expose){
246
			if(ev.type == Expose){
-
 
247
				ex = ev.xexpose;
-
 
248
				renderall = true;
69
				render();
249
				render();
-
 
250
			}else if(ev.type == KeyPress){
-
 
251
				for(i = 0; keybuffer[i] != 0; i++);
-
 
252
				char* k_ = XKeysymToString(XLookupKeysym(&ev.xkey, 0));
-
 
253
				char* k = malloc(strlen(k_) + 1);
-
 
254
				memcpy(k, k_, strlen(k_));
-
 
255
				k[strlen(k_)] = 0;
-
 
256
				if(strcmp(k, "Return") == 0){
-
 
257
					k[0] = '\n';
-
 
258
				}else if(strcmp(k, "BackSpace") == 0){
-
 
259
					k[0] = '\x08';
-
 
260
				}else if(strcmp(k, "space") == 0){
-
 
261
					k[0] = ' ';
-
 
262
				}else if(strcmp(k, "comma") == 0){
-
 
263
					k[0] = ',';
-
 
264
				}else if(strcmp(k, "semicolon") == 0){
-
 
265
					k[0] = ';';
-
 
266
				}else if(strcmp(k, "c") == 0 && ev.xkey.state & ControlMask){
-
 
267
					k[0] = '\x01';
-
 
268
				}else if(strcmp(k, "1") == 0 && ev.xkey.state & ShiftMask){
-
 
269
					k[0] = '!';
-
 
270
				}else if(strcmp(k, "2") == 0 && ev.xkey.state & ShiftMask){
-
 
271
					k[0] = '"';
-
 
272
				}else if(strcmp(k, "3") == 0 && ev.xkey.state & ShiftMask){
-
 
273
					k[0] = '#';
-
 
274
				}else if(strcmp(k, "4") == 0 && ev.xkey.state & ShiftMask){
-
 
275
					k[0] = '$';
-
 
276
				}else if(strcmp(k, "5") == 0 && ev.xkey.state & ShiftMask){
-
 
277
					k[0] = '%';
-
 
278
				}else if(strcmp(k, "6") == 0 && ev.xkey.state & ShiftMask){
-
 
279
					k[0] = '&';
-
 
280
				}else if(strcmp(k, "7") == 0 && ev.xkey.state & ShiftMask){
-
 
281
					k[0] = '\'';
-
 
282
				}else if(strcmp(k, "8") == 0 && ev.xkey.state & ShiftMask){
-
 
283
					k[0] = '(';
-
 
284
				}else if(strcmp(k, "9") == 0 && ev.xkey.state & ShiftMask){
-
 
285
					k[0] = ')';
-
 
286
				}else if(strcmp(k, "0") == 0 && ev.xkey.state & ShiftMask){
-
 
287
					k[0] = '~';
-
 
288
				}else if(strcmp(k, "Control_L") == 0){
-
 
289
					k[0] = '\x00';
-
 
290
				}else if(strcmp(k, "Shift_L") == 0){
-
 
291
					k[0] = '\x00';
-
 
292
				}else if(strcmp(k, "Control_R") == 0){
-
 
293
					k[0] = '\x00';
-
 
294
				}else if(strcmp(k, "Shift_R") == 0){
-
 
295
					k[0] = '\x00';
-
 
296
				}else if(ev.xkey.state & ShiftMask){
-
 
297
					k[0] = toupper(k[0]);
-
 
298
				}
-
 
299
				keybuffer[i] = k[0];
-
 
300
				free(k);
70
			}
301
			}
71
		}
302
		}
72
	}
303
	}
73
	stop = true;
304
	stop = true;
74
	return arg;
305
	return arg;