ciolib.c 43.4 KB
Newer Older
1
/* $Id: ciolib.c,v 1.204 2020/07/18 18:15:28 rswindell Exp $ */
deuce's avatar
deuce committed
2
3
4
5
6

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
deuce's avatar
deuce committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *																			*
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

34
/* Icon file! */
rswindell's avatar
rswindell committed
35
#ifdef __BORLANDC__
36
#pragma resource "ciolib.res"
		/* DO NOT REMOVE THE EXTRA \r! */
rswindell's avatar
rswindell committed
37
#endif
38

39
#include <stdarg.h>
40
#include <stdlib.h>	/* alloca */
41
#include <stdio.h>
42
43
44
#if defined(_WIN32)
 #include <malloc.h>	/* alloca() on Win32 */
#endif
45

deuce's avatar
deuce committed
46
#include <threadwrap.h>
47
48
#include <genwrap.h>
#include <xpbeep.h>
deuce's avatar
deuce committed
49

50
51
52
#define CIOLIB_NO_MACROS
#include "ciolib.h"

53
#if defined(WITH_SDL)
54
 #include "sdl_con.h"
55
 #include "sdlfuncs.h"
56
#endif
deuce's avatar
deuce committed
57
58
59
#ifdef _WIN32
 #include "win32cio.h"
#else
60
61
62
63
64
65
66
 #ifndef NO_X
  #include "x_cio.h"
 #endif
 #include "curs_cio.h"
 #undef getch
#endif

deuce's avatar
deuce committed
67
#include "bitmap_con.h"
68
#include "ansi_cio.h"
69
#include "syncicon64.h"
70

71
CIOLIBEXPORT cioapi_t	cio_api;
72

73
static const int tabs[]={1,9,17,25,33,41,49,57,65,73,81,89,97,105,113,121,129,137,145};
74
static int ungotch;
75
struct text_info cio_textinfo;
76
77
uint32_t ciolib_fg;
uint32_t ciolib_bg;
deuce's avatar
deuce committed
78
static int lastmode=C80;
79
80
81
CIOLIBEXPORT int _wscroll=1;
CIOLIBEXPORT int directvideo=0;
CIOLIBEXPORT int hold_update=0;
82
CIOLIBEXPORT int puttext_can_move=0;
deuce's avatar
deuce committed
83
CIOLIBEXPORT int ciolib_reaper=TRUE;
84
CIOLIBEXPORT char *ciolib_appname=NULL;
85
86
CIOLIBEXPORT int ciolib_initial_window_height = -1;
CIOLIBEXPORT int ciolib_initial_window_width = -1;
87
88
static int initialized=0;

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
CIOLIBEXPORT int ciolib_movetext(int sx, int sy, int ex, int ey, int dx, int dy);
CIOLIBEXPORT char * ciolib_cgets(char *str);
CIOLIBEXPORT int ciolib_cscanf (char *format , ...);
CIOLIBEXPORT int ciolib_kbhit(void);
CIOLIBEXPORT int ciolib_getch(void);
CIOLIBEXPORT int ciolib_getche(void);
CIOLIBEXPORT int ciolib_ungetch(int ch);
CIOLIBEXPORT void ciolib_gettextinfo(struct text_info *info);
CIOLIBEXPORT int ciolib_wherex(void);
CIOLIBEXPORT int ciolib_wherey(void);
CIOLIBEXPORT void ciolib_wscroll(void);
CIOLIBEXPORT void ciolib_gotoxy(int x, int y);
CIOLIBEXPORT void ciolib_clreol(void);
CIOLIBEXPORT void ciolib_clrscr(void);
CIOLIBEXPORT int ciolib_cputs(char *str);
CIOLIBEXPORT int	ciolib_cprintf(const char *fmat, ...);
CIOLIBEXPORT void ciolib_textbackground(int colour);
CIOLIBEXPORT void ciolib_textcolor(int colour);
CIOLIBEXPORT void ciolib_highvideo(void);
CIOLIBEXPORT void ciolib_lowvideo(void);
CIOLIBEXPORT void ciolib_normvideo(void);
CIOLIBEXPORT int ciolib_puttext(int a,int b,int c,int d,void *e);
CIOLIBEXPORT int ciolib_vmem_puttext(int a,int b,int c,int d,struct vmem_cell *e);
CIOLIBEXPORT int ciolib_gettext(int a,int b,int c,int d,void *e);
CIOLIBEXPORT int ciolib_vmem_gettext(int a,int b,int c,int d,struct vmem_cell *e);
CIOLIBEXPORT void ciolib_textattr(int a);
CIOLIBEXPORT void ciolib_delay(long a);
CIOLIBEXPORT int ciolib_putch(int a);
CIOLIBEXPORT void ciolib_setcursortype(int a);
CIOLIBEXPORT void ciolib_textmode(int mode);
CIOLIBEXPORT void ciolib_window(int sx, int sy, int ex, int ey);
CIOLIBEXPORT void ciolib_delline(void);
CIOLIBEXPORT void ciolib_insline(void);
CIOLIBEXPORT char * ciolib_getpass(const char *prompt);
CIOLIBEXPORT void ciolib_copytext(const char *text, size_t buflen);
CIOLIBEXPORT char * ciolib_getcliptext(void);
CIOLIBEXPORT int ciolib_get_window_info(int *width, int *height, int *xpos, int *ypos);
CIOLIBEXPORT void ciolib_setscaling(int new_value);
CIOLIBEXPORT int ciolib_getscaling(void);
CIOLIBEXPORT int ciolib_setpalette(uint32_t entry, uint16_t r, uint16_t g, uint16_t b);
CIOLIBEXPORT int ciolib_attr2palette(uint8_t attr, uint32_t *fg, uint32_t *bg);
CIOLIBEXPORT int ciolib_setpixel(uint32_t x, uint32_t y, uint32_t colour);
CIOLIBEXPORT struct ciolib_pixels * ciolib_getpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, int force);
CIOLIBEXPORT int ciolib_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_t x_off, uint32_t y_off, struct ciolib_pixels *pixels, void *mask);
CIOLIBEXPORT void ciolib_freepixels(struct ciolib_pixels *pixels);
CIOLIBEXPORT struct ciolib_screen * ciolib_savescreen(void);
CIOLIBEXPORT void ciolib_freescreen(struct ciolib_screen *);
CIOLIBEXPORT int ciolib_restorescreen(struct ciolib_screen *scrn);
CIOLIBEXPORT void ciolib_setcolour(uint32_t fg, uint32_t bg);
CIOLIBEXPORT int ciolib_get_modepalette(uint32_t p[16]);
CIOLIBEXPORT int ciolib_set_modepalette(uint32_t p[16]);
CIOLIBEXPORT void ciolib_set_vmem(struct vmem_cell *cell, uint8_t ch, uint8_t attr, uint8_t font);
CIOLIBEXPORT void ciolib_set_vmem_attr(struct vmem_cell *cell, uint8_t attr);
CIOLIBEXPORT void ciolib_setwinsize(int width, int height);
CIOLIBEXPORT void ciolib_setwinposition(int x, int y);
CIOLIBEXPORT enum ciolib_codepage ciolib_getcodepage(void);
145

