From 97556f671152fcdebfe19f9c8ee05d78d9743ba8 Mon Sep 17 00:00:00 2001 From: Rene Richarz Date: Tue, 5 May 2026 09:55:51 +0200 Subject: [PATCH] Stable PTY terminal mode, ready for testing --- docs/quickstart.md | 44 +++++----- dodekagon.plt | 1 - src/main.c | 8 +- src/tube.c | 82 +++++++++++-------- src/tube.h | 1 + tektests/circles | Bin 0 -> 33816 bytes tektests/circles.c | 10 +-- tektests/circles.plt | 1 - tektests/dodecagon | Bin 0 -> 34488 bytes tektests/dodecagon.c | 29 +++++++ tektests/incremental | Bin 0 -> 33672 bytes tektests/incremental.plt | 1 - tektests/makefile | 5 +- tektests/tekio.c | 170 +++++++++++++++++++++++++++++++++++++++ tektests/tekio.h | 77 ++++++++++++++++++ test.plt | 2 +- 16 files changed, 360 insertions(+), 71 deletions(-) delete mode 100644 dodekagon.plt create mode 100755 tektests/circles delete mode 100644 tektests/circles.plt create mode 100755 tektests/dodecagon create mode 100755 tektests/dodecagon.c create mode 100755 tektests/incremental delete mode 100644 tektests/incremental.plt create mode 100755 tektests/tekio.c create mode 100755 tektests/tekio.h diff --git a/docs/quickstart.md b/docs/quickstart.md index 0d5e3fa..4960823 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -1,56 +1,48 @@ # Tek4010 Quick Start +This is a Tektronix 4010 graphics terminal emulator. +It is not a full VT100/xterm terminal. + Basic usage: - tek4010 [options] command [command options] - -The command is required, for example: cat, head, -telnet, or rsh. + tek4010 [options] --- ## Examples -To use the included examples and demos, go to the -Tek4010 directory first +To use the included examples and demos, start tek4010 with the command + + tek4010 + +In the tek4010 window, change to the Tek4010 directory: + + cd Tek4010 Display a plot file: - tek4010 -noexit cat test.plt - -ARDS example: - - tek4010 -noexit -ARDS cat ardsfiles/trek.pic - -Text output: - - tek4010 -noexit head -n 32 src/tek4010.c + cat test.plt Animation: - tek4010 cat animation.plt + cat animation.plt Demo script: - tek4010 demos/demo.sh - ---- - -## Important option - --noexit - -Keeps the window open after the command finishes. + sh demos/demo.sh --- ## Options +By default, the screen clears automatically when the bottom is reached. +Use -noAutoClear to disable this. + | Option | Description | |----------|------------------------------------------| -| -noexit | Keep window open after command | | -fast | Fast rendering without fading | | -full | Full screen mode (Ctrl-Q to close) | +| -half | Use half of the screen width. | | -b9600… | Emulate terminal baud rates | --- diff --git a/dodekagon.plt b/dodekagon.plt deleted file mode 100644 index 978ea97..0000000 --- a/dodekagon.plt +++ /dev/null @@ -1 +0,0 @@ - ,f:^1u9N ,f:^5u5N ,f:^7e/_ ,f:^5u*O ,f:^1u&O ,f:^,f$_ ,f:^&v&O ,f:^"v*O ,f:^!g/^ ,f:^"v5N ,f:^&v9N 1u9N5u5N 1u9N7e/_ 1u9N5u*O 1u9N1u&O 1u9N,f$_ 1u9N&v&O 1u9N"v*O 1u9N!g/^ 1u9N"v5N 1u9N&v9N 5u5N7e/_ 5u5N5u*O 5u5N1u&O 5u5N,f$_ 5u5N&v&O 5u5N"v*O 5u5N!g/^ 5u5N"v5N 5u5N&v9N 7e/_5u*O 7e/_1u&O 7e/_,f$_ 7e/_&v&O 7e/_"v*O 7e/_!g/^ 7e/_"v5N 7e/_&v9N 5u*O1u&O 5u*O,f$_ 5u*O&v&O 5u*O"v*O 5u*O!g/^ 5u*O"v5N 5u*O&v9N 1u&O,f$_ 1u&O&v&O 1u&O"v*O 1u&O!g/^ 1u&O"v5N 1u&O&v9N ,f$_&v&O ,f$_"v*O ,f$_!g/^ ,f$_"v5N ,f$_&v9N &v&O"v*O &v&O!g/^ &v&O"v5N &v&O&v9N "v*O!g/^ "v*O"v5N "v*O&v9N !g/^"v5N !g/^&v9N "v5N&v9N  ` @ \ No newline at end of file diff --git a/src/main.c b/src/main.c index ef9ce32..fa585e4 100644 --- a/src/main.c +++ b/src/main.c @@ -107,6 +107,9 @@ void check_graphics_response(long lag) long now = tube_mSeconds(); + if (brightCounter <= 0) + return; + // ignore startup phase (first 1000 ms) if (now < STARTUP_IGNORE_MSEC) return; @@ -439,8 +442,11 @@ int main (int argc, char *argv[]) } gtk_window_set_title(GTK_WINDOW(window), windowName); - + + gtk_widget_set_can_focus(window, TRUE); gtk_widget_show_all(window); + gtk_window_present(GTK_WINDOW(window)); + gtk_widget_grab_focus(window); gtk_main(); diff --git a/src/tube.c b/src/tube.c index 62817fd..5a86442 100755 --- a/src/tube.c +++ b/src/tube.c @@ -84,7 +84,7 @@ struct keyCode { struct keyCode keyTable[MAXKEYCODES]; -int argNoexit = 0; // options +int argNoexit = 1; // options int argRaw = 0; int argBaud = 19200; int argTab1 = 0; @@ -92,7 +92,7 @@ int argFull = 0; int argFullV = 0; int argARDS = 0; int argAPL = 0; -int argAutoClear = 0; +int argAutoClear = 1; int argKeepSize = 0; int argHideCursor = 0; int argWait = 0; @@ -119,6 +119,7 @@ int specialPlotMode = 0; int defocussed = 0; int intensity = 100; int aplMode = 0; +pid_t childPid = -1; int argPty = 0; @@ -314,6 +315,8 @@ void tube_init(int argc, char* argv[]) size_t bufsize = 127; int firstArg = 1; int ptyMaster = -1; + argAutoClear = 1; + argNoexit = 1; printf("tek4010 version 2.0\n"); windowName = "Tektronix 4010/4014 emulator"; if (argc > 19) { @@ -338,6 +341,8 @@ void tube_init(int argc, char* argv[]) argRaw = 1; else if (strcmp(argv[firstArg],"-noexit") == 0) argNoexit = 1; + else if (strcmp(argv[firstArg],"-exit") == 0) + argNoexit = 0; else if (strcmp(argv[firstArg],"-b100000") == 0) argBaud = 100000; else if (strcmp(argv[firstArg],"-b38400") == 0) @@ -364,6 +369,8 @@ void tube_init(int argc, char* argv[]) argFullV = 1; else if (strcmp(argv[firstArg],"-autoClear") == 0) argAutoClear = 1; + else if (strcmp(argv[firstArg],"-noAutoClear") == 0) + argAutoClear = 0; else if (strcmp(argv[firstArg],"-keepsize") == 0) argKeepSize = 1; else if (strcmp(argv[firstArg],"-hidecursor") == 0) @@ -429,13 +436,14 @@ void tube_init(int argc, char* argv[]) printf("Cannot fork pseudo terminal\n"); exit(1); } -else if (pid == 0) { - setenv("TERM", "vt100", 1); - setenv("PS1", "Tek4010$ ", 1); - execl("/bin/sh", "sh", "-i", (char *) NULL); - _exit(127); -} - + else if (pid == 0) { + setenv("TERM", "vt100", 1); + setenv("PS1", "tek4010$ ", 1); + execl("/bin/sh", "sh", "-i", (char *) NULL); + _exit(127); + } + + childPid = pid; getDataPipe[0] = ptyMaster; putKeysPipe[1] = dup(ptyMaster); if (putKeysPipe[1] == -1) { @@ -516,6 +524,9 @@ else if (pid == 0) { } // parent process + + childPid = pid; + free(str); close(getDataPipe[1]); // not used @@ -566,31 +577,34 @@ int tube_on_timer_event() // is child process still running? - int status; - if (argWait && (tube_isInput() == 0) && (waitpid(-1, &status, WNOHANG))) { - if (firstWait == 0) - firstWait = tube_mSeconds(); - else { - if ((int)((tube_mSeconds() - firstWait) / 1000) > argWait) { - tube_quit(); - gtk_main_quit(); - printf("Process has been terminated after %d seconds\n", argWait); - exit(0); - } - } - } - else if ((!argNoexit) && (tube_isInput() == 0) && (waitpid(-1, &status, WNOHANG))) { - long t = tube_mSeconds(); - // printf("Execution time: %0.3f sec\n", (double)t/1000.0); - // if (t > 0) { - // printf("Average screen refresh rate: %0.1f Hz\n",(double)(1000.0*refreshCount)/t); - // printf("Average character rate: %0.0f baud\n",(double)(8000.0*charCount)/t); - // } - tube_quit(); - gtk_main_quit(); - printf("Process has been terminated\n"); - exit(0); - } + int status; + int childExited = 0; + + if (childPid > 0) { + if (waitpid(childPid, &status, WNOHANG) == childPid) + childExited = 1; + } + + if (childExited) { + if (argPty || !argNoexit) { + tube_quit(); + gtk_main_quit(); + printf("Process has been terminated\n"); + exit(0); + } + + if (argWait) { + if (firstWait == 0) + firstWait = tube_mSeconds(); + else if ((int)((tube_mSeconds() - firstWait) / 1000) > argWait) { + tube_quit(); + gtk_main_quit(); + printf("Process has been terminated after %d seconds\n", argWait); + exit(0); + } + } + } + if (brightCounter > 0) brightCounter--; diff --git a/src/tube.h b/src/tube.h index fb6564b..680a2f4 100755 --- a/src/tube.h +++ b/src/tube.h @@ -47,6 +47,7 @@ extern int aplMode; extern int plotPointMode; extern int writeThroughMode; +extern pid_t childPid; extern int argPty; extern int tube_x0, tube_x2, tube_y0, tube_y2; diff --git a/tektests/circles b/tektests/circles new file mode 100755 index 0000000000000000000000000000000000000000..3a2a16d1044b6d729f16f3250f4b0dd25bf64bb1 GIT binary patch literal 33816 zcmeI5e{57$7RS$<8R(QLv;|iAWm^rB))3GIS2SjK%Cx&wNg)r&HiUS0Xb0QvFSavX zi`97BN&x)_l4e(8)D{(|ie|GhZYN=vA};&q2L4cD%%^ z{SjmQ!*i4K?mg$+d)_^td*5sSd2|1I?aGZZB8N}{kcE);5Yc|BL5pZ9WD`WGt@S@^ z+}Y@EVe8Gs48GZPi^g#_prcaT8(X&D>^9@0H`~bSb6{o(TDMZE#6Zd_sEXsIF?WvF zg_;ZNoYzbVk)COzp;R)}zdJc&Dvr0f)Qfk&?ZLV~Uf9M1LsOLM?|G`Dr%iSA?CFK2 zI9`K|*JAs#?vH29GZk}t38GX({q}kl+tR$vqZhS{hT4>(nt8D>iwcNRPxkt--8Nn= z`kE4*WzPCsh(*e(*%!0(GA8e$i{|BXannC9)|G1Q?e6aF;Wig9Pp@sR+KU(Vnf$!W z-tqZn_v_}S=EoZwnhJYus%Tz_%Vmj8isSfWttZmVjd#moRO_sM82SKop2HHBA)@)H zD~5^oqK-heLi~m2&cgfnb|s5A*b29l1+dgWcz>e#)uZC_U#bS}#wJdc(g zb)U`+uZyIoBW0Hl%=_$zu+=~u2+=Yu-ZIlR&r$el=ss9Ye#TFPb=Mqcmmf5AzV8MI z`#kQOk%lun7tCkdzGN!Vy=LPY%&TKJI-;zCaQrax;=0c2%!|ui5VmV@d&!$5n{Qk4 zBXlk|=uG5dbY$#I_2k6}WzuKV~Ji)e@{^JMi(yefyB%CDfCds_cL3p)E9 zr}7_GZ^AaJbLdE|Lm7@|^h!_94c1Q}zavvY_3?L+XCc4Boa!9p`-4NB(*=gU{7)gD z8P3SLkXK<$w&b;C*%B|uFc|n_)y*K7g^cSgWuT{gNOWdT#J^+N@2?!5$2uuVeP$ z_(=8Su~_va&u1d0Cdny{jE|_v9r^rkPX+CM40=A!yR5|9ljA{kvS!72Grdt$P8Z@& z9Lx@%uRZwo)%Kr!bhS2^z3MnmzDnVE)v=g5S-;{~^WEroH~P_%c-7cQ)pfpKwwyBK z@cZLTM<_Qo^2GJ6m~*x~nsHW)HBU#PIgV9I167zqBwLN=26N0V|2N|odE>EWquJ%r z%yhMlv1m4igBU+Yer69Kx9}XQOe5E``TU*l!JZpzn8?Q*Z!e$WXErdA!``;f?3WbP z?lk5;bf0$l84fJf?%No55qnH;*6whbb}wQ7yb0SSthuqT)9$#{r#Y`G?Y`pIAJXp8 zLX2hF{o;m=m(cEN*bhR?xR7@L4xedn)$YBp4?*x2a&vL( zZOn2J0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^VfDjM@LO=)z0U;m+ zgn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^VfDjM@LO=)z0U;m+ zzBK|hh>SCXiO&@0Gs?Z+0zd=Be`YzK0bVGk9mT2e(SpSr=imnf95|hOAUK5FX@FlT zl}xqu_NVp|j(bm%+OwytKiN)dZ-1(_J>Ewu*-vE^Uw3){pM#sUx=Ja##yx(#- zR+k`0_;6-4`s3hUt3P0MK2M$f4_Teh17>|A>kL3sC?JP4mp&u6-0TIRfYzYQj;!D8KtQ5lTpYF9!PkSc=|>svsofK&nL|F-DY z{#G`H%tmqRLavKp1Aa$S0I&jPDSiQe3xo?&8P+uclZI#ckJnI_bvvzQ6D3K9&+WW? zSF*M1aO0BB@jtC=El_%U)?>=|p_bt6=FYlQOeRA$xXJAXqocuHI zKlAkdPyhJhrbDaW`lkLX?blb(zqI=O0e|`Pat=6Cac<{L9(expfzZH(k4Oq2$NR>uZor2Wic06s>Hg(!4Ij`Sm-+hnw zE}`1-kN&fp+4tRNpWSD7Kl|*yZ)Wappa0^a(>nniS6t~L0xZNv#B{>E$Vyo^GM1?$mWPHiJbM z+@Sk5ZfG)w=9Nx>y9fn$J2E*kTQq_CZJm~BIIBG`%8KAM>Pv~vL890caL@0TMG-IP zmqo=%Yrk05^_J+F*)+$=8X4k-J*O$-ZsjF>(V{!!|LfOn_}ZG)>r6)&Dd<<+sFdP? zA+Q~*t&51_%#FS8AZ`~*`5@$#D9C-7hv?i*RD=6Og2;pX5~Qz07hJXM!szZt&tL3*?zH3c z$nzkgO9<6)v}%!N{^T5Yd(3gv-Ia)}WjvL z+m~Lx6#WXdh(fd&H@2VNW%Of-l$jTY1&FNo?16t9o#gDZhHS!iJhQ_!l=0d6kBqug z$%H#KV0TZfJ@w-k)~@%r&M#z|{?AZf3gOs|SJ4vsEJ9bJxlVnHf>KJLB+ zsXZF)J2G0ALX&d_N4KP$14Z4}&Z6d=+(#9I38_yQ`sYdw{lMtA4|{3{HqZf28NKA+ zGFC#F0bfC08D*08EtC64w;XP$-M?WW$}U7%a{BASHrjWp#GBD-lN-j$ycu#fxSiBn zH#l088b}n_shq}k)!A(a*mk9~U1hOtuT4$qcg-}m-O_eqYQMk4wriwqx5c&(whQ~c zXsYdGqIOa+na1`Cw!O%kNsfLC^SL>--?ur%e3FUHlg!5sKJOCk6Z6CKA?N45Y_=+I z&M>F9BhTxIH)<4bJXuD=L#PMN!xd;Fn;`g)2LGY{B>d-O2@Ma9>Z!dnv4ZWePZ{>~ zlrvM-{V*AGe)J~xBSV)i@eZ5iv#8JIInQ}PX|8;`Ki-&@x}-hccpCmD%Iqwvq+L|; zZ&R+oqkETD@lVLy52w_>Ys#$Gw2Hqi{}`V+ zF7D5gB5;^{>vdz2o2lb5AHo=NY%xwzUNg$4i+@s`E;h#H#F$N6OOSSIuIq%}4t=qA zc#!B~!QAd0P7_^}<1bkzWjkEf)LYqNpE=VH$@lJ$$v3m($WX>k{bQKZTTlo4A|zjLlX0Q67!~Kv-iA%m^W{u?3cEo4Cayjavw?7xq4XXngSL6XWeg zX|b1%6;ozV+9j=}?qo5qe}5f`eM?Ub`Sg@)r>kZ!{9eO+jfnAGK9n6jyI-Ede7}x4 zHMz`39iFq?+JaupE%FN2BKwNz1G)0BW#&y;i&8fRTPNW+E6~;*1#@7|?N-cf8Rjys z#T#c@=G3Y$Mn27oHx}V;^?}paYfK-omgjsbjW@oJyR|&;X=eH9)@~uAV;^Sk5o3TK z6`}v;cx*@uju=}OWlW}%NH-OXGwajfYYzCamh-j!n0NLmo=4JLB?Fl2pQG*(yYw5o zq2sk!S}dP~c0KPo==|Ki7xv!y(0Kc*Uys+@)8iVR!R#aZeR}>gaGt*|nW&rO_R`p& z2cR!}o+cA`c7jbB`?h#a;(5uoT<|yap(O3bzKuSnYo@7>XC~Jl;QBS*;W4+gf#;%W z13p^9<70mr#MrQ2Dh4suXYlMO7Q9vufs?VPTGwX6Juv`Qrz+vM34P)=Zo^Iw@i@|z z*l)1s^V;)j1|zZmxeDZ&)I9?I9JHPE>8XWS*Mv6l9wg*9F=k$u%z7Pk+RSIGC(u{t zGq=xlS=P$KbyV-K z<987r58m_Vzzk{% z#@2^Af>(3~pbbfFtgp+^Vjid#k?$Tv4jx3~{hS>94!;^QNB;kp1E;Nl{|_j|e`E86 z6(X;Tw0$mQmYZg*rBzxHPy`eKML-cy1QY>9KoL*`6ahs*5l{pa0YyL&Py`eKML-cy z1QY>9KoL*`6ahs*5l{pa0YyL&Py`eKML-cy1QY>9KoL*`6ahs*5l{sFcLL>c{_H9KoL*`6ahs*5l{pa0YyL&Py`eKML-cy1QY>9KoL*`6ahs*5l{pa0YyL&Py`eK zML-cy1QY>9KoL*`6ahs*5l{pa0YyL&Py`eKML-cy1QY>9;1d(@z`~V?U5Ge8QJ&z3 z1cLFseW&jR@e1tEYR5#>mt3i zGfH}}Hxwg%+qQ5|w4L;>NT?&W4fmc{D-JazJsRr3B^C(>J48#GPB;VEIGoTZ;YxMgRL=tM;kP?-$1f6 zLJRFQF&lLbRKe`(i2r)}`qhz8EZE#0>FjB1r)%t#s)c^Sh0C!@T#`6`-PRE9YWLGk z&7E|!Mm9hCc|+%Sf^@59r`s2x&?L?zx8+I1tNAq(gMkoB*Y^1&H~zE#S-I75=_ zhoyW#mftDml{jdV^}D6aXH~MiSIWm^{kx@{l=6?He7mfV^N+=NCZ&8x$}90h7i{l0 zQjW>?UxJK$R*CRBu2wl+Aiq-}|Eoa$ut3JSz`g$ zW{j02l2}c8;enp^e5O}^j>U7eNo1f3m?2zIs)=PL+GNl<}dp50}pTf;!l6u zaEA-)&2eAJARhF^zjv4#ew@)y!KJ`KdIim|LVVQ&%AG|@f;~W c{rrLNesjwkk1Sh!^jC-bYUke{TXdM{KPH6;X8-^I literal 0 HcmV?d00001 diff --git a/tektests/dodecagon.c b/tektests/dodecagon.c new file mode 100755 index 0000000..fafc840 --- /dev/null +++ b/tektests/dodecagon.c @@ -0,0 +1,29 @@ +/* dodecagon.c */ +/* rricharz 2019 */ + + +#include +#include +#include +#include "tekio.h" + +int main (int argc, char *argv[]) +{ + int angle, angle1; + double rad = 3.14159265 / 180; + int xcenter = MAXX / 2; + int ycenter = MAXY / 2; + int radius = 9 * MAXY / 20; + + clearScreen(); + for (angle = 0; angle < 360; angle += 30) { + for (angle1 = angle + 30; angle1 < 360; angle1 += 30) { + drawVector((int)(xcenter + radius * cos(rad * angle)), + (int)(ycenter + radius * sin (rad * angle)), + (int)(xcenter + radius * cos (rad * angle1)), + (int)(ycenter + radius * sin (rad * angle1))); + } + } + moveAlpha(34,0); + exit(0); +} diff --git a/tektests/incremental b/tektests/incremental new file mode 100755 index 0000000000000000000000000000000000000000..41869d08ebf543808fdf7dc83549512e3fcb60e8 GIT binary patch literal 33672 zcmeI5O>9(E6vxk-wlJlYwtymtQVkLyhT;dNE{s!XqYZ@O&_z{}YiXx+LOZ21(@-qP zYxoFCOsJ`Wg^4vWp$%%(AZZs$35h{B(uGJ|7<4t&m=H`VMkv z?mg$;bKX6_cVD}jxnExY>5ozoM<4;{JZO8N$U&(@Ph=7F8K^OvYo4xqzAoIL-kD;9 zXS!~%G*2}q8q-+U)Hrk4#)oG5#J7v!RxR*{jY&p&lfHo_Ki@FcuK8AIF%Y%=uIDHe z*Xwv!V-m@pZHXyYe!dH{ynJ{2Gt|z_7xeRip%r6#V!NWTRuhf2b-|OLFXiWJ^5?6a zo6mPoHOlQc)R@|u#u~G}Vbd0mUdVrFXszV6%1c#QltYc#-j##xrunjUN@$un!UfBm zvCf(6(iy(EdF#sh{Wf=9>N2LKtFyB!mYwF+nYGZmUcO+CE0>quJ2_+1`*maerVVwq z_1V2Pp0_UKRXOZ$EX|Xf>oMF}x#|7!E06lN3*$xDx&~#Haz%>K9_<&=XIcW?49yi~ zr|RD-cWA2Li+J7V`7#%dN~rFys-8r=sw29ss&#iqD{Pf}pt_EO$=bnduUE^N(qk)9 z&qWqL0$(N6fr=~^DO_y(b`8O+g{$DT_1ST}FQ`xRjOHyu?^_MkF^~I3%y6dHg7s|K zok&JHSFc-*bw#&fB4jyK^IvvF^x3WSZRMqMFI2~`pzh<|BGr9U$?TVjbe}VlUM~Yf z=a!CsS0ZD>=gjC~`R#FpFE|6Aw(1Ky<=rPm8r4qibHl^_SgIs6mYttLyd8%x_;Bge z{Pt!yobtzp3fwT>;X#cH?k$=x{Zg?bYggb;WxrFg9k#uvKi-nHb=+|(jBnRti>!2H zV1*-Nn$Ox5o}KQi89{vm;|1noy6?g zZh7cfkyNBG_m@m&;mu;k5reheQcS4W4P(FFQcNXc@DBWC%*Uv42+up+w{8SHEWb72 zRXz*60!uI2{v5B5+GL5pyK-CI)A~OmgjQAmzN>`nb^4<3O)2($x&KDNL==StNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1pX@m<*t4{5}(L*_4AMr*Is!c0TLhq5+DH* zAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8} z0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*_}>Ur;!ZegTDC&<_LpUrsl=XOV4!%IZ!Jvb~p>epoNhDjldXhWEw6%5gB-+L7>`At?H^--< z9HVECdxwh`$k7t4U{o)|#W-Nu#rF{u$^rdWf?1}s-9&mLEj`JIX^%9wM&eQ&iM7_o zn|H|_oz2mh%u6Jj<4NmS*qe|gyA$%jaB<2mMZede%qh3G)%xzTHV%unr zT*n{uZ9N-WZJZ@7WeUUfY@82o?LyzKhK+eT)yjHYbL|az_H5Wes2(?+?V~G|fOcb{ zCR?bng@S6fP=i7Z3jH^zHUIT*OUJRY zXX7isU-sUnR^|M`gzPA;fl_|Br`zZOrv`swA{&HqpFlP_<5tL5~EZ#F~^y&ZnPv3%p6 U7v2b6T61D_@b~-r19d +#include +#include +#include "tekio.h" + +static int xs,ys; + +void startDraw(int x1, int y1) +{ + if (x1 < 0) x1 = 0; + if (x1 >= MAXX) x1 = MAXX -1; + if (y1 < 0) y1 = 0; + if (y1 >= MAXY) y1 = MAXY - 1; + putchar(29); + putchar((y1 >> 5) + 32); + putchar((y1 & 31) + 96); + putchar((x1 >> 5) + 32); + putchar((x1 & 31) + 64); + xs = x1; + ys = y1; +} + +void draw(int x2, int y2) +{ + int hxchange, lychange; + + if (x2 < 0) x2 = 0; + if (x2 >= MAXX) x2 = MAXX -1; + if (y2 < 0) y2 = 0; + if (y2 >= MAXY) y2 = MAXY - 1; + + if ((y2 >> 5) != (ys >> 5)) /* if high y has changed */ + putchar((y2 >> 5) + 32); + hxchange = (x2 >> 5) != (xs >> 5); + lychange = (y2 & 31) != (ys & 31); + if (hxchange || lychange) putchar((y2 & 31) + 96); + if (hxchange) /* if high order x has changed */ + putchar((x2 >> 5) + 32); + putchar((x2 & 31) + 64); + xs = x2; + ys = y2; +} + +void endDraw() +{ + putchar(31); + fflush(stdout); +} + +void moveTo(int x1, int y1) +{ + startDraw(x1,y1); + endDraw(); +} + +void moveAlpha(int line, int column) +{ + int vDotsPerChar; + double hDotsPerChar; + if (line < 1) line = 1; + if (line > MAXLINES) line = MAXLINES; + if (column < 1) column = 1; + if (column > MAXCOLUMNS) column = MAXCOLUMNS; + vDotsPerChar = MAXY / MAXLINES; + hDotsPerChar = (double)(MAXX)/(double)(MAXCOLUMNS); + moveTo((int)((double)(column - 1) * hDotsPerChar), MAXY - line * vDotsPerChar); +} + +void drawVector(int x1, int y1, int x2, int y2) +{ + startDraw(x1,y1); + if (x2 < 0) x2 = 0; + if (x2 >= MAXX) x2 = MAXX -1; + if (y2 < 0) y2 = 0; + if (y2 >= MAXY) y2 = MAXY - 1; + draw(x2,y2); + endDraw(); +} + +void clearScreen() +{ + putchar(27); + putchar(12); +} + + +void startWriteThrough() +{ + putchar(27); + putchar('p'); + fflush(stdout); +} + +void endWriteThrough() +{ + putchar(27); + putchar('`'); + fflush(stdout); +} + +void drawRectangle(int x1, int y1, int x2, int y2) +{ + startDraw(x1,y1); + draw(x2,y1); + draw(x2,y2); + draw(x1,y2); + draw(x1,y1); + endDraw(); +} + +void drawCircle(int x, int y, int r) +{ + int i; + double arg; + startDraw(x + r, y); + for (i = 0; i <= r; i++) { + arg = (double)(i) * PI2 / (double) r; + draw(x + (int)((double)r * cos(arg)), y + (int)((double)r * sin(arg))); + } + endDraw(); +} + +void drawJustifiedText(char *s, int line, int justify) +/* justify 0=left, 1=center; 2=right */ +{ + int length; + length = strlen(s); + switch (justify) { + case 1: moveAlpha(line, 1); break; + case 2: moveAlpha(line, (MAXCOLUMNS - length) / 2); break; + case 3: moveAlpha(line, MAXCOLUMNS - length + 1); break; + } + printf("%s",s); +} + +int fix(double r) +/* round double and convert to int */ +{ + if (r >= 0) return (int)(r + 0.5); + else return (int)(r - 0.5); +} + +void setCharacterSize(int size) +{ + if ((size >= 1) && (size <= 4)) { + putchar(27); + putchar('7' + size); + } + else + printf("setCharacterSize: Illegal size %d\n", size); +} + +void setLineMode(int type) +{ + if ((type >= SOLID) && (type <= LONGDASH)) { + putchar(27); + putchar(95 + type); + } + else + printf("SetLineMode: illegal type %d\n", type); +} + + diff --git a/tektests/tekio.h b/tektests/tekio.h new file mode 100755 index 0000000..927b15c --- /dev/null +++ b/tektests/tekio.h @@ -0,0 +1,77 @@ +/* tecio.h 2.11 BSD Tektronix graphics */ +/* io functions for Tektronix 4010 */ +/* cc 2019 rricharz */ +/* If you want to use this, you need to */ +/* be in tek4010 */ +/* See https://github.com/rricharz/Tek4010 */ + +#define MAXX 1023 /* Tektronix graphics screen size */ +#define MAXY 780 + +#define MAXCOLUMNS 74 /* Tektronix alpha screen size */ +#define MAXLINES 35 + +/* */ +/* clear screen with */ +/* clearScreen() */ +/* */ +/* draw individual vectors with */ +/* drawVector(x1,y1,x2,y2) */ +/* */ +/* draw a string using graphics coordinates */ +/* moveTo(x1,y1) */ +/* printf(.....) */ +/* */ +/* draw a string using alpha coordinates */ +/* moveAlpha(line,column) */ +/* printf(.....) */ +/* */ +/* fast draw multiple joint vectors */ +/* startDraw(x1,y1) */ +/* draw(x2,y2) */ +/* draw(x3,y3) */ +/* ............. */ +/* endDraw() */ +/* */ +/* drawRectange(x1,y1.x2.y2) */ +/* */ +/* drawCircle(x,y,r) */ +/* */ +/* drawJustifiedText(s, line, justify) */ +/* justify 0=left, 1=center; 2=right */ +/* */ +/* writethrough mode for short animations */ +/* startWriteThrough() */ +/* endWriteThrough() */ +/* */ +/* setCharacterSize(size) */ +/* select character size 1..4 */ +/* */ +/* void setLineMode(type) */ +/* set line type */ +/* SOLID,DOTTED,DOTDASH,SHORTDASH,LONGDASH */ + +#define PI 3.14159265 +#define PI2 6.28318531 + +#define SOLID 1 +#define DOTTED 2 +#define DOTDASH 3 +#define SHORTDASH 4 +#define LONGDASH 5 + +extern void drawVector(int x1, int y1, int x2, int y2); +extern void moveTo(int lx, int ly); +extern void moveAlpha(int line, int column); +extern void clearScreen(void); +extern void startDraw(int lx, int ly); +extern void draw(int x2, int y2); +extern void endDraw(void); +extern void startWriteThrough(); +extern void endWriteThrough(); +extern void drawRectangle(int x1, int y1, int x2, int y2); +extern void drawCircle(int x, int y, int r); +extern void drawJustifiedText(char *s, int line, int justify); +extern int fix(double r); +extern void setCharacterSize(int size); +extern void setLineMode(int type); diff --git a/test.plt b/test.plt index 23de809..7cc4b72 100644 --- a/test.plt +++ b/test.plt @@ -1 +1 @@ -6d:Ld M3o*P{:U5w+Z!u O }(Z#s7Y6d9B` ]3p+J~9]4w+H!t \a)Q$q7[6d\5|!N3p,A9Fx*W!s!Jg*H%m7[6c6X5x!_3q,V8O2{*H!r!Xm*^&h7Y6c5V5t"P3r-I}7X1)[!r"Gu+S'a7V6b4X5q#A3r-Zz7B1e)N!r"V~,F'y7Q6a3[5n#S3s.Iv6L0l)D!s#E"g,X(p7K6`3A5k$D3s.Vp5W/u(Z!t#U"q-I)f7D52Jh$U3s/Aj5B.~(R!u$D"|-Y)z6]5~1Tf%E3r/Jc4N.i(K!w$T#g.H*n6T5}1@c%U3r/S2{3[-u(E!z%C#r.U+`6K5{0Na&E3q/Y2s3H-b(@!|%R#~/A+q6B5z/]4~&U3o/_2j2V,p'\"`&A$j/L,b5X5y/N4|'D3m0C2a2E+'Y"c&P$w/W,q5N5w/A4y'R3k0G1w1T+o'W"h&_%c0@-`5D5v.U4w(@3h0I1m1D+a'V"lM%p0H-n4Y5t.J4u(M3e0J1cU*s'U"q\%}0O-{4O5s.A4r(Z3b0K0yG*f'V"w(I&i0V.g4E5q-Y4p)F2~0K0n/Y)z'W"|(W&v0[.s3Z5o-Q4n)Q2z0J0c/L)o'X#b)D'c1@.~3P5n-K4k)\2v0H/y/@)e'Z#i)P'o1D/h3G5l-E4h*F2q0F/n.U({']#p)]'|1G/r2]5j-A4f*P2l0D/d.J(s(@#w*H(h1J/{2S5h,]4c*Y2g0A.y.@(k(D#~*T(t1L0d2J5f,Y4`+A2b/^.o-V(d(H$e*^)`1N0l2A \ No newline at end of file + ,f:^1u9N,f:^5u5N,f:^7e/_,f:^5u*O,f:^1u&O,f:^f%@,f:^&v&O,f:^"v*O,f:^!g/^,f:^"v5N,f:^&v9N1u9N5u5N1u9N7e/_1u9N5u*O1u9Nu&O1u9N,f%@1u9N&v&O1u9N"v*O1u9N!g/^1u9N"v5N1u9N&vN5u5N7e/_5u5Nu*O5u5N1u&O5u5N,f%@5u5N&v&O5u5N"v*O5u5N!g/^5u5N"vN5u5N&v9N7e/_5u*O7e/_1u&O7e/_,f%@7e/_&v&O7e/_"v*O7e/_!g^7e/_"v5N7e/_&v9N5u*O1u&O5u*O,f%@5u*O&v&O5u*O"vO5u*O!g/^5u*O"v5N5u*O&v9N1u&O,f%@1u&O&vO1u&O"v*O1u&O!g/^1u&O"v5N1u&O&v9N,f%@&v&O,f%@"v*O,f%@!g/^,f%@"v5N,f%@&v9N&v&O"v*O&v&O!g/^&v&O"v5N&v&Ov9N"v*O!g/^"v*Ov5N"v*O&v9N!g/^"v5N!g/^&v9N"v5N&v9N!` @ \ No newline at end of file