forked from rricharz/Tek4010
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tek4010.c
executable file
·710 lines (625 loc) · 31.9 KB
/
tek4010.c
1
2
3
4
5
6
7
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
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
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
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
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
/*
* tek4010.c
*
* A tek4010/4014 graphics emulator
*
* Copyright 2019 rricharz
*
* https://github.com/rricharz/Tek4010
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#define DEBUG 0 // print debug info
#define TODO (long)(16) // draw multiple objects until screen updates
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include "main.h"
#include "tube.h"
// mode handles the current state of the emulator:
//
// mode 0 alpha mode
//
// mode 1 expecting address byte of dark mode (move to) address
// mode 2 expecting second byte of dark mode (move to) address
// mode 3 expecting third byte of dark mode (move to) address
// mode 4 expecting fourth byte of dark mode (move to) address
// mode 5 expecting first byte of persistent vector end point address
// mode 6 expecting second byte of persistent vector end point address
// mode 7 expecting third byte of persistent vector end point address
// mode 8 expecting fourth byte of persistent vector end point address
//
// mode 30 expecting escape sequence, escape code received
// mode 31 received in ANSI escape sequence, escape sequence continues if next char is digit
//
// mode 40 incremental plot mode; is ignored until exit from incremental plot received
// mode 50 special point plot mode
// mode 60 crosshair mode
// mode 101 ignore until group separator
int mode, savemode;
int penDown = 1;
extern int leftmargin;
extern FILE *putKeys;
static long startPaintTime;
static int xh,xl,yh,yl,xy4014;
static long todo;
static double efactor;
int ginCharacter[6] = {0, 0, 0, 0, 0, 0};
// table for special plot point mode
// 4014 manual page F-9
int intensityTable[] = {14,16,17,19, 20,22,23,25, 28,31,34,38, 41,33,47,50,
56,62,69,75, 81,88,94,100, 56,62,69,75, 81,88,96,100,
0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3,
4, 4, 4, 5, 5, 5, 6, 6, 7, 8, 9,10, 11,12,12,13,
14,16,17,19, 20,22,23,25, 28,31,34,38, 41,44,47,50,
56,62,69,75, 81,88,94,100, 56,63,69,75, 81,88};
void tek4010_checkLimits(cairo_t *cr, cairo_t *cr2)
/* check whether char is in visibel space */
{
/* don't check here for leftmargin, graphics needs to write characters to the whole screen */
if (tube_x0 < 0) tube_x0 = 0;
if (tube_x0 > windowWidth - hDotsPerChar) {
tube_x0 = leftmargin; tube_y0 -= vDotsPerChar;
}
if (tube_y0 < 4) { // new line at bottom of page
tube_y0 = windowHeight - vDotsPerChar;
if (leftmargin) leftmargin = 0;
else leftmargin = windowWidth / 2;
if (argAutoClear) {
leftmargin = 0;
tube_clearPersistent(cr,cr2);
}
/* check here for leftmargin */
if (tube_x0 < leftmargin) tube_x0 = leftmargin;
}
if (tube_y0 > (windowHeight - vDotsPerChar)) tube_y0 = windowHeight - vDotsPerChar;
}
void tek4010_bell()
{
// bell function, delay 0.05 sec
tube_u100ResetSeconds(1);
usleep(50000);
showCursor=0;
todo = 0;
}
void sendCoordinates()
{
// send 4 coordinate bytes
int x,y,ch;
x = (int)((double)tube_x0 / efactor);
y = (int)((double)tube_y0 / efactor);
if (DEBUG) printf("sendCoordinates, x=%d, y=%d\n", x, y);
ch = (x >> 5) + 0x20;
putc(ch, putKeys);
ginCharacter[4] = ch; // save to check for echo
ch = (x & 31) + 0x20;
putc(ch,putKeys);
ginCharacter[3] = ch; // save to check for echo
ch = (y >> 5) + 0x20;
putc(ch, putKeys);
ginCharacter[2] = ch; // save to check for echo
ch = (y & 31) + 0x20;
putc(ch,putKeys);
ginCharacter[1] = ch; // save to check for echo
}
void enqMode()
{
// activated by sending ESC ENQ
int status;
status = 0x20;
if (leftmargin == 0) status += 2;
if (mode == 0) status += 4;
putc(status,putKeys); // send status byte
sendCoordinates();
putc(13, putKeys); // cannot send a EOT here
}
void ginMode(cairo_t *cr, cairo_t *cr2)
{
// activated by sending ESC SUB
if (DEBUG) printf("GIN, mode = %d, isGinMode = %d\n", mode, isGinMode);
tube_crosshair(cr, cr2);
mode = 60;
todo = 0;
showCursor = 0;
isGinMode = 1;
}
void ginSend(int ch)
{
// user has stoken a key during GIN mode
if (DEBUG) printf("ginSend, ch = %d\n", ch);
putc(ch,putKeys); // user key stroke character
ginCharacter[5] = ch; // save to check for echo
sendCoordinates(); // 4 characters of packed coordinates
// cannot send a EOT here
// wait 5 ms, then send CR.
usleep(5000);
putc(13,putKeys); // cr
ginCharacter[0] = 13;
// prepare to suppress unwanted echoed characters.
isGinSuppress = 6;
}
void tek4010_clicked(int x, int y)
{
if (DEBUG) printf("Clicked, mode = %d\n", mode);
if (mode == 60) {
tube_x0 = x;
tube_y0 = y;
}
}
void tek4010_escapeCodeHandler(cairo_t *cr, cairo_t *cr2, int ch)
// handle escape sequencies, see 4014 user manual, table page G-1
// codes identical for all modes are handled elsewhere
{
if (DEBUG) printf("Escape %02X, savemode=%d\n",ch,savemode);
switch (ch) {
case 0: break; // ignore filler 0
case 5: // ENQ: ask for status and position
enqMode();
mode = 0; break;
case 6: break;
case 8: // backspace during ESC
tube_x0 -= hDotsPerChar;
tek4010_checkLimits(cr, cr2);
mode = 0; break;
case 9: // tab during ESC
if (argTab1)
tube_x0 += hDotsPerChar;
else
tube_x0 = tube_x0 - (tube_x0 % (8 * hDotsPerChar)) + 8 * hDotsPerChar;
tek4010_checkLimits(cr, cr2);
mode = 0; break;
case 11:// VT during ESC, move one line up
tube_y0 += vDotsPerChar;
tek4010_checkLimits(cr, cr2);
mode = 0; break;
case 12:// FF during ESC
if (!argKeepSize)
tube_changeCharacterSize(cr, cr2, 74, 35, efactor);
tube_clearPersistent(cr,cr2);
mode = 0; break;
case 13:mode = 0; break;
case 14: // SO activate alternative char set
if (argAPL) { // switch only of argAPL is set
aplMode = 1;
// printf("Setting APL mode to 1 from computer\n");
}
mode = 0;
todo = 0;
break;
case 15: // SI deactivate alternative char set
aplMode = 0;
mode = 0;
todo = 0;
// printf("Setting APL mode to 0 from computer\n");
break;
case 23: system("scrot --focussed"); mode= 0; break;
case 26: // sub
ginMode(cr, cr2);
break;
// modes 27 and 29 - 31 are identical in all modes
case 28: // record separator
if (DEBUG) printf("Special point plot mode, mode=%d\n",savemode);
mode = 50; // for the intensity/focus character
plotPointMode = 1;
specialPlotMode = 1;
double intensity = 1.0;
int defocussed = 0;
break;
case '8': tube_changeCharacterSize(cr, cr2, 74, 35, efactor); mode = 0; break;
case '9': tube_changeCharacterSize(cr, cr2, 81, 38, efactor * 0.9); mode = 0; break;
case ':': tube_changeCharacterSize(cr, cr2, 121, 58, efactor * 0.65); mode = 0; break;
case ';': tube_changeCharacterSize(cr, cr2, 133, 64, efactor * 0.55); mode = 0; break;
case '[': printf("Ignoring ANSI escape sequence: [");
mode=31;
break;
// normal mode
case '`': ltype = SOLID; writeThroughMode = 0; mode = savemode; break;
case 'a': ltype = DOTTED; writeThroughMode = 0; mode = savemode; break;
case 'b': ltype = DOTDASH; writeThroughMode = 0; mode = savemode; break;
case 'c': ltype = SHORTDASH;writeThroughMode = 0; mode = savemode; break;
case 'd': ltype = LONGDASH; writeThroughMode = 0; mode = savemode; break;
case 'e': ltype = SOLID; writeThroughMode = 0; mode = savemode; break;
case 'f': ltype = SOLID; writeThroughMode = 0; mode = savemode; break;
case 'g': ltype = SOLID; writeThroughMode = 0; mode = savemode; break;
// defocussed mode
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o': if (DEBUG) printf("Defocussed mode ESC %c not supported, ignored\n", ch);
mode = 101; break;
// write-trough mode
case 'p': ltype = SOLID; writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 'q': ltype = DOTTED; writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 'r': ltype = DOTDASH; writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 's': ltype = SHORTDASH;writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 't': ltype = LONGDASH; writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 'u': ltype = SOLID; writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 'v': ltype = SOLID; writeThroughMode = 1; mode = 101; showCursor = 0; break;
case 'w': ltype = SOLID; writeThroughMode = 1; mode = 101; showCursor = 0; break;
default:
printf("Ignoring escape code: 0x%02x\n",ch);
mode = 0;
break;
}
}
int tek4010_checkReturnToAlpha(int ch)
// test for return to alpha character set
// see 4014 manual, page F-10, note 1
{
if (ch == 27)
savemode = mode;
if ((ch==31) || (ch==13) || (ch==27) /*|| (ch==12)*/) {
if (DEBUG && mode) printf("Going to alpha mode\n");
mode = 0;
showCursor = 0;
//if (ch == 12) {
// tube_doClearPersistent = 1;
// todo = 0;
//}
if (ch == 27) {
mode = 30;
todo = 0;
}
plotPointMode = 0;
specialPlotMode = 0;
if (isGinMode && DEBUG)
printf("clearing isGinMode, char = %d\n", ch);
isGinMode = 0;
return 1;
}
else return 0;
}
int digit(char ch)
{
return ((ch>='0') && (ch<='9'));
}
void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first)
// draw onto the main window using cairo
// cr is used for persistent drawing, cr2 for temporary drawing
{
int ch, tag;
refreshCount++;
if (first) {
first = 0;
efactor = windowWidth / 1024.0;
refresh_interval = 30;
tube_changeCharacterSize(cr, cr2, 74, 35, efactor);
if (efactor > 0.8) pensize = efactor * 1.25;
if (windowWidth != 1024) printf("Scaling: %0.3f\n", efactor / 4.0);
}
startPaintTime = tube_mSeconds(); // start to measure time for this draw operation
showCursor = 1;
isBrightSpot = 0;
// clear the second surface
tube_clearSecond(cr2);
// clear persistent surface, if necessary
if (tube_doClearPersistent) {
tube_clearPersistent(cr,cr2);
if (!argKeepSize)
tube_changeCharacterSize(cr, cr2, 74, 35, efactor);
}
if (aplMode)
tube_setupPainting(cr, cr2, APL_FONT);
else
tube_setupPainting(cr, cr2, STANDARD_FONT);
if (plotPointMode)
todo = 100 * TODO;
else if (writeThroughMode)
todo = 8 * TODO;
else if (mode == 0)
todo = 4 * TODO; // for text speed
else
todo = TODO;
do {
ch = tube_getInputChar();
if (tube_isInput() == 0) {
todo = 0;
}
if (ch == -1) {
if ((mode == 0) && showCursor) tube_doCursor(cr2);
if (mode != 60) return; // no char available, need to allow for updates
}
// Try suppressing GIN echoed characters here.
if (isGinSuppress){
if (ch == 10) // additional line feed may be echoed if cr is typed
return;
if ((ch & 0x7F) == ginCharacter[isGinSuppress - 1]) {
if (DEBUG) printf( "isGinSuppress (%d): suppressing: %d\n",
isGinSuppress, ch);
isGinSuppress --;
return;
}
else {
if (DEBUG) printf("isGinSuppress, characters are different (%d,%d)\n",
ch & 0x7F, ginCharacter[isGinSuppress - 1]);
isGinSuppress = 0;
}
}
// if (aplMode) printf("Receiving character %d from host\n", ch);
if (DEBUG) {
printf("mode=%d, ch code %02X",mode,ch);
if ((ch>0x20)&&(ch<=0x7E)) printf(" (%c)",ch);
printf("\n");
}
if (tek4010_checkReturnToAlpha(ch)) {
todo = todo - 4;
goto endDo;
}
// the following chars are identical in all modes (with exception: 13,28)
// see 4014 user manual, table on page G1 ff
switch (ch) {
case 7: tek4010_bell();
goto endDo;
case 10: // new line
tube_y0 -= vDotsPerChar;
if (!argRaw) tube_x0 = leftmargin;
tek4010_checkLimits(cr, cr2);
goto endDo;
case 13: // return
if (mode != 30) { // special handling in ESC mode
mode = 0; tube_x0 = leftmargin;
goto endDo;
}
break;
case 27: // escape code, all modes
savemode = mode;
mode = 30;
goto endDo;
case 28: // file separator >> point plot mode
if (mode != 30) { // special handling in ESC mode
mode = 5;
plotPointMode= 1;
goto endDo;
}
break;
case 29: // group separator >> graphics mode
mode = 1;
plotPointMode = 0;
goto endDo;
case 30: // record separator >> incremental plot mode
if (DEBUG) printf("Incremental point plot mode\n");
penDown = 1;
mode = 40;
goto endDo;
case 31: // US, normal mode
mode = 0;
goto endDo;
}
// handle skipping coordinate bytes
// this cannot be done in switch(mode) below, because multiple bytes
// can be skipped and the current byte must be executed after a mode change
tag = (ch >> 5) & 3;
if ((mode >= 1) && (mode <= 8)) {
if ((mode == 5) && (ch == 29)) {
if (DEBUG) printf("group separator, go from mode 5 to mode 1\n");
mode = 1;
goto endDo; // goto end of do loop
}
if (DEBUG) {
if (mode & 1)
printf(" mode=%d,tag=%d-H-val=%d,",
mode,tag, 32 * (ch & 31));
else
printf(" mode=%d,tag=%d-L-val=%d,",
mode,tag, ch & 31);
printf("xh=%d,xl=%d,yh=%d,yl=%d\n",xh,xl,yh,yl);
}
if (tag != 0) {
if ((mode == 1) && (tag != 1)) mode = 2;
if ((mode == 3) && (tag == 3)) {
// this overwrites the extra data byte of the 4014 for the
// persistent mode ccordinates and stores it for further use
mode = 2;
xy4014 = yl;
if (DEBUG)
printf("4014 coordinates, overwrite last value\n");
}
if ((mode == 2) && (tag != 3)) mode = 3;
if ((mode == 3) && (tag != 1)) mode = 4;
if ((mode == 5) && (tag != 1)) mode = 6;
if ((mode == 7) && (tag == 3)) {
// this overwrites the extra data byte of the 4014 for the
// persistent mode ccordinates and stores it for further use
mode = 6;
xy4014 = yl;
if (DEBUG)
printf("4014 coordinates, overwrite last value\n");
}
if ((mode == 6) && (tag != 3)) mode = 7;
if ((mode == 7) && (tag != 1)) mode = 8;
}
else {
if (ch == 0) return;
if (ch == 29) mode = 1; // group separator
else if (ch == 28) { plotPointMode = 1; todo = 16 * todo; }
else if (DEBUG) printf("Plot mode, unknown char %d, plotPointMode = %d\n",ch,plotPointMode);
return;
}
}
// handling anything specific to a mode
switch (mode) {
case 1: plotPointMode = 0; // normal graphics mode, starting coordinates
yh = 32 * (ch & 31); mode++;
if (DEBUG) printf("setting yh to %d\n", yh);
break;
case 2: yl = (ch & 31);
mode++;
if (DEBUG) printf("setting yl to %d\n", yl);
break;
case 3: if (tag == 1) xh = 32 * (ch & 31); mode++;
if (DEBUG) printf("setting xh to %d\n", xh);
break;
case 4: xl = (ch & 31);
if (windowWidth != 1024) {
int xb = xy4014 & 3;
tube_x0 = (int)(efactor * (double)(((xh+xl) << 2) + xb) / 4.0);
int yb = (xy4014 >> 2) & 3;
tube_y0 = (int)(efactor * (double)(((yh+yl) << 2) + yb) / 4.0);
}
else {
tube_x0 = xh + xl;
tube_y0 = yh + yl;
}
mode++;
tube_emulateDeflectionTime();
if (DEBUG) printf("setting xl to %d\n", xl);
if (DEBUG) printf("******************************************** Moving to (%d,%d)\n",tube_x0,tube_y0);
break;
case 5: if (ch == 29) {
if (DEBUG) printf("setting mode to 1\n");
mode = 1;
}
else if (tag != 0) {
yh = 32 * (ch & 31); mode++;
}
else if (DEBUG) printf("case 5: tag is 0\n");
if (DEBUG) printf(">>>>>yh=%d\n",yh);
break;
case 6: yl = (ch & 31); mode++;
break;
if (DEBUG) printf(">>>>>yl=%d\n",yl);
case 7: xh = 32 * (ch & 31); mode++;
break;
if (DEBUG) printf(">>>>>xh=%d\n",xh);
case 8: xl = (ch & 31);
if (windowWidth != 1024) {
int xb = xy4014 & 3;
tube_x2 = (int)(efactor * (double)(((xh+xl) << 2) + xb) / 4.0);
int yb = (xy4014 >> 2) & 3;
tube_y2 = (int)(efactor * (double)(((yh+yl) << 2) + yb) / 4.0);
}
else {
tube_x2 = xh + xl;
tube_y2 = yh + yl;
}
if (DEBUG) printf(">>>>>xl=%d\n",xl);
if (plotPointMode>0.0) {
// draw the point
tube_drawPoint(cr, cr2);
todo--;
}
else {
tube_drawVector(cr,cr2);
todo--;
}
showCursor = 0;
tube_x0 = tube_x2; // prepare for additional vectors
tube_y0 = tube_y2;
if (specialPlotMode) mode = 50; // another intensity/focus char follows
else mode = 5;
break;
case 30: // escape code handler
tek4010_escapeCodeHandler(cr, cr2, ch);
break;
case 31: // ANSI CSI sequence
printf("%c",ch);
if ((ch<0x20) || (ch>0x3F)) {
mode=0;
printf("\n");
}
case 40: // incremental plot mode
tek4010_checkReturnToAlpha(ch); // check for exit
if (DEBUG) printf("Incremental plot mode, ch = %d, penDown = %d\n",ch, penDown);
if (ch == 32) penDown = 0;
else if (ch == 80) penDown = 1;
else if ((ch & 0x70) == 0x40){
if (ch & 4) tube_y0++;
if (ch & 1) tube_x0++;
if (ch & 8) tube_y0--;
if (ch & 2) tube_x0--;
if (DEBUG) printf("point (%d,%d)\n", tube_x0, tube_y0);
tube_x2 = tube_x0;
tube_y2 = tube_y0;
if (penDown) tube_drawPoint(cr, cr2);
}
else if (DEBUG) printf("Illegal byte 0x%02X in incremental plot\n", ch);
break;
case 50:// special plot mode
tag = ch >> 5;
if ((ch < 32) || (ch >= 126)) return;
if (DEBUG) printf("intensity/focus control = %c: %d: ", ch, tag);
defocussed = (tag == 1);
intensity = intensityTable[ch - 32];
if (DEBUG) printf("defocussed = %d, intensity = %d%%\n", defocussed, intensity);
mode = 5; // coordinates follow
break;
case 60:// crosshair mode
if (isGinMode > 1) { // key stroken by user
ginSend(isGinMode);
mode = 0;
todo = 0;
if (DEBUG) printf("GIN: key stroken by user, exiting GIN mode\n");
isGinMode = 0;
}
else
ginMode(cr, cr2);
break;
case 101:
if (DEBUG) printf("Ignore until group separator, ch = %02x\n", ch);
if (ch == 29) mode = 1;
break;
case 0: // handle ALPHA mode; 4014 user manual, table page G-1
// some characters are indentical for all modes and handled elsewhere
switch (ch) {
case 0: break;
case 8: // backspace
tube_x0 -= hDotsPerChar;
tek4010_checkLimits(cr, cr2);
break;
case 9: // tab
if (argTab1)
tube_x0 += hDotsPerChar;
else
tube_x0 = tube_x0 - (tube_x0 % (8 * hDotsPerChar)) + 8 * hDotsPerChar;
tek4010_checkLimits(cr, cr2);
break;
case 11: // VT, move one line up
tube_y0 += vDotsPerChar;
tek4010_checkLimits(cr, cr2);
break;
case 23: // ctrl-w screen dump
system("scrot --focussed");
break;
default: if ((ch >= 32) && (ch <127)) { // printable character
tek4010_checkLimits(cr, cr2);
tube_drawCharacter(cr,cr2, ch);
todo-= 2;
}
break;
}
break;
default: if (DEBUG) printf("Illegal mode - this is a tek4010decoder error and should not happen\n");
break;
}
endDo:;
}
while ((todo > 0) && ((tube_mSeconds() - startPaintTime) < refresh_interval));
// display cursor
if (showCursor && (tube_isInput() == 0)) tube_doCursor(cr2);
}