146
#if defined(WITH_SDL)
147
148
149
int sdl_video_initialized = 0;
#endif

150
#define CIOLIB_INIT()		{ if(initialized != 1) initciolib(CIOLIB_MODE_AUTO); }
151

152
#if defined(WITH_SDL)
153
static int try_sdl_init(int mode)
154
{
155
	if(!sdl_initciolib(mode)) {
156
		cio_api.mouse=1;
deuce's avatar
deuce committed
157
		cio_api.puttext=bitmap_puttext;
158
159
		cio_api.vmem_puttext=bitmap_vmem_puttext;
		cio_api.vmem_gettext=bitmap_vmem_gettext;
deuce's avatar
deuce committed
160
161
162
163
164
		cio_api.gotoxy=bitmap_gotoxy;
		cio_api.setcursortype=bitmap_setcursortype;
		cio_api.setfont=bitmap_setfont;
		cio_api.getfont=bitmap_getfont;
		cio_api.loadfont=bitmap_loadfont;
165
		cio_api.movetext=bitmap_movetext;
166
167
		cio_api.clreol=bitmap_clreol;
		cio_api.clrscr=bitmap_clrscr;
168
169
		cio_api.getcustomcursor=bitmap_getcustomcursor;
		cio_api.setcustomcursor=bitmap_setcustomcursor;
170
171
		cio_api.getvideoflags=bitmap_getvideoflags;
		cio_api.setvideoflags=bitmap_setvideoflags;
deuce's avatar
deuce committed
172

173
174
175
176
177
		cio_api.kbhit=sdl_kbhit;
		cio_api.getch=sdl_getch;
		cio_api.textmode=sdl_textmode;
		cio_api.showmouse=sdl_showmouse;
		cio_api.hidemouse=sdl_hidemouse;
178
		cio_api.setname=sdl_setname;
179
		cio_api.seticon=sdl_seticon;
180
		cio_api.settitle=sdl_settitle;
181
182
		cio_api.copytext=sdl_copytext;
		cio_api.getcliptext=sdl_getcliptext;
183
		cio_api.get_window_info=sdl_get_window_info;
deuce's avatar
deuce committed
184
185
		cio_api.setwinsize=sdl_setwinsize;
		cio_api.setwinposition=sdl_setwinposition;
186
		cio_api.setpalette=bitmap_setpalette;
187
		cio_api.attr2palette=bitmap_attr2palette;
deuce's avatar
deuce committed
188
		cio_api.setpixel=bitmap_setpixel;
deuce's avatar
deuce committed
189
190
		cio_api.getpixels=bitmap_getpixels;
		cio_api.setpixels=bitmap_setpixels;
deuce's avatar
deuce committed
191
		cio_api.get_modepalette=bitmap_get_modepalette;
deuce's avatar
deuce committed
192
		cio_api.set_modepalette=bitmap_set_modepalette;
193
		cio_api.map_rgb = bitmap_map_rgb;
194
		cio_api.replace_font = bitmap_replace_font;
195
		cio_api.beep = sdl_beep;
deuce's avatar
deuce committed
196
		cio_api.mousepointer=sdl_mousepointer;
197
198
199
200
201
202
		return(1);
	}
	return(0);
}
#endif

