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;
Deucе's avatar
Deucе committed
84
CIOLIBEXPORT const 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
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);
Deucе's avatar
Deucе committed
103
CIOLIBEXPORT int ciolib_cputs(const char *str);
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_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
#ifndef NO_X
204
static int try_x_init(int mode)
205
{
206
#if defined(WITH_SDL)
207
	if (sdl_video_initialized) {
208
		sdl.QuitSubSystem(SDL_INIT_VIDEO);
209
	}
210 211
#endif

deuce's avatar
deuce committed
212
	if(!x_init()) {
213
		cio_api.mode=CIOLIB_MODE_X;
deuce's avatar
deuce committed
214
		cio_api.mouse=1;
deuce's avatar
deuce committed
215
		cio_api.puttext=bitmap_puttext;
216 217
		cio_api.vmem_puttext=bitmap_vmem_puttext;
		cio_api.vmem_gettext=bitmap_vmem_gettext;
deuce's avatar
deuce committed
218 219 220 221 222
		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
223
		cio_api.beep=x_beep;
224
		cio_api.movetext=bitmap_movetext;
225 226
		cio_api.clreol=bitmap_clreol;
		cio_api.clrscr=bitmap_clrscr;
227 228
		cio_api.getcustomcursor=bitmap_getcustomcursor;
		cio_api.setcustomcursor=bitmap_setcustomcursor;
229 230
		cio_api.getvideoflags=bitmap_getvideoflags;
		cio_api.setvideoflags=bitmap_setvideoflags;
231 232

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

259
#ifndef _WIN32
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:
Deucе's avatar
Deucе committed
400 401 402
#ifndef NO_X
			if(!try_x_init(mode))
#endif
403
#if defined(WITH_SDL)
Deucе's avatar
Deucе committed
404
				if(!try_sdl_init(CIOLIB_MODE_SDL))
405
#endif
406
#ifdef _WIN32
Deucе's avatar
Deucе committed
407
					if(!try_conio_init(mode))
408
#else
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));

Deucе's avatar
Deucе committed
703
	ciolib_cputs(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