cterm.c 47.2 KB
Newer Older
rswindell's avatar
rswindell committed
1
/* $Id$ */
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 2006 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.	*
 ****************************************************************************/

deuce's avatar
deuce committed
34
#include <ctype.h>
deuce's avatar
deuce committed
35
#include <stdlib.h>
deuce's avatar
deuce committed
36
#include <string.h>
37
38
39
#if defined(_WIN32)
 #include <malloc.h>	/* alloca() on Win32 */
#endif
deuce's avatar
deuce committed
40

41
#include <genwrap.h>
deuce's avatar
deuce committed
42
#include <xpbeep.h>
43
#include <link_list.h>
rswindell's avatar
rswindell committed
44
45
46
#ifdef __unix__
	#include <xpsem.h>
#endif
47
#include <threadwrap.h>
48
49
50
51
52
53
54
55
56
57

#if (defined CIOLIB_IMPORTS)
 #undef CIOLIB_IMPORTS
#endif
#if (defined CIOLIB_EXPORTS)
 #undef CIOLIB_EXPORTS
#endif

#include "ciolib.h"
#include "keys.h"
58
59

#include "cterm.h"
60
#include "allfonts.h"
61
62
63

#define	BUFSIZE	2048

64
struct cterminal cterm;
65

66
const int cterm_tabs[]={1,9,17,25,33,41,49,57,65,73,81,89,97,105,113,121,129,137,145};
67

68
69
70
71
const char *octave="C#D#EF#G#A#B";

/* Characters allowed in music strings... if one that is NOT in here is
 * found, CTerm leaves music capture mode and tosses the buffer away */
72
const char *musicchars="aAbBcCdDeEfFgGlLmMnNoOpPsStT0123456789.-+#<> ";
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
const uint note_frequency[]={	/* Hz*1000 */
/* Octave 0 (Note 1) */
	 65406
	,69296
	,73416
	,77782
	,82407
	,87307
	,92499
	,97999
	,103820
	,110000
	,116540
	,123470
/* Octave 1 */
	,130810
	,138590
	,146830
	,155560
	,164810
	,174610
	,185000
	,196000
	,207650
	,220000
	,233080
	,246940
/* Octave 2 */
	,261620
	,277180
	,293660
	,311130
	,329630
	,349230
	,369990
	,392000
	,415300
	,440000
	,466160
	,493880
/* Octave 3 */
	,523250
	,554370
	,587330
	,622250
	,659260
	,698460
	,739990
	,783990
	,830610
	,880000
	,932330
	,987770
/* Octave 4 */
	,1046500
	,1108700
	,1174700
	,1244500
	,1318500
	,1396900
	,1480000
	,1568000
	,1661200
	,1760000
	,1864600
	,1975500
/* Octave 5 */
	,2093000
	,2217500
	,2349300
	,2489000
	,2637000
	,2793800
	,2959900
	,3136000
	,3322400
	,3520000
	,3729300
	,3951100
/* Octave 6 */
	,4186000
	,4435000
	,4698600
	,4978000
	,5274000
	,5587000
	,5920000
	,6272000
	,6644000
	,7040000
	,7458600
	,7902200
};
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

struct note_params {
	int notenum;
	int	notelen;
	int	dotted;
	int	tempo;
	int	noteshape;
	int	foreground;
};

static int playnote_thread_running=FALSE;
static link_list_t	notes;
sem_t	playnote_thread_terminated;
sem_t	note_completed_sem;