203
204
#ifndef _WIN32
 #ifndef NO_X
205
static int try_x_init(int mode)
206
{
207
#if defined(WITH_SDL)
208
	if (sdl_video_initialized) {
209
		sdl.QuitSubSystem(SDL_INIT_VIDEO);
210
	}
211
212
#endif

deuce's avatar
deuce committed
213
	if(!x_init()) {
214
		cio_api.mode=CIOLIB_MODE_X;
deuce's avatar
deuce committed
215
		cio_api.mouse=1;
deuce's avatar
deuce committed
216
		cio_api.puttext=bitmap_puttext;
217
218
		cio_api.vmem_puttext=bitmap_vmem_puttext;
		cio_api.vmem_gettext=bitmap_vmem_gettext;
deuce's avatar
deuce committed
219
220
221
222
223
		cio_api.gotoxy=bitmap_gotoxy;
		cio_api.setcursortype=bitmap_setcursortype;
		cio_api.setfont=bitmap_setfont;
		cio_api.getfont=bitmap_getfont;
		cio_api.loadfont=bitmap_loadfont;
deuce's avatar
deuce committed
224
		cio_api.beep=x_beep;
225
		cio_api.movetext=bitmap_movetext;
226
227
		cio_api.clreol=bitmap_clreol;
		cio_api.clrscr=bitmap_clrscr;
228
229
		cio_api.getcustomcursor=bitmap_getcustomcursor;
		cio_api.setcustomcursor=bitmap_setcustomcursor;
230
231
		cio_api.getvideoflags=bitmap_getvideoflags;
		cio_api.setvideoflags=bitmap_setvideoflags;
232
233

		cio_api.kbhit=x_kbhit;
234
235
		cio_api.getch=x_getch;
		cio_api.textmode=x_textmode;
236
		cio_api.setname=x_setname;
237
		cio_api.settitle=x_settitle;
deuce's avatar
deuce committed
238
239
		cio_api.copytext=x_copytext;
		cio_api.getcliptext=x_getcliptext;
240
		cio_api.get_window_info=x_get_window_info;
241
242
		cio_api.setscaling=x_setscaling;
		cio_api.getscaling=x_getscaling;
deuce's avatar
deuce committed
243
		cio_api.seticon=x_seticon;
244
		cio_api.setpalette=bitmap_setpalette;
245
		cio_api.attr2palette=bitmap_attr2palette;
deuce's avatar
deuce committed
246
		cio_api.setpixel=bitmap_setpixel;
deuce's avatar
deuce committed
247
		cio_api.getpixels=bitmap_getpixels;
deuce's avatar
deuce committed
248
		cio_api.setpixels=bitmap_setpixels;
deuce's avatar
deuce committed
249
		cio_api.get_modepalette=bitmap_get_modepalette;
deuce's avatar
deuce committed
250
		cio_api.set_modepalette=bitmap_set_modepalette;
251
		cio_api.map_rgb = bitmap_map_rgb;
252
		cio_api.replace_font = bitmap_replace_font;
253
		cio_api.mousepointer=x_mousepointer;
254
255
256
257
258
259
		return(1);
	}
	return(0);
}
 #endif