void playnote_thread(void *args)
182
183
184
185
{
	/* Tempo is quarter notes per minute */
	int duration;
	int pauselen;
186
	struct note_params *note;
deuce's avatar
deuce committed
187
	int	device_open=FALSE;
188

189
190
	playnote_thread_running=TRUE;
	while(1) {
deuce's avatar
deuce committed
191
		if(device_open) {
192
			if(!listSemTryWaitBlock(&notes,5000)) {
deuce's avatar
deuce committed
193
				xptone_close();
194
				device_open=FALSE;
deuce's avatar
deuce committed
195
196
197
198
199
				listSemWait(&notes);
			}
		}
		else
			listSemWait(&notes);
deuce's avatar
deuce committed
200
		device_open=xptone_open();
201
202
		note=listShiftNode(&notes);
		if(note==NULL)
203
			break;
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
		if(note->dotted)
			duration=360000/note->tempo;
		else
			duration=240000/note->tempo;
		duration/=note->notelen;
		switch(note->noteshape) {
			case CTERM_MUSIC_STACATTO:
				pauselen=duration/4;
				break;
			case CTERM_MUSIC_LEGATO:
				pauselen=0;
				break;
			case CTERM_MUSIC_NORMAL:
			default:
				pauselen=duration/8;
				break;
		}
		duration-=pauselen;
deuce's avatar
deuce committed
222
223
224
225
226
227
		if(note->notenum < 72 && note->notenum >= 0) {
			if(device_open)
				xptone(((double)note_frequency[note->notenum])/1000,duration,WAVE_SHAPE_SINE_SAW_HARM);
			else
				xpbeep(((double)note_frequency[note->notenum])/1000,duration);
		}
228
229
230
231
232
233
		else
			SLEEP(duration);
		SLEEP(pauselen);
		if(note->foreground)
			sem_post(&note_completed_sem);
		free(note);
234
	}
235
236
	playnote_thread_running=FALSE;
	sem_post(&playnote_thread_terminated);
237
238
}