260
static int try_curses_init(int mode)
261
{
262
#if defined(WITH_SDL)
263
	if (sdl_video_initialized) {
264
		sdl.QuitSubSystem(SDL_INIT_VIDEO);
265
	}
266
267
#endif

268
	if(curs_initciolib(mode)) {
269
270
271
		if(mode==CIOLIB_MODE_AUTO)
			mode=CIOLIB_MODE_CURSES;
		cio_api.mode=mode;
272
		cio_api.puttext=curs_puttext;
273
274
		cio_api.vmem_puttext=curs_vmem_puttext;
		cio_api.vmem_gettext=curs_vmem_gettext;
275
276
277
278
279
280
		cio_api.textattr=curs_textattr;
		cio_api.kbhit=curs_kbhit;
		cio_api.gotoxy=curs_gotoxy;
		cio_api.setcursortype=curs_setcursortype;
		cio_api.getch=curs_getch;
		cio_api.textmode=curs_textmode;
deuce's avatar
deuce committed
281
282
		cio_api.showmouse=curs_showmouse;
		cio_api.hidemouse=curs_hidemouse;
283
284
		cio_api.suspend=curs_suspend;
		cio_api.resume=curs_resume;
285
		cio_api.beep=curs_beep;
286
287
		cio_api.setvideoflags=curs_setvideoflags;
		cio_api.getvideoflags=curs_getvideoflags;
288
#if defined(NCURSES_VERSION_MAJOR) || defined (__NetBSD__)
289
		cio_api.escdelay=&ESCDELAY;
290
#endif
291
292
293
294
295
		cio_api.setfont = curs_setfont;
		cio_api.getfont = curs_getfont;
		cio_api.setpalette = curs_setpalette;
		cio_api.get_modepalette = curs_get_modepalette;
		cio_api.set_modepalette = curs_set_modepalette;
deuce's avatar
deuce committed
296
		cio_api.attr2palette = curs_attr2palette;
297
298
299
300
301
302
		return(1);
	}
	return(0);
}
#endif

303
static int try_ansi_init(int mode)
304
{
305
#if defined(WITH_SDL)
306
	if (sdl_video_initialized) {
307
		sdl.QuitSubSystem(SDL_INIT_VIDEO);
308
	}
309
310
#endif

311
	if(ansi_initciolib(mode)) {
312
		cio_api.mode=CIOLIB_MODE_ANSI;
deuce's avatar
deuce committed
313
		cio_api.mouse=0;
314
315
316
317
318
319
320
321
		cio_api.puttext=ansi_puttext;
		cio_api.gettext=ansi_gettext;
		cio_api.textattr=ansi_textattr;
		cio_api.kbhit=ansi_kbhit;
		cio_api.gotoxy=ansi_gotoxy;
		cio_api.setcursortype=ansi_setcursortype;
		cio_api.getch=ansi_getch;
		cio_api.textmode=ansi_textmode;
322
		cio_api.escdelay=&CIOLIB_ANSI_TIMEOUT;
deuce's avatar
deuce committed
323
		cio_api.beep=ansi_beep;
324
		cio_api.suspend=ansi_suspend;
325
326
327
328
329
330
		return(1);
	}
	return(0);
}

#ifdef _WIN32
331
332
333
#if defined(__BORLANDC__)
        #pragma argsused
#endif
334
static int try_conio_init(int mode)
335
{
336
#if defined(WITH_SDL)
337
	if (sdl_video_initialized) {
338
		sdl.QuitSubSystem(SDL_INIT_VIDEO);
339
	}
340
341
#endif

342
	/* This should test for something or other */
343
	if(win32_initciolib(mode)) {
344
345
346
347
		if(mode==CIOLIB_MODE_AUTO)
			cio_api.mode=CIOLIB_MODE_CONIO;
		else
			cio_api.mode=mode;	/* CIOLIB_MODE_CONIO or CIOLIB_MODE_CONIO_FULLSCREEN */
deuce's avatar
deuce committed
348
		cio_api.mouse=1;
349
350
		cio_api.puttext=win32_puttext;
		cio_api.gettext=win32_gettext;
deuce's avatar
deuce committed
351
		cio_api.kbhit=win32_kbhit;
352
353
		cio_api.gotoxy=win32_gotoxy;
		cio_api.setcursortype=win32_setcursortype;
deuce's avatar
deuce committed
354
		cio_api.getch=win32_getch;
355
		cio_api.textmode=win32_textmode;
deuce's avatar
deuce committed
356
357
		cio_api.showmouse=win32_showmouse;
		cio_api.hidemouse=win32_hidemouse;
358
		cio_api.setname=win32_settitle;
359
		cio_api.settitle=win32_settitle;
deuce's avatar
deuce committed
360
361
		cio_api.copytext=win32_copytext;
		cio_api.getcliptext=win32_getcliptext;
362
363
		cio_api.suspend=win32_suspend;
		cio_api.resume=win32_resume;
364
365
		cio_api.getcustomcursor=win32_getcustomcursor;
		cio_api.setcustomcursor=win32_setcustomcursor;
366
		cio_api.getvideoflags=win32_getvideoflags;
367
		cio_api.setpalette=win32_setpalette;
368
369
370
371
372
373
		return(1);
	}
	return(0);
}
#endif

374
/* Optional */
375
CIOLIBEXPORT void suspendciolib(void)
376
{
377
	ciolib_clrscr();
378
379
380
381
382
	if(cio_api.suspend != NULL)
		cio_api.suspend();
	initialized=-1;
}

383
CIOLIBEXPORT int initciolib(int mode)
384
{
385
386
387
388
	switch(initialized) {
		case 1:
			return(0);
		case -1:
389
			initialized=1;
390
391
			if(cio_api.resume != NULL)
				cio_api.resume();
392
			ciolib_clrscr();
393
394
395
			return(0);
	}

396
397
	memset(&cio_api,0,sizeof(cio_api));

398
	switch(mode) {
399
		case CIOLIB_MODE_AUTO:
400
#if defined(WITH_SDL)
401
			if(!try_sdl_init(CIOLIB_MODE_SDL))
402
#endif
403
#ifdef _WIN32
404
				if(!try_conio_init(mode))
405
#else
406
#ifndef NO_X
407
				if(!try_x_init(mode))
408
#endif
409
					if(!try_curses_init(mode))
410
#endif
411
						try_ansi_init(mode);
412
413
			break;
#ifdef _WIN32
414
		case CIOLIB_MODE_CONIO:
415
		case CIOLIB_MODE_CONIO_FULLSCREEN:
416
			try_conio_init(mode);
417
418
			break;
#else
419
420
		case CIOLIB_MODE_CURSES:
		case CIOLIB_MODE_CURSES_IBM:
deuce's avatar
deuce committed
421
		case CIOLIB_MODE_CURSES_ASCII:
422
423
			try_curses_init(mode);
			break;
424

425
		case CIOLIB_MODE_X:
426
#ifndef NO_X
427
			try_x_init(mode);
428
#endif
429
430
			break;
#endif
431
		case CIOLIB_MODE_ANSI:
432
433
			try_ansi_init(mode);
			break;
434

435
#if defined(WITH_SDL)
436
		case CIOLIB_MODE_SDL:
437
		case CIOLIB_MODE_SDL_FULLSCREEN:
438
439
440
			try_sdl_init(mode);
			break;
#endif
441
	}
442
	if(cio_api.mode==CIOLIB_MODE_AUTO) {
deuce's avatar
deuce committed
443
		fprintf(stderr,"CIOLIB initialization failed!\n");
444
445
446
447
448
449
450
451
		return(-1);
	}

	initialized=1;
	cio_textinfo.winleft=1;
	cio_textinfo.wintop=1;
	cio_textinfo.winright=cio_textinfo.screenwidth;
	cio_textinfo.winbottom=cio_textinfo.screenheight;
452
453

	/* Default C64 is Lt Blue on Dark Blue (As per Every picture ever) */
deuce's avatar
Typo.    
deuce committed
454
	switch(cio_textinfo.currmode) {
455
		case C64_40X25:
456
457
			cio_textinfo.normattr=0x6e;
			break;
458
		case C128_40X25:
459
			cio_textinfo.normattr=0xbd;
460
461
			break;
		default:
deuce's avatar
deuce committed
462
			cio_textinfo.normattr=LIGHTGRAY;
463
			break;
464
	}
465
	ciolib_seticon(syncicon64, SYNCICON64_WIDTH);
466
	ciolib_textattr(cio_textinfo.normattr);
467

deuce's avatar
deuce committed
468
	_beginthread(ciolib_mouse_thread,0,NULL);
469
470
471
	return(0);
}

472
/* **MUST** be implemented */
473
474
475
/*
 * Returns non-zero if a key is hit
 */
476
CIOLIBEXPORT int ciolib_kbhit(void)
477
{
478
	CIOLIB_INIT();
479
480
481
482
483
	if(ungotch)
		return(1);
	return(cio_api.kbhit());
}

484
/* **MUST** be implemented */
485
CIOLIBEXPORT int ciolib_getch(void)
486
487
488
{
	int ch;

489
490
	CIOLIB_INIT();

491
492
493
494
495
496
497
498
	if(ungotch) {
		ch=ungotch;
		ungotch=0;
		return(ch);
	}
	return(cio_api.getch());
}

499
/* Optional */
500
CIOLIBEXPORT int ciolib_getche(void)
501
502
503
{
	int ch;

504
505
	CIOLIB_INIT();

506
507
508
509
510
511
	if(ungotch) {
		ch=ungotch;
		ungotch=0;
		ciolib_putch(ch);
		return(ch);
	}
512
	if(cio_api.getche)
513
514
515
516
		return(cio_api.getche());
	else {
		while(1) {
			ch=ciolib_getch();
517
			if(ch != 0 && ch != 0xe0) {
518
519
520
				ciolib_putch(ch);
				return(ch);
			}
521
522
523
			/* Eat extended chars - except ESC which is an abort */
			if(ciolib_getch()==1)
				return(EOF);
524
525
		}
	}
526
527
}