239
240
void play_music(void)
{
241
242
243
	int		i;
	char	*p;
	char	*out;
deuce's avatar
deuce committed
244
	int		offset;
245
246
247
	char	note;
	int		notelen;
	char	numbuf[10];
deuce's avatar
deuce committed
248
	int		dotted;
249
	int		notenum;
250
251
	struct	note_params *np;
	int		fore_count;
252

deuce's avatar
deuce committed
253
	if(cterm.quiet) {
254
255
256
257
		cterm.music=0;
		cterm.musicbuf[0]=0;
		return;
	}
258
	p=cterm.musicbuf;
259
	fore_count=0;
260
	if(cterm.music==1) {
261
262
263
264
265
266
267
268
269
270
		switch(toupper(*p)) {
			case 'F':
				cterm.musicfore=TRUE;
				p++;
				break;
			case 'B':
				cterm.musicfore=FALSE;
				p++;
				break;
			case 'N':
271
				if(!isdigit(*(p+1))) {
272
273
274
					cterm.noteshape=CTERM_MUSIC_NORMAL;
					p++;
				}
275
276
277
278
279
280
281
282
283
284
				break;
			case 'L':
				cterm.noteshape=CTERM_MUSIC_LEGATO;
				p++;
				break;
			case 'S':
				cterm.noteshape=CTERM_MUSIC_STACATTO;
				p++;
				break;
		}
285
	}
286
	for(;*p;p++) {
287
		notenum=0;
deuce's avatar
deuce committed
288
		offset=0;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
		switch(toupper(*p)) {
			case 'M':
				p++;
				switch(toupper(*p)) {
					case 'F':
						cterm.musicfore=TRUE;
						break;
					case 'B':
						cterm.musicfore=FALSE;
						break;
					case 'N':
						cterm.noteshape=CTERM_MUSIC_NORMAL;
						break;
					case 'L':
						cterm.noteshape=CTERM_MUSIC_LEGATO;
						break;
					case 'S':
						cterm.noteshape=CTERM_MUSIC_STACATTO;
						break;
					default:
						p--;
				}
				break;
			case 'T':						/* Tempo */
				out=numbuf;
				while(isdigit(*(p+1)))
					*(out++)=*(++p);
				*out=0;
317
				cterm.tempo=strtoul(numbuf,NULL,10);
318
319
320
321
322
323
324
325
326
327
				if(cterm.tempo>255)
					cterm.tempo=255;
				if(cterm.tempo<32)
					cterm.tempo=32;
				break;
			case 'O':						/* Octave */
				out=numbuf;
				while(isdigit(*(p+1)))
					*(out++)=*(++p);
				*out=0;
328
				cterm.octave=strtoul(numbuf,NULL,10);
329
330
331
				if(cterm.octave>6)
					cterm.octave=6;
				break;
332
333
334
335
336
			case 'L':
				out=numbuf;
				while(isdigit(*(p+1)))
					*(out++)=*(++p);
				*out=0;
337
				cterm.notelen=strtoul(numbuf,NULL,10);
338
339
340
341
342
				if(cterm.notelen<1)
					cterm.notelen=1;
				if(cterm.notelen>64)
					cterm.notelen=64;
				break;
343
344
345
346
347
348
349
350
			case 'N':						/* Note by number */
				if(isdigit(*(p+1))) {
					out=numbuf;
					while(isdigit(*(p+1))) {
						*(out++)=*(p+1);
						p++;
					}
					*out=0;
351
					notenum=strtoul(numbuf,NULL,10);
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
				}
				if(notenum==0) {
					notenum=-1;
					offset=1;
				}
				/* Fall-through */
			case 'A':						/* Notes in current octave by letter */
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
			case 'G':
			case 'P':
				note=toupper(*p);
				notelen=cterm.notelen;
				dotted=0;
				i=1;
				while(i) {
					i=0;
					if(*(p+1)=='+' || *(p+1)=='#') {	/* SHARP */
						offset+=1;
						p++;
						i=1;
					}
					if(*(p+1)=='-') {					/* FLAT */
						offset-=1;
						p++;
						i=1;
					}
					if(*(p+1)=='.') {					/* Dotted note (1.5*notelen) */
						dotted=1;
						p++;
						i=1;
					}
					if(isdigit(*(p+1))) {
						out=numbuf;
						while(isdigit(*(p+1))) {
							*(out++)=*(p+1);
							p++;
						}
						*out=0;
394
						notelen=strtoul(numbuf,NULL,10);
395
396
397
						i=1;
					}
				}
deuce's avatar
deuce committed
398
399
400
401
				if(note=='P') {
					notenum=-1;
					offset=0;
				}
402
403
404
405
406
407
408
409
410
411
412
413
				if(notenum==0) {
					out=strchr(octave,note);
					if(out==NULL) {
						notenum=-1;
						offset=1;
					}
					else {
						notenum=cterm.octave*12+1;
						notenum+=(out-octave);
					}
				}
				notenum+=offset;
414
415
416
417
418
419
420
421
422
423
424
425
				np=(struct note_params *)malloc(sizeof(struct note_params));
				if(np!=NULL) {
					np->notenum=notenum;
					np->notelen=notelen;
					np->dotted=dotted;
					np->tempo=cterm.tempo;
					np->noteshape=cterm.noteshape;
					np->foreground=cterm.musicfore;
					listPushNode(&notes, np);
					if(cterm.musicfore)
						fore_count++;
				}
426
427
428
429
430
431
432
433
434
435
436
437
438
				break;
			case '<':							/* Down one octave */
				cterm.octave--;
				if(cterm.octave<0)
					cterm.octave=0;
				break;
			case '>':							/* Up one octave */
				cterm.octave++;
				if(cterm.octave>6)
					cterm.octave=6;
				break;
		}
	}
439
	cterm.music=0;
440
	cterm.musicbuf[0]=0;
441
442
443
444
	while(fore_count) {
		sem_wait(&note_completed_sem);
		fore_count--;
	}
445
446
447
448
}

void scrolldown(void)
{
449
	int x,y;
450

451
	movetext(cterm.x,cterm.y,cterm.x+cterm.width-1,cterm.y+cterm.height-2,cterm.x,cterm.y+1);
452
453
454
455
456
	x=wherex();
	y=wherey();
	gotoxy(1,1);
	clreol();
	gotoxy(x,y);
457
458
459
460
}

void scrollup(void)
{
461
	int x,y;
462

463
464
465
466
467
	cterm.backpos++;
	if(cterm.scrollback!=NULL) {
		if(cterm.backpos>cterm.backlines) {
			memmove(cterm.scrollback,cterm.scrollback+cterm.width*2,cterm.width*2*(cterm.backlines-1));
			cterm.backpos--;
468
		}
469
		gettext(cterm.x,cterm.y,cterm.x+cterm.width-1,cterm.y,cterm.scrollback+(cterm.backpos-1)*cterm.width*2);
470
	}
471
	movetext(cterm.x,cterm.y+1,cterm.x+cterm.width-1,cterm.y+cterm.height-1,cterm.x,cterm.y);
472
473
474
475
476
	x=wherex();
	y=wherey();
	gotoxy(1,cterm.height);
	clreol();
	gotoxy(x,y);
477
478
}

deuce's avatar
deuce committed
479
480
void dellines(int lines)
{
deuce's avatar
deuce committed
481
	int i;
deuce's avatar
deuce committed
482
	int linestomove;
483
	int x,y;
deuce's avatar
deuce committed
484

deuce's avatar
deuce committed
485
486
487
	if(lines<1)
		return;
	linestomove=cterm.height-wherey();
488
	movetext(cterm.x,cterm.y+wherey()-1+lines,cterm.x+cterm.width-1,cterm.y+cterm.height-1,cterm.x,cterm.y+wherey()-1);
489
490
491
492
493
	x=wherex();
	y=wherey();
	for(i=cterm.height-lines+1; i<=cterm.height; i++) {
		gotoxy(1,i);
		clreol();
deuce's avatar
deuce committed
494
	}
495
	gotoxy(x,y);
deuce's avatar
deuce committed
496
497
}

498
499
500
void clear2bol(void)
{
	char *buf;
deuce's avatar
deuce committed
501
	int i,j,k;
502

deuce's avatar
deuce committed
503
504
	k=wherex();
	buf=(char *)alloca(k*2);
505
	j=0;
deuce's avatar
deuce committed
506
	for(i=0;i<k;i++) {
507
		if(cterm.emulation == CTERM_EMULATION_ATASCII)
deuce's avatar
deuce committed
508
			buf[j++]=0;
509
		else
deuce's avatar
deuce committed
510
			buf[j++]=' ';
511
		buf[j++]=cterm.attr;
512
	}
deuce's avatar
deuce committed
513
	puttext(cterm.x,cterm.y+wherey()-1,cterm.x+wherex()-1,cterm.y+wherey()-1,buf);
514
515
}

516
void cterm_clearscreen(char attr)
517
{
518
519
520
521
522
	if(cterm.scrollback!=NULL) {
		cterm.backpos+=cterm.height;
		if(cterm.backpos>cterm.backlines) {
			memmove(cterm.scrollback,cterm.scrollback+cterm.width*2*(cterm.backpos-cterm.backlines),cterm.width*2*(cterm.backlines-(cterm.backpos-cterm.backlines)));
			cterm.backpos=cterm.backlines;
523
		}
524
		gettext(cterm.x,cterm.y,cterm.x+cterm.width-1,cterm.y+cterm.height-1,cterm.scrollback+(cterm.backpos-cterm.height)*cterm.width*2);
525
	}
526
527
	clrscr();
	gotoxy(1,1);
528
529
}