528
/* Optional */
529
530
531
/*
 * On success, returns ch, on error, returns EOF
 */
532
CIOLIBEXPORT int ciolib_ungetch(int ch)
533
{
534
	CIOLIB_INIT();
535

536
537
	if(ungotch)
		return(EOF);
538
539
	if(cio_api.ungetch)
		return(cio_api.ungetch(ch));
540
541
542
543
	ungotch=ch;
	return(ch);
}

544
/* Optional */
545
546
547
/*
 * Returns non-zero on success
 */
548
CIOLIBEXPORT int ciolib_movetext(int sx, int sy, int ex, int ey, int dx, int dy)
549
550
551
{
	int width;
	int height;
552
	void *buf;
553

554
	CIOLIB_INIT();
555
556

	if(cio_api.movetext != NULL)
deuce's avatar
deuce committed
557
		return(cio_api.movetext(sx, sy, ex, ey, dx, dy));
558

559
560
	width=ex-sx;
	height=ey-sy;
561
562
563
	if (cio_api.vmem_gettext) {
		buf=malloc((width+1)*(height+1)*sizeof(struct vmem_cell));
		if (buf == NULL)
564
			return 0;
565
		if(!ciolib_vmem_gettext(sx,sy,ex,ey,buf))
566
			goto fail;
567
		if(!ciolib_vmem_puttext(dx,dy,dx+width,dy+height,buf))
568
569
570
			goto fail;
	}
	else {
571
572
573
		buf=malloc((width+1)*(height+1)*2);
		if (buf == NULL)
			return 0;
574
575
576
577
578
579
		if(!ciolib_gettext(sx,sy,ex,ey,buf))
			goto fail;
		if(!ciolib_puttext(dx,dy,dx+width,dy+height,buf))
			goto fail;
	}

580
	return(1);
deuce's avatar
deuce committed
581
582
583
584

fail:
	free(buf);
	return 0;
585
586
}

587
/* Optional */
588
589
590
591
/*
 * Returns &str[2]
 * Cannot fail
 */
592
CIOLIBEXPORT char * ciolib_cgets(char *str)
593
594
595
596
597
{
	int	maxlen;
	int len=0;
	int ch;

598
	CIOLIB_INIT();
599

600
601
602
	if(cio_api.cgets)
		return(cio_api.cgets(str));

603
	maxlen=*(unsigned char *)str;
604
	while((ch=ciolib_getch())!='\n' && ch !='\r') {
605
		switch(ch) {
606
607
608
609
			case 0:		/* Skip extended keys */
			case 0xe0:	/* Skip extended keys */
				if(ciolib_getche()==1)
					goto early_return;
610
611
612
				break;
			case '\b':
				if(len==0) {
613
					ciolib_putch(7);
614
615
616
617
618
619
					break;
				}
				ciolib_putch('\b');
				len--;
				break;
			default:
620
				ciolib_putch(ch);
621
622
623
624
				str[(len++)+2]=ch;
				if(len==maxlen) {
					str[len+2]=0;
					*((unsigned char *)(str+1))=(unsigned char)len;
deuce's avatar
deuce committed
625
					ciolib_putch('\r');
626
					ciolib_putch('\n');
627
628
629
630
631
					return(&str[2]);
				}
				break;
		}
	}
deuce's avatar
deuce committed
632
early_return:
633
634
	str[len+2]=0;
	*((unsigned char *)(str+1))=(unsigned char)len;
deuce's avatar
deuce committed
635
	ciolib_putch('\r');
636
	ciolib_putch('\n');
637
	return(&str[2]);
638
639
}

deuce's avatar
deuce committed
640
#if defined(_MSC_VER) && (_MSC_VER < 1800)	/* Use lame vsscanf() implementation */
641
642
643
644
645
646
647
648
649
650
651
/* This is a way to do _vsscanf without using fancy stack tricks or using the
 * "_input" method provided by Microsoft, which is no longer exported as of .NET.
 * The function has a limit of 25 arguments (or less if you run out of stack space),
 *  but how many arguments do you need?
 */
/* From "krabsheva" - http://www.codeguru.com/Cpp/Cpp/string/comments.php/c5631/?thread=1051 */
int vsscanf( const char *buffer, const char *format, va_list arg_ptr )
{
	int i, ret;
	void *arg_arr[25];

652
	/* Do exception handling in case we go too far // */
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
	__try
	{
		for ( i = 0; i < 25; i++ )
			arg_arr[i] = va_arg( arg_ptr, void * );
	}
	__except( EXCEPTION_EXECUTE_HANDLER )
	{
	}

	/* This is lame, but the extra arguments won't be used by sscanf */
	ret = sscanf( buffer, format, arg_arr[0], arg_arr[1], arg_arr[2], arg_arr[3],
		arg_arr[4], arg_arr[5], arg_arr[6], arg_arr[7], arg_arr[8], arg_arr[9],
		arg_arr[10], arg_arr[11], arg_arr[12], arg_arr[13], arg_arr[14],
		arg_arr[15], arg_arr[16], arg_arr[17], arg_arr[18], arg_arr[19],
		arg_arr[20], arg_arr[21], arg_arr[22], arg_arr[23], arg_arr[24] );

	return ret;
}
#endif

673
674
/* Can't be overridden */
/* Returns the number of fields converted */
675
CIOLIBEXPORT int ciolib_cscanf (char *format , ...)
676
677
678
679
680
{
	char str[255];
    va_list argptr;
	int ret;

681
	CIOLIB_INIT();
682

683
684
685
686
687
688
689
	str[0]=-1;
	va_start(argptr,format);
	ret=vsscanf(ciolib_cgets(str),format,argptr);
	va_end(argptr);
	return(ret);
}

690
/* Optional */
691
/* So dumb */
692
CIOLIBEXPORT char * ciolib_getpass(const char *prompt)
693
694
695
696
697
{
	static char pass[9];
	int len=0;
	int ch;

698
	CIOLIB_INIT();
699
700
701
702

	if(cio_api.getpass)
		return(cio_api.getpass(prompt));

703
	ciolib_cputs((char *)prompt);
deuce's avatar
deuce committed
704
	while((ch=ciolib_getch())!='\n') {
705
		switch(ch) {
706
707
708
709
			case 0:		/* Skip extended keys */
			case 0xe0:	/* Skip extended keys */
				if(ciolib_getch()==1)
					goto early_return;
710
711
712
713
714
				break;
			case '\r':	/* Skip \r (ToDo: Should this be treeated as a \n? */
				break;
			case '\b':
				if(len==0) {
715
					ciolib_putch(7);
716
717
718
719
720
721
					break;
				}
				len--;
				break;
			default:
				if(len==8)
722
					ciolib_putch(7);
723
724
725
726
727
				else
					pass[len++]=ch;
				break;
		}
	}
728
early_return:
729
730
	pass[len]=0;
	return(pass);
731
732
}

733
734
/* TODO: Hackery here... must fix */
/* Optional */
735
CIOLIBEXPORT void ciolib_gettextinfo(struct text_info *info)
736
{
737
738
	CIOLIB_INIT()

deuce's avatar
deuce committed
739
	if(cio_api.gettextinfo)
740
		cio_api.gettextinfo(&cio_textinfo);
741

742
743
	if(info!=&cio_textinfo)
		*info=cio_textinfo;
744
745
}

746
/* Optional */
747
/* Not part of Borland conio? */
748
CIOLIBEXPORT void ciolib_wscroll(void)
749
750
751
{
	int os;

752
	CIOLIB_INIT();
753

754
	if(cio_api.wscroll!=NULL) {
755
756
757
		cio_api.wscroll();
		return;
	}
758
759
	if(!_wscroll)
		return;
760
761
762
763
764
765
766
	ciolib_movetext(cio_textinfo.winleft
			,cio_textinfo.wintop+1
			,cio_textinfo.winright
			,cio_textinfo.winbottom
			,cio_textinfo.winleft
			,cio_textinfo.wintop);
	ciolib_gotoxy(1,cio_textinfo.winbottom-cio_textinfo.wintop+1);
767
768
	os=_wscroll;
	_wscroll=0;
769
770
	/* ciolib_cprintf("%*s",ti.winright-ti.winleft+1,""); */
	ciolib_clreol();
771
	_wscroll=os;
772
	ciolib_gotoxy(cio_textinfo.curx,cio_textinfo.cury);
773
774
}

775
/* Optional */
776
/* Cannot fail */
777
CIOLIBEXPORT int ciolib_wherex(void)
778
779
780
{
	int x;

781
	CIOLIB_INIT();
782
783
784
785
786
787
788
789

	if(cio_api.wherex) {
		/* TODO: This is old hackery... beware */
		x=cio_api.wherex();
		x=x-cio_textinfo.winleft+1;
	}
	else
		x=cio_textinfo.curx;
790
791
792
	return(x);
}

793
/* Optional */
794
/* Cannot fail */
795
CIOLIBEXPORT int ciolib_wherey(void)
796
797
798
{
	int y;

799
	CIOLIB_INIT();
800
801
802
803
804
805
806
807

	if(cio_api.wherey) {
		/* TODO: This is old hackery... beware */
		y=cio_api.wherey();
		y=y-cio_textinfo.wintop+1;
	}
	else
		y=cio_textinfo.cury;
808
809
810
	return(y);
}