deuce's avatar
deuce committed
530
void do_ansi(char *retbuf, size_t retsize, int *speed)
531
532
533
534
{
	char	*p;
	char	*p2;
	char	tmp[1024];
535
	int		i,j,k,l;
536
	int		row,col;
537
	struct text_info ti;
538

539
	switch(cterm.escbuf[0]) {
540
541
		case '[':
			/* ANSI stuff */
542
			p=cterm.escbuf+strlen(cterm.escbuf)-1;
543
			if(cterm.escbuf[1]>=60 && cterm.escbuf[1] <= 63) {	/* Private extenstions */
544
545
546
				switch(*p) {
					case 'M':
						if(cterm.escbuf[1] == '=') {	/* ANSI Music setup */
547
							i=strtoul(cterm.escbuf+2,NULL,10);
548
549
550
551
552
553
554
555
556
557
558
							switch(i) {
								case 1:					/* BANSI (ESC[N) music only) */
									cterm.music_enable=CTERM_MUSIC_BANSI;
									break;
								case 2:					/* ESC[M ANSI music */
									cterm.music_enable=CTERM_MUSIC_ENABLED;
									break;
								default:					/* Disable ANSI Music */
									cterm.music_enable=CTERM_MUSIC_SYNCTERM;
									break;
							}
559
						}
560
						break;
deuce's avatar
deuce committed
561
					case 'h':
562
563
564
565
						if(!strcmp(cterm.escbuf,"[?25h")) {
							cterm.cursor=_NORMALCURSOR;
							_setcursortype(cterm.cursor);
						}
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
						if(!strcmp(cterm.escbuf,"[?31h")) {
							i=getvideoflags();
							i|=CIOLIB_VIDEO_ALTCHARS;
							setvideoflags(i);
						}
						if(!strcmp(cterm.escbuf,"[?32h")) {
							i=getvideoflags();
							i|=CIOLIB_VIDEO_NOBRIGHT;
							setvideoflags(i);
						}
						if(!strcmp(cterm.escbuf,"[?33h")) {
							i=getvideoflags();
							i|=CIOLIB_VIDEO_BGBRIGHT;
							setvideoflags(i);
						}
deuce's avatar
deuce committed
581
582
583
584
						if(!strcmp(cterm.escbuf,"[=255h"))
							cterm.doorway_mode=1;
						break;
					case 'l':
585
586
587
588
						if(!strcmp(cterm.escbuf,"[?25l")) {
							cterm.cursor=_NOCURSOR;
							_setcursortype(cterm.cursor);
						}
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
						if(!strcmp(cterm.escbuf,"[?31l")) {
							i=getvideoflags();
							i&=~CIOLIB_VIDEO_ALTCHARS;
							setvideoflags(i);
						}
						if(!strcmp(cterm.escbuf,"[?32l")) {
							i=getvideoflags();
							i&=~CIOLIB_VIDEO_NOBRIGHT;
							setvideoflags(i);
						}
						if(!strcmp(cterm.escbuf,"[?33l")) {
							i=getvideoflags();
							i&=~CIOLIB_VIDEO_BGBRIGHT;
							setvideoflags(i);
						}
deuce's avatar
deuce committed
604
605
606
						if(!strcmp(cterm.escbuf,"[=255l"))
							cterm.doorway_mode=0;
						break;
607
608
609
610
611
					case '{':
						if(cterm.escbuf[1] == '=') {	/* Font loading */
							i=255;
							j=0;
							if(strlen(cterm.escbuf)>2) {
612
								if((p=strtok(cterm.escbuf+2,";"))!=NULL) {
613
									i=strtoul(p,NULL,10);
614
615
616
									if(!i && cterm.escbuf[2] != '0')
										i=255;
									if((p=strtok(NULL,";"))!=NULL) {
617
										j=strtoul(p,NULL,10);
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
									}
								}
							}
							if(i>255)
								break;
							cterm.font_start_time=time(NULL);
							cterm.font_read=0;
							cterm.font_slot=i;
							switch(j) {
								case 0:
									cterm.font_size=4096;
									break;
								case 1:
									cterm.font_size=3586;
									break;
								case 2:
									cterm.font_size=2048;
									break;
								default:
									cterm.font_size=0;
									break;
							}
						}
						break;
642
643
644
				}
				break;
			}
645
646
647
648
			switch(*p) {
				case '@':	/* Insert Char */
					i=wherex();
					j=wherey();
649
					k=strtoul(cterm.escbuf+1,NULL,10);
deuce's avatar
deuce committed
650
651
652
653
					if(k<1)
						k=1;
					if(k>cterm.width - j)
						k=cterm.width - j;
654
					movetext(cterm.x+i-1,cterm.y+j-1,cterm.x+cterm.width-1-k,cterm.y+j-1,cterm.x+i-1+k,cterm.y+j-1);
deuce's avatar
deuce committed
655
656
					for(l=0; l< k; l++)
						putch(' ');
657
658
659
					gotoxy(i,j);
					break;
				case 'A':	/* Cursor Up */
660
					i=strtoul(cterm.escbuf+1,NULL,10);
661
662
663
664
665
666
667
668
					if(i==0)
						i=1;
					i=wherey()-i;
					if(i<1)
						i=1;
					gotoxy(wherex(),i);
					break;
				case 'B':	/* Cursor Down */
669
					i=strtoul(cterm.escbuf+1,NULL,10);
670
671
672
					if(i==0)
						i=1;
					i=wherey()+i;
673
674
					if(i>cterm.height)
						i=cterm.height;
675
676
677
					gotoxy(wherex(),i);
					break;
				case 'C':	/* Cursor Right */
678
					i=strtoul(cterm.escbuf+1,NULL,10);
679
680
681
					if(i==0)
						i=1;
					i=wherex()+i;
682
683
					if(i>cterm.width)
						i=cterm.width;
684
685
					gotoxy(i,wherey());
					break;
686
687
688
689
690
691
				case 'D':	/* Cursor Left and Font Select */
					if(*(p-1)==' ') {	/* Font Select */
						i=0;
						j=0;
						if(strlen(cterm.escbuf)>2) {
							if((p=strtok(cterm.escbuf+1,";"))!=NULL) {
692
								i=strtoul(p,NULL,10);
693
								if((p=strtok(NULL,";"))!=NULL) {
694
									j=strtoul(p,NULL,10);
695
696
								}
							}
697
698
699
							switch(i) {
								case 0:	/* Only the primary and secondary font is currently supported */
								case 1:
deuce's avatar
deuce committed
700
									setfont(j,FALSE,i+1);
701
702
703
704
							}
						}
					}
					else {
705
						i=strtoul(cterm.escbuf+1,NULL,10);
706
707
708
709
710
711
712
						if(i==0)
							i=1;
						i=wherex()-i;
						if(i<1)
							i=1;
						gotoxy(i,wherey());
					}
713
					break;
deuce's avatar
deuce committed
714
				case 'E':	/* Cursor next line */
715
					i=strtoul(cterm.escbuf+1,NULL,10);
716
717
718
					if(i==0)
						i=1;
					i=wherey()+i;
719
720
721
722
					while(i>cterm.height) {
						scrollup();
						i--;
					}
deuce's avatar
deuce committed
723
724
725
					gotoxy(1,i);
					break;
				case 'F':	/* Cursor preceding line */
726
					i=strtoul(cterm.escbuf+1,NULL,10);
deuce's avatar
deuce committed
727
728
729
730
731
732
					if(i==0)
						i=1;
					i=wherey()-i;
					if(i<1)
						i=1;
					gotoxy(1,i);
733
734
735
736
737
					break;
				case 'f':
				case 'H':
					row=1;
					col=1;
deuce's avatar
deuce committed
738
					*p=0;
739
740
					if(strlen(cterm.escbuf)>1) {
						if((p=strtok(cterm.escbuf+1,";"))!=NULL) {
741
							row=strtoul(p,NULL,10);
742
							if((p=strtok(NULL,";"))!=NULL) {
743
								col=strtoul(p,NULL,10);
744
745
746
747
748
749
750
							}
						}
					}
					if(row<1)
						row=1;
					if(col<1)
						col=1;
751
752
753
754
					if(row>cterm.height)
						row=cterm.height;
					if(col>cterm.width)
						col=cterm.width;
755
756
757
					gotoxy(col,row);
					break;
				case 'J':
758
					i=strtoul(cterm.escbuf+1,NULL,10);
759
760
					switch(i) {
						case 0:
761
762
763
764
765
766
							clreol();
							row=wherey();
							col=wherex();
							for(i=row+1;i<=cterm.height;i++) {
								gotoxy(1,i);
								clreol();
767
							}
768
							gotoxy(col,row);
769
770
771
							break;
						case 1:
							clear2bol();
772
773
774
775
776
							row=wherey();
							col=wherex();
							for(i=row-1;i>=1;i--) {
								gotoxy(1,i);
								clreol();
777
							}
778
							gotoxy(col,row);
779
780
							break;
						case 2:
781
							cterm_clearscreen((char)cterm.attr);
782
783
784
785
786
							gotoxy(1,1);
							break;
					}
					break;
				case 'K':
787
					i=strtoul(cterm.escbuf+1,NULL,10);
788
789
					switch(i) {
						case 0:
790
							clreol();
791
792
793
794
795
							break;
						case 1:
							clear2bol();
							break;
						case 2:
796
797
798
799
800
							row=wherey();
							col=wherex();
							gotoxy(1,row);
							clreol();
							gotoxy(col,row);
801
802
803
							break;
					}
					break;
deuce's avatar
deuce committed
804
				case 'L':		/* Insert line */
805
806
					row=wherey();
					col=wherex();
807
					i=strtoul(cterm.escbuf+1,NULL,10);
808
809
					if(i==0)
						i=1;
810
811
					if(i>cterm.height-row)
						i=cterm.height-row;
812
					if(i)
813
						movetext(cterm.x,cterm.y+row-1,cterm.x+cterm.width-1,cterm.y+cterm.height-1-i,cterm.x,cterm.y+row-1+i);
deuce's avatar
deuce committed
814
					for(j=0;j<i;j++) {
815
816
						gotoxy(1,row+j);
						clreol();
817
					}
818
					gotoxy(col,row);
819
					break;
820
				case 'M':	/* ANSI music and also supposed to be delete line! */
821
822
					if(cterm.music_enable==CTERM_MUSIC_ENABLED) {
						cterm.music=1;
deuce's avatar
deuce committed
823
824
					}
					else {
825
						i=strtoul(cterm.escbuf+1,NULL,10);
826
827
828
						if(i<1)
							i=1;
						dellines(i);
deuce's avatar
deuce committed
829
					}
830
					break;
831
832
				case 'N':
					/* BananANSI style... does NOT start with MF or MB */
deuce's avatar
deuce committed
833
834
835
					/* This still conflicts (ANSI erase field) */
					if(cterm.music_enable >= CTERM_MUSIC_BANSI)
						cterm.music=2;
836
					break;
837
				case 'P':	/* Delete char */
838
839
840
					row=wherey();
					col=wherex();

841
					i=strtoul(cterm.escbuf+1,NULL,10);
842
843
					if(i==0)
						i=1;
844
845
846
847
848
849
					if(i>cterm.width-col+1)
						i=cterm.width-col+1;
					movetext(cterm.x+col-1+i,cterm.y+row-1,cterm.x+cterm.width-1-i,cterm.y+row-1,cterm.x+col-1,cterm.y+row-1);
					gotoxy(cterm.width-i,col);
					clreol();
					gotoxy(col,row);
850
851
					break;
				case 'S':
852
					i=strtoul(cterm.escbuf+1,NULL,10);
853
					if(i==0 && cterm.escbuf[1] != '0')
deuce's avatar
deuce committed
854
						i=1;
855
856
					for(j=0; j<i; j++)
						scrollup();
857
858
					break;
				case 'T':
859
					i=strtoul(cterm.escbuf+1,NULL,10);
860
					if(i==0 && cterm.escbuf[1] != '0')
deuce's avatar
deuce committed
861
						i=1;
862
863
					for(j=0; j<i; j++)
						scrolldown();
864
					break;
865
#if 0
866
				case 'U':
867
					gettextinfo(&ti);
868
					cterm_clearscreen(ti.normattr);
869
870
					gotoxy(1,1);
					break;
871
#endif
deuce's avatar
deuce committed
872
				case 'X':
873
					i=strtoul(cterm.escbuf+1,NULL,10);
deuce's avatar
deuce committed
874
875
876
877
878
879
880
881
882
883
					if(i<1)
						i=1;
					if(i>cterm.width-wherex())
						i=cterm.width-wherex();
					p2=alloca(i*2);
					j=0;
					for(k=0;k<i;k++) {
						p2[j++]=' ';
						p2[j++]=cterm.attr;
					}
deuce's avatar
deuce committed
884
					puttext(cterm.x+wherex()-1,cterm.y+wherey()-1,cterm.x+wherex()-1+i-1,cterm.y+wherey()-1,p2);
deuce's avatar
deuce committed
885
886
					break;
				case 'Z':
887
					i=strtoul(cterm.escbuf+1,NULL,10);
deuce's avatar
deuce committed
888
889
					if(i==0 && cterm.escbuf[0] != '0')
						i=1;
890
					for(j=(sizeof(cterm_tabs)/sizeof(cterm_tabs[0]))-1;j>=0;j--) {
891
						if(cterm_tabs[j]<wherex()) {
deuce's avatar
deuce committed
892
893
894
895
							k=j-i+1;
							if(k<0)
								k=0;
							gotoxy(cterm_tabs[k],wherey());
896
897
898
899
900
901
							break;
						}
					}
					break;
				case 'b':	/* ToDo?  Banana ANSI */
					break;
902
				case 'c':	/* Device Attributes */
903
					i=strtoul(cterm.escbuf+1,NULL,10);
904
905
					if(!i) {
						if(retbuf!=NULL) {
deuce's avatar
deuce committed
906
907
							if(strlen(retbuf)+strlen(cterm.DA) < retsize)
								strcat(retbuf,cterm.DA);
908
909
910
						}
					}
					break;
911
912
				case 'g':	/* ToDo?  VT100 Tabs */
					break;
913
				case 'h':	/* ToDo?  Scrolling region, word-wrap */
914
915
916
					break;
				case 'i':	/* ToDo?  Printing */
					break;
917
				case 'l':	/* ToDo?  Scrolling region, word-wrap */
918
919
920
					break;
				case 'm':
					*(p--)=0;
921
					p2=cterm.escbuf+1;
922
					gettextinfo(&ti);
923
					if(p2>p) {
924
						cterm.attr=ti.normattr;
925
926
927
928
						break;
					}
					while((p=strtok(p2,";"))!=NULL) {
						p2=NULL;
929
						switch(strtoul(p,NULL,10)) {
930
							case 0:
931
								cterm.attr=ti.normattr;
932
933
								break;
							case 1:
934
								cterm.attr|=8;
935
936
								break;
							case 2:
937
								cterm.attr&=247;
938
939
940
941
942
								break;
							case 4:	/* Underscore */
								break;
							case 5:
							case 6:
943
								cterm.attr|=128;
944
945
								break;
							case 7:
946
							case 27:
947
948
949
950
951
								i=cterm.attr&7;
								j=cterm.attr&112;
								cterm.attr &= 136;
								cterm.attr |= j>>4;
								cterm.attr |= i<<4;
952
953
								break;
							case 8:
954
955
956
								j=cterm.attr&112;
								cterm.attr&=112;
								cterm.attr |= j>>4;
957
								break;
958
959
960
							case 22:
								cterm.attr &= 0xf7;
								break;
961
962
963
							case 25:
								cterm.attr &= 0x7f;
								break;
964
							case 30:
965
								cterm.attr&=248;
966
967
								break;
							case 31:
968
969
								cterm.attr&=248;
								cterm.attr|=4;
970
971
								break;
							case 32:
972
973
								cterm.attr&=248;
								cterm.attr|=2;
974
975
								break;
							case 33:
976
977
								cterm.attr&=248;
								cterm.attr|=6;
978
979
								break;
							case 34:
980
981
								cterm.attr&=248;
								cterm.attr|=1;
982
983
								break;
							case 35:
984
985
								cterm.attr&=248;
								cterm.attr|=5;
986
987
								break;
							case 36:
988
989
								cterm.attr&=248;
								cterm.attr|=3;
990
991
								break;
							case 37:
992
							case 39:
993
994
								cterm.attr&=248;
								cterm.attr|=7;
995
996
								break;
							case 40:
997
								cterm.attr&=143;
998
999
								break;
							case 41:
1000
								cterm.attr&=143;
For faster browsing, not all history is shown. View entire blame