811
/* **MUST** be implemented */
812
CIOLIBEXPORT void ciolib_gotoxy(int x, int y)
813
{
814
	CIOLIB_INIT();
815

816
	if(		x < 1
817
			|| x > cio_textinfo.winright-cio_textinfo.winleft+1
818
			|| y < 1
819
			|| y > cio_textinfo.winbottom-cio_textinfo.wintop+1)
820
		return;
821
	cio_api.gotoxy(x,y);
822
823
}

824
/* **MUST** be implemented */
825
CIOLIBEXPORT void ciolib_textmode(int mode)
826
{
827
	CIOLIB_INIT();
828

deuce's avatar
deuce committed
829
	if(mode==LASTMODE) {
830
831
832
833
		cio_api.textmode(lastmode);
		lastmode=cio_textinfo.currmode;
	}
	else {
834
835
		if(mode==64)
			mode=C80X50;
deuce's avatar
deuce committed
836
837
		if(mode==_ORIGMODE)
			mode=C80;
838
839
840
841
842
843
844
		lastmode=cio_textinfo.currmode;
		cio_api.textmode(mode);
	}
	cio_textinfo.winleft=1;
	cio_textinfo.wintop=1;
	cio_textinfo.winright=cio_textinfo.screenwidth;
	cio_textinfo.winbottom=cio_textinfo.screenheight;
845

deuce's avatar
Typo.    
deuce committed
846
	switch(cio_textinfo.currmode) {
847
		case C64_40X25:
848
849
			cio_textinfo.normattr=0x6e;
			break;
850
		case C128_40X25:
851
			cio_textinfo.normattr=0xbd;
852
853
			break;
		default:
854
855
			cio_textinfo.normattr=LIGHTGRAY;
			break;
856
	}
857
	ciolib_textattr(cio_textinfo.normattr);
858
859
}

860
/* Optional */
861
CIOLIBEXPORT void ciolib_window(int sx, int sy, int ex, int ey)
862
{
863
	CIOLIB_INIT();
864
865
866
867

	if(cio_api.window)
		cio_api.window(sx,sy,ex,ey);

868
869
870
871
872
873
874
875
876
	if(		   sx < 1
			|| sy < 1
			|| ex < 1
			|| ey < 1
			|| sx > cio_textinfo.screenwidth
			|| sy > cio_textinfo.screenheight
			|| sx > ex
			|| sy > ey
			|| ex > cio_textinfo.screenwidth
877
			|| ey > cio_textinfo.screenheight) {
878
		return;
879
	}
880
881
882
883
884
885
886
	cio_textinfo.winleft=sx;
	cio_textinfo.wintop=sy;
	cio_textinfo.winright=ex;
	cio_textinfo.winbottom=ey;
	ciolib_gotoxy(1,1);
}

887
/* Optional */
888
CIOLIBEXPORT void ciolib_clreol(void)
889
{
890
	struct vmem_cell *buf;
891
892
	int i;
	int width,height;
893

894
	CIOLIB_INIT();
895

896
897
898
899
	if(cio_api.clreol) {
		cio_api.clreol();
		return;
	}
900

901
	width=cio_textinfo.winright-cio_textinfo.winleft+1-cio_textinfo.curx+1;
902
	height=1;
903
	buf=malloc(width*height*sizeof(*buf));
deuce's avatar
deuce committed
904
905
	if (!buf)
		return;
906
907
908
909
910
911
	for(i=0;i<width*height;i++) {
		buf[i].ch = ' ';
		buf[i].legacy_attr = cio_textinfo.attribute;
		buf[i].fg = ciolib_fg;
		buf[i].bg = ciolib_bg;
		buf[i].font = ciolib_attrfont(cio_textinfo.attribute);
912
	}
913
	ciolib_vmem_puttext(
914
915
916
917
			cio_textinfo.curx+cio_textinfo.winleft-1,
			cio_textinfo.cury+cio_textinfo.wintop-1,
			cio_textinfo.winright,
			cio_textinfo.cury+cio_textinfo.wintop-1,
918
			buf);
deuce's avatar
deuce committed
919
	free(buf);
920
921
}

922
/* Optional */
923
CIOLIBEXPORT void ciolib_clrscr(void)
924
{
925
	struct vmem_cell *buf;
926
927
	int i;
	int width,height;
928
	int old_ptcm=puttext_can_move;
929

930
	CIOLIB_INIT();
931
932
933
934
	if(cio_api.clrscr) {
		cio_api.clrscr();
		return;
	}