diff --git a/README.md b/README.md index c54ed7e..c7269fe 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # decstuff Various bits of data and code related to Digital Equipment Corporation + +This repository contains programs and data related, perhaps loosely, +to DEC and its products. + +Current contents: +* Fonts +* TECO diff --git a/fonts/Handbook/Handbook-Regular.ttf b/fonts/Handbook/Handbook-Regular.ttf new file mode 100644 index 0000000..df92982 Binary files /dev/null and b/fonts/Handbook/Handbook-Regular.ttf differ diff --git a/fonts/Handbook/Handbook.otf b/fonts/Handbook/Handbook.otf new file mode 100644 index 0000000..77a6321 Binary files /dev/null and b/fonts/Handbook/Handbook.otf differ diff --git a/fonts/Handbook/Handbook.sfd b/fonts/Handbook/Handbook.sfd new file mode 100644 index 0000000..49af97b --- /dev/null +++ b/fonts/Handbook/Handbook.sfd @@ -0,0 +1,1979 @@ +SplineFontDB: 3.0 +FontName: Handbook +FullName: Handbook +FamilyName: Handbook +Weight: Book +Copyright: (c) Paul Koning +Version: 1.0 +ItalicAngle: 0 +UnderlinePosition: 0 +UnderlineWidth: 0 +Ascent: 800 +Descent: 200 +InvalidEm: 0 +sfntRevision: 0x00010000 +LayerCount: 2 +Layer: 0 1 "Back" 1 +Layer: 1 1 "Fore" 0 +XUID: [1021 82 -590886842 5483728] +StyleMap: 0x0040 +FSType: 0 +OS2Version: 0 +OS2_WeightWidthSlopeOnly: 0 +OS2_UseTypoMetrics: 0 +CreationTime: -2082535712 +ModificationTime: 1461867665 +PfmFamily: 17 +TTFWeight: 400 +TTFWidth: 5 +LineGap: 0 +VLineGap: 0 +Panose: 2 11 6 3 5 3 2 2 2 4 +OS2TypoAscent: 941 +OS2TypoAOffset: 0 +OS2TypoDescent: -201 +OS2TypoDOffset: 0 +OS2TypoLinegap: 0 +OS2WinAscent: 941 +OS2WinAOffset: 0 +OS2WinDescent: 201 +OS2WinDOffset: 0 +HheadAscent: 941 +HheadAOffset: 0 +HheadDescent: -201 +HheadDOffset: 0 +OS2SubXSize: 0 +OS2SubYSize: 0 +OS2SubXOff: 0 +OS2SubYOff: 0 +OS2SupXSize: 0 +OS2SupYSize: 0 +OS2SupXOff: 0 +OS2SupYOff: 0 +OS2StrikeYSize: 0 +OS2StrikeYPos: 0 +OS2FamilyClass: 1283 +OS2Vendor: 'PfEd' +OS2CodePages: 00000001.c0000000 +OS2UnicodeRanges: 00000001.00000000.00000000.00000000 +Lookup: 258 0 0 "'kern' Horizontal Kerning in Latin lookup 0" { "'kern' Horizontal Kerning in Latin lookup 0-1" [153,15,0] } ['kern' ('DFLT' <'dflt' > 'latn' <'dflt' > ) ] +MarkAttachClasses: 1 +DEI: 91125 +KernClass2: 4 5 "'kern' Horizontal Kerning in Latin lookup 0-1" + 1 r + 1 t + 1 f + 13 a c d e g o q + 1 f + 1 t + 1 v + 0 {} 0 {} 0 {} 0 {} 0 {} 0 {} -98 {} 0 {} 42 {} 17 {} 0 {} -78 {} 0 {} -68 {} -98 {} 0 {} -98 {} -59 {} 39 {} 0 {} +ShortTable: maxp 16 + 1 + 0 + 42 + 122 + 3 + 0 + 0 + 1 + 0 + 16 + 0 + 0 + 0 + 0 + 0 + 0 +EndShort +LangName: 1033 "" "" "Regular" "Handbook" "" "" "" "" "" "G. Paul Koning" +Encoding: UnicodeBmp +Compacted: 1 +UnicodeInterp: none +NameList: AGL For New Fonts +DisplaySize: -48 +AntiAlias: 1 +FitToEm: 0 +WidthSeparation: 100 +WinInfo: 0 16 6 +BeginPrivate: 0 +EndPrivate +TeXData: 1 0 0 198656 99328 66218 573440 1048576 66218 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144 +BeginChars: 65539 39 + +StartChar: space +Encoding: 32 32 0 +Width: 300 +Flags: W +LayerCount: 2 +Fore +Validated: 1 +EndChar + +StartChar: period +Encoding: 46 46 1 +Width: 197 +Flags: W +LayerCount: 2 +Fore +SplineSet +101 118 m 0,0,1 + 113 118 113 118 123.5 113.5 c 128,-1,2 + 134 109 134 109 142 101 c 128,-1,3 + 150 93 150 93 154.5 82 c 128,-1,4 + 159 71 159 71 159 60 c 0,5,6 + 159 47 159 47 154.5 36 c 128,-1,7 + 150 25 150 25 142 17.5 c 128,-1,8 + 134 10 134 10 123 5 c 128,-1,9 + 112 0 112 0 101 0 c 0,10,11 + 88 0 88 0 77 5 c 128,-1,12 + 66 10 66 10 58.5 17.5 c 128,-1,13 + 51 25 51 25 46 36 c 128,-1,14 + 41 47 41 47 41 60 c 0,15,16 + 41 72 41 72 46 82.5 c 128,-1,17 + 51 93 51 93 58.5 101 c 128,-1,18 + 66 109 66 109 77 113.5 c 128,-1,19 + 88 118 88 118 101 118 c 0,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: a +Encoding: 97 97 2 +Width: 637 +Flags: W +LayerCount: 2 +Fore +SplineSet +313 120 m 0,0,1 + 344 120 344 120 372.5 132.5 c 128,-1,2 + 401 145 401 145 421.5 166 c 128,-1,3 + 442 187 442 187 454.5 214.5 c 128,-1,4 + 467 242 467 242 467 274 c 0,5,6 + 467 305 467 305 454.5 333.5 c 128,-1,7 + 442 362 442 362 421.5 382.5 c 128,-1,8 + 401 403 401 403 373 415.5 c 128,-1,9 + 345 428 345 428 313 428 c 0,10,11 + 281 428 281 428 253.5 415.5 c 128,-1,12 + 226 403 226 403 205 382.5 c 128,-1,13 + 184 362 184 362 171.5 334 c 128,-1,14 + 159 306 159 306 159 274 c 0,15,16 + 159 242 159 242 171.5 214.5 c 128,-1,17 + 184 187 184 187 205 166 c 128,-1,18 + 226 145 226 145 253.5 132.5 c 128,-1,19 + 281 120 281 120 313 120 c 0,0,1 +469 52 m 1,20,21 + 452 40 452 40 433.5 30.5 c 128,-1,22 + 415 21 415 21 394.5 14 c 128,-1,23 + 374 7 374 7 353.5 3.5 c 128,-1,24 + 333 0 333 0 313 0 c 0,25,26 + 285 0 285 0 258 6 c 128,-1,27 + 231 12 231 12 207 22 c 128,-1,28 + 183 32 183 32 161 47 c 128,-1,29 + 139 62 139 62 120.5 81 c 128,-1,30 + 102 100 102 100 86.5 122 c 128,-1,31 + 71 144 71 144 61 168.5 c 128,-1,32 + 51 193 51 193 45 219.5 c 128,-1,33 + 39 246 39 246 39 274 c 0,34,35 + 39 301 39 301 45 328 c 128,-1,36 + 51 355 51 355 61 379.5 c 128,-1,37 + 71 404 71 404 86.5 426 c 128,-1,38 + 102 448 102 448 120.5 467 c 128,-1,39 + 139 486 139 486 161 501 c 128,-1,40 + 183 516 183 516 207 526.5 c 128,-1,41 + 231 537 231 537 258 542.5 c 128,-1,42 + 285 548 285 548 313 548 c 0,43,44 + 333 548 333 548 353.5 544.5 c 128,-1,45 + 374 541 374 541 394.5 534 c 128,-1,46 + 415 527 415 527 433.5 518 c 128,-1,47 + 452 509 452 509 469 497 c 1,48,-1 + 469 544 l 1,49,-1 + 587 544 l 1,50,-1 + 587 0 l 1,51,-1 + 469 0 l 1,52,-1 + 469 52 l 1,20,21 +EndSplineSet +Validated: 1 +EndChar + +StartChar: b +Encoding: 98 98 3 +Width: 640 +Flags: W +LayerCount: 2 +Fore +SplineSet +322 120 m 0,0,1 + 354 120 354 120 382 132.5 c 128,-1,2 + 410 145 410 145 431 166 c 128,-1,3 + 452 187 452 187 464.5 214.5 c 128,-1,4 + 477 242 477 242 477 274 c 0,5,6 + 477 305 477 305 464.5 333.5 c 128,-1,7 + 452 362 452 362 431 382.5 c 128,-1,8 + 410 403 410 403 382 415.5 c 128,-1,9 + 354 428 354 428 322 428 c 0,10,11 + 291 428 291 428 262.5 415.5 c 128,-1,12 + 234 403 234 403 213 382.5 c 128,-1,13 + 192 362 192 362 180.5 334 c 128,-1,14 + 169 306 169 306 169 274 c 0,15,16 + 169 242 169 242 180.5 214.5 c 128,-1,17 + 192 187 192 187 213 166 c 128,-1,18 + 234 145 234 145 262.5 132.5 c 128,-1,19 + 291 120 291 120 322 120 c 0,0,1 +166 52 m 1,20,-1 + 166 2 l 1,21,-1 + 48 2 l 1,22,-1 + 46 742 l 1,23,-1 + 166 744 l 1,24,-1 + 166 497 l 1,25,26 + 183 509 183 509 202 518 c 128,-1,27 + 221 527 221 527 241 534 c 128,-1,28 + 261 541 261 541 282 544.5 c 128,-1,29 + 303 548 303 548 322 548 c 0,30,31 + 350 548 350 548 376.5 542.5 c 128,-1,32 + 403 537 403 537 428 526.5 c 128,-1,33 + 453 516 453 516 475 501 c 128,-1,34 + 497 486 497 486 515.5 467 c 128,-1,35 + 534 448 534 448 549 426 c 128,-1,36 + 564 404 564 404 574.5 379.5 c 128,-1,37 + 585 355 585 355 591 328.5 c 128,-1,38 + 597 302 597 302 597 274 c 0,39,40 + 597 246 597 246 591 219.5 c 128,-1,41 + 585 193 585 193 574.5 168.5 c 128,-1,42 + 564 144 564 144 549 122 c 128,-1,43 + 534 100 534 100 515.5 81 c 128,-1,44 + 497 62 497 62 475 47 c 128,-1,45 + 453 32 453 32 428 22 c 128,-1,46 + 403 12 403 12 377 6 c 128,-1,47 + 351 0 351 0 322 0 c 0,48,49 + 302 0 302 0 281.5 3.5 c 128,-1,50 + 261 7 261 7 241 14 c 128,-1,51 + 221 21 221 21 202 30.5 c 128,-1,52 + 183 40 183 40 166 52 c 1,20,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: c +Encoding: 99 99 4 +Width: 586 +Flags: W +LayerCount: 2 +Fore +SplineSet +550 411 m 1,0,-1 + 446 351 l 1,1,2 + 435 369 435 369 421 383 c 128,-1,3 + 407 397 407 397 390 407 c 128,-1,4 + 373 417 373 417 353 422 c 0,5,6 + 332 428 332 428 312 428 c 0,7,8 + 281 428 281 428 253 416 c 128,-1,9 + 225 404 225 404 204 383 c 128,-1,10 + 183 362 183 362 170.5 334 c 128,-1,11 + 158 306 158 306 158 273 c 0,12,13 + 158 242 158 242 170.5 214 c 128,-1,14 + 183 186 183 186 204 165 c 128,-1,15 + 225 144 225 144 253 132 c 0,16,17 + 280 119 280 119 312 119 c 0,18,19 + 333 119 333 119 353 124.5 c 128,-1,20 + 373 130 373 130 390 140 c 128,-1,21 + 407 150 407 150 422 165 c 128,-1,22 + 437 180 437 180 446 197 c 1,23,-1 + 549 137 l 1,24,25 + 531 106 531 106 505.5 80.5 c 128,-1,26 + 480 55 480 55 449.5 37.5 c 128,-1,27 + 419 20 419 20 384.5 10 c 128,-1,28 + 350 0 350 0 312 0 c 0,29,30 + 284 0 284 0 257.5 5.5 c 128,-1,31 + 231 11 231 11 206.5 21.5 c 128,-1,32 + 182 32 182 32 160 47 c 128,-1,33 + 138 62 138 62 119.5 80.5 c 128,-1,34 + 101 99 101 99 86 121 c 128,-1,35 + 71 143 71 143 60.5 167.5 c 128,-1,36 + 50 192 50 192 44.5 218.5 c 128,-1,37 + 39 245 39 245 39 273 c 256,38,39 + 39 301 39 301 44.5 328 c 128,-1,40 + 50 355 50 355 60.5 380 c 128,-1,41 + 71 405 71 405 86 426.5 c 128,-1,42 + 101 448 101 448 119.5 467 c 128,-1,43 + 138 486 138 486 160 501 c 128,-1,44 + 182 516 182 516 206.5 526 c 128,-1,45 + 231 536 231 536 257.5 542 c 128,-1,46 + 284 548 284 548 312 548 c 0,47,48 + 349 548 349 548 384 538 c 128,-1,49 + 419 528 419 528 449.5 510.5 c 128,-1,50 + 480 493 480 493 506 467.5 c 128,-1,51 + 532 442 532 442 550 411 c 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: d +Encoding: 100 100 5 +Width: 637 +Flags: W +LayerCount: 2 +Fore +SplineSet +313 120 m 0,0,1 + 344 120 344 120 372.5 132.5 c 128,-1,2 + 401 145 401 145 421.5 166 c 128,-1,3 + 442 187 442 187 454.5 214.5 c 128,-1,4 + 467 242 467 242 467 274 c 0,5,6 + 467 305 467 305 454.5 333.5 c 128,-1,7 + 442 362 442 362 421.5 382.5 c 128,-1,8 + 401 403 401 403 373 415.5 c 128,-1,9 + 345 428 345 428 313 428 c 0,10,11 + 281 428 281 428 253.5 415.5 c 128,-1,12 + 226 403 226 403 205 382.5 c 128,-1,13 + 184 362 184 362 171.5 334 c 128,-1,14 + 159 306 159 306 159 274 c 0,15,16 + 159 242 159 242 171.5 214.5 c 128,-1,17 + 184 187 184 187 205 166 c 128,-1,18 + 226 145 226 145 253.5 132.5 c 128,-1,19 + 281 120 281 120 313 120 c 0,0,1 +469 52 m 1,20,21 + 452 40 452 40 433.5 30.5 c 128,-1,22 + 415 21 415 21 394.5 14 c 128,-1,23 + 374 7 374 7 353.5 3.5 c 128,-1,24 + 333 0 333 0 313 0 c 0,25,26 + 285 0 285 0 258 6 c 128,-1,27 + 231 12 231 12 207 22 c 128,-1,28 + 183 32 183 32 161 47 c 128,-1,29 + 139 62 139 62 120.5 81 c 128,-1,30 + 102 100 102 100 86.5 122 c 128,-1,31 + 71 144 71 144 61 168.5 c 128,-1,32 + 51 193 51 193 45 219.5 c 128,-1,33 + 39 246 39 246 39 274 c 0,34,35 + 39 301 39 301 45 328 c 128,-1,36 + 51 355 51 355 61 379.5 c 128,-1,37 + 71 404 71 404 86.5 426 c 128,-1,38 + 102 448 102 448 120.5 467 c 128,-1,39 + 139 486 139 486 161 501 c 128,-1,40 + 183 516 183 516 207 526.5 c 128,-1,41 + 231 537 231 537 258 542.5 c 128,-1,42 + 285 548 285 548 313 548 c 0,43,44 + 333 548 333 548 353.5 544.5 c 128,-1,45 + 374 541 374 541 394.5 534 c 128,-1,46 + 415 527 415 527 433.5 518 c 128,-1,47 + 452 509 452 509 469 497 c 1,48,-1 + 469 744 l 1,49,-1 + 587 744 l 1,50,-1 + 587 2 l 1,51,-1 + 469 2 l 1,52,-1 + 469 52 l 1,20,21 +EndSplineSet +Validated: 1 +EndChar + +StartChar: e +Encoding: 101 101 6 +Width: 630 +Flags: W +LayerCount: 2 +Fore +SplineSet +453 332 m 1,0,1 + 445 353 445 353 430.5 370.5 c 128,-1,2 + 416 388 416 388 397.5 400.5 c 128,-1,3 + 379 413 379 413 357.5 420.5 c 128,-1,4 + 336 428 336 428 313 428 c 0,5,6 + 290 428 290 428 268 421 c 128,-1,7 + 246 414 246 414 228 401.5 c 128,-1,8 + 210 389 210 389 196 371.5 c 128,-1,9 + 182 354 182 354 173 332 c 1,10,-1 + 453 332 l 1,0,1 +175 214 m 1,11,12 + 183 193 183 193 197 175.5 c 128,-1,13 + 211 158 211 158 229 146 c 128,-1,14 + 247 134 247 134 269 127 c 128,-1,15 + 291 120 291 120 313 120 c 0,16,17 + 332 120 332 120 351 125.5 c 128,-1,18 + 370 131 370 131 387 141 c 128,-1,19 + 404 151 404 151 418.5 165.5 c 128,-1,20 + 433 180 433 180 442 198 c 1,21,-1 + 552 138 l 1,22,23 + 532 108 532 108 505.5 82.5 c 128,-1,24 + 479 57 479 57 448.5 38.5 c 128,-1,25 + 418 20 418 20 383.5 10 c 128,-1,26 + 349 0 349 0 313 0 c 0,27,28 + 285 0 285 0 258 6 c 128,-1,29 + 231 12 231 12 207 22 c 128,-1,30 + 183 32 183 32 161 47 c 128,-1,31 + 139 62 139 62 120.5 81 c 128,-1,32 + 102 100 102 100 86.5 122 c 128,-1,33 + 71 144 71 144 61 168 c 128,-1,34 + 51 192 51 192 45 219 c 128,-1,35 + 39 246 39 246 39 273 c 0,36,37 + 39 301 39 301 45 328 c 128,-1,38 + 51 355 51 355 61 379.5 c 128,-1,39 + 71 404 71 404 86.5 426 c 128,-1,40 + 102 448 102 448 120.5 466.5 c 128,-1,41 + 139 485 139 485 161 500.5 c 128,-1,42 + 183 516 183 516 207 526 c 128,-1,43 + 231 536 231 536 258 542 c 128,-1,44 + 285 548 285 548 313 548 c 0,45,46 + 340 548 340 548 367.5 542 c 128,-1,47 + 395 536 395 536 419 526 c 128,-1,48 + 443 516 443 516 465 500.5 c 128,-1,49 + 487 485 487 485 505.5 466.5 c 128,-1,50 + 524 448 524 448 539.5 426 c 128,-1,51 + 555 404 555 404 565.5 379.5 c 128,-1,52 + 576 355 576 355 581.5 328.5 c 128,-1,53 + 587 302 587 302 587 273 c 0,54,55 + 587 258 587 258 584 243 c 128,-1,56 + 581 228 581 228 578 214 c 1,57,-1 + 175 214 l 1,11,12 +EndSplineSet +Validated: 1 +EndChar + +StartChar: g +Encoding: 103 103 7 +Width: 637 +Flags: W +LayerCount: 2 +Fore +SplineSet +159 273 m 0,0,1 + 159 242 159 242 171.5 214.5 c 128,-1,2 + 184 187 184 187 205 166 c 128,-1,3 + 226 145 226 145 253.5 132.5 c 128,-1,4 + 281 120 281 120 313 120 c 0,5,6 + 344 120 344 120 372.5 132.5 c 128,-1,7 + 401 145 401 145 422 166 c 0,8,9 + 444 188 444 188 456 214 c 128,-1,10 + 468 240 468 240 468 269 c 0,11,12 + 468 271 468 271 468 273 c 0,13,14 + 468 305 468 305 455.5 333 c 128,-1,15 + 443 361 443 361 422 382 c 128,-1,16 + 401 403 401 403 373 415.5 c 128,-1,17 + 345 428 345 428 313 428 c 128,-1,18 + 281 428 281 428 253.5 415.5 c 128,-1,19 + 226 403 226 403 205 382 c 128,-1,20 + 184 361 184 361 171.5 333 c 128,-1,21 + 159 305 159 305 159 273 c 0,0,1 +39 274 m 256,22,23 + 39 302 39 302 45 328.5 c 128,-1,24 + 51 355 51 355 61 379.5 c 128,-1,25 + 71 404 71 404 86.5 426 c 128,-1,26 + 102 448 102 448 120.5 467 c 128,-1,27 + 139 486 139 486 161 501 c 128,-1,28 + 183 516 183 516 207 526.5 c 128,-1,29 + 231 537 231 537 258 542.5 c 128,-1,30 + 285 548 285 548 313 548 c 0,31,32 + 333 548 333 548 353.5 544.5 c 128,-1,33 + 374 541 374 541 394.5 534 c 128,-1,34 + 415 527 415 527 433.5 518 c 128,-1,35 + 452 509 452 509 469 497 c 1,36,-1 + 469 544 l 1,37,-1 + 587 544 l 1,38,-1 + 587 72 l 2,39,40 + 587 44 587 44 581.5 18 c 128,-1,41 + 576 -8 576 -8 566 -32.5 c 128,-1,42 + 556 -57 556 -57 540.5 -79 c 128,-1,43 + 525 -101 525 -101 506.5 -119.5 c 128,-1,44 + 488 -138 488 -138 466 -153 c 128,-1,45 + 444 -168 444 -168 420 -178 c 128,-1,46 + 396 -188 396 -188 369 -194 c 128,-1,47 + 342 -200 342 -200 313 -200 c 0,48,49 + 267 -200 267 -200 225 -185 c 128,-1,50 + 183 -170 183 -170 147.5 -143.5 c 128,-1,51 + 112 -117 112 -117 87 -80 c 128,-1,52 + 62 -43 62 -43 50 0 c 1,53,-1 + 177 0 l 1,54,55 + 188 -18 188 -18 202 -33 c 128,-1,56 + 216 -48 216 -48 234 -58.5 c 128,-1,57 + 252 -69 252 -69 272 -75 c 128,-1,58 + 292 -81 292 -81 313 -81 c 0,59,60 + 341 -81 341 -81 367.5 -71 c 128,-1,61 + 394 -61 394 -61 414.5 -42.5 c 128,-1,62 + 435 -24 435 -24 448.5 -0.5 c 128,-1,63 + 462 23 462 23 466 51 c 1,64,65 + 448 40 448 40 430 30.5 c 128,-1,66 + 412 21 412 21 392.5 14.5 c 128,-1,67 + 373 8 373 8 353 4 c 128,-1,68 + 333 0 333 0 313 0 c 0,69,70 + 285 0 285 0 258.5 6 c 128,-1,71 + 232 12 232 12 207.5 22 c 128,-1,72 + 183 32 183 32 161 47 c 128,-1,73 + 139 62 139 62 120.5 81 c 128,-1,74 + 102 100 102 100 86.5 122 c 128,-1,75 + 71 144 71 144 61 168.5 c 128,-1,76 + 51 193 51 193 45 219.5 c 128,-1,77 + 39 246 39 246 39 274 c 256,22,23 +EndSplineSet +Validated: 1 +EndChar + +StartChar: h +Encoding: 104 104 8 +Width: 641 +Flags: W +LayerCount: 2 +Fore +SplineSet +594 274 m 2,0,-1 + 594 0 l 1,1,-1 + 475 0 l 1,2,-1 + 475 276 l 2,3,4 + 474 307 474 307 461.5 335 c 128,-1,5 + 449 363 449 363 428.5 383.5 c 128,-1,6 + 408 404 408 404 380 416 c 128,-1,7 + 352 428 352 428 320 428 c 0,8,9 + 304 428 304 428 289 424.5 c 128,-1,10 + 274 421 274 421 260 414 c 128,-1,11 + 246 407 246 407 233.5 398.5 c 128,-1,12 + 221 390 221 390 210 378.5 c 128,-1,13 + 199 367 199 367 191 355 c 128,-1,14 + 183 343 183 343 177 329 c 128,-1,15 + 171 315 171 315 167.5 301.5 c 128,-1,16 + 164 288 164 288 164 274 c 2,17,-1 + 164 2 l 1,18,-1 + 46 2 l 1,19,-1 + 46 744 l 1,20,-1 + 164 744 l 1,21,-1 + 164 497 l 1,22,23 + 181 509 181 509 200 518 c 128,-1,24 + 219 527 219 527 239 534 c 128,-1,25 + 259 541 259 541 279.5 544.5 c 128,-1,26 + 300 548 300 548 320 548 c 0,27,28 + 348 548 348 548 374.5 542.5 c 128,-1,29 + 401 537 401 537 425.5 526.5 c 128,-1,30 + 450 516 450 516 472 500.5 c 128,-1,31 + 494 485 494 485 513 466.5 c 128,-1,32 + 532 448 532 448 547 426 c 128,-1,33 + 562 404 562 404 572.5 379.5 c 128,-1,34 + 583 355 583 355 588.5 328 c 128,-1,35 + 594 301 594 301 594 274 c 2,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: i +Encoding: 105 105 9 +Width: 214 +Flags: W +LayerCount: 2 +Fore +SplineSet +105 744 m 0,0,1 + 117 744 117 744 128 739.5 c 128,-1,2 + 139 735 139 735 147 727 c 128,-1,3 + 155 719 155 719 159.5 708 c 128,-1,4 + 164 697 164 697 164 686 c 0,5,6 + 164 673 164 673 159.5 662 c 128,-1,7 + 155 651 155 651 147 643 c 128,-1,8 + 139 635 139 635 128 630.5 c 128,-1,9 + 117 626 117 626 105 626 c 0,10,11 + 92 626 92 626 81.5 630.5 c 128,-1,12 + 71 635 71 635 63.5 643 c 128,-1,13 + 56 651 56 651 51 662 c 128,-1,14 + 46 673 46 673 46 686 c 0,15,16 + 46 698 46 698 51 708.5 c 128,-1,17 + 56 719 56 719 63.5 727 c 128,-1,18 + 71 735 71 735 81.5 739.5 c 128,-1,19 + 92 744 92 744 105 744 c 0,0,1 +46 549 m 1,20,-1 + 164 549 l 1,21,-1 + 164 0 l 1,22,-1 + 46 0 l 1,23,-1 + 46 549 l 1,20,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: k +Encoding: 107 107 10 +Width: 539 +Flags: W +LayerCount: 2 +Fore +SplineSet +499 0 m 1,0,1 + 494 0 l 0,2,3 + 488 0 488 0 480 0 c 128,-1,4 + 472 0 472 0 460.5 0 c 128,-1,5 + 449 0 449 0 438 0 c 128,-1,6 + 427 0 427 0 416 0 c 128,-1,7 + 405 0 405 0 396.5 0 c 128,-1,8 + 388 0 388 0 383 0 c 0,9,-1 + 378 0 l 1,10,11 + 378 22 378 22 373.5 42.5 c 128,-1,12 + 369 63 369 63 361 83 c 128,-1,13 + 353 103 353 103 341 120 c 128,-1,14 + 329 137 329 137 315 151 c 128,-1,15 + 301 165 301 165 284 176.5 c 128,-1,16 + 267 188 267 188 247.5 196.5 c 128,-1,17 + 228 205 228 205 207.5 209.5 c 128,-1,18 + 187 214 187 214 164 214 c 1,19,-1 + 164 0 l 1,20,-1 + 46 0 l 1,21,-1 + 46 745 l 1,22,-1 + 164 745 l 1,23,-1 + 164 334 l 1,24,25 + 186 334 186 334 207 338.5 c 128,-1,26 + 228 343 228 343 247 351 c 128,-1,27 + 266 359 266 359 283 370.5 c 128,-1,28 + 300 382 300 382 314.5 396.5 c 128,-1,29 + 329 411 329 411 340.5 428 c 128,-1,30 + 352 445 352 445 360 464 c 128,-1,31 + 368 483 368 483 372.5 504 c 128,-1,32 + 377 525 377 525 377 547 c 1,33,-1 + 497 547 l 1,34,35 + 497 507 497 507 487.5 468 c 128,-1,36 + 478 429 478 429 459.5 393.5 c 128,-1,37 + 441 358 441 358 415.5 328 c 128,-1,38 + 390 298 390 298 356 274 c 1,39,40 + 389 252 389 252 415.5 221 c 128,-1,41 + 442 190 442 190 460.5 154.5 c 128,-1,42 + 479 119 479 119 489 80 c 128,-1,43 + 499 41 499 41 499 0 c 1,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: l +Encoding: 108 108 11 +Width: 214 +Flags: W +LayerCount: 2 +Fore +SplineSet +46 744 m 1,0,-1 + 164 744 l 1,1,-1 + 164 0 l 1,2,-1 + 46 0 l 1,3,-1 + 46 744 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: m +Encoding: 109 109 12 +Width: 1070 +Flags: W +LayerCount: 2 +Fore +SplineSet +1022 274 m 2,0,-1 + 1022 0 l 1,1,-1 + 902 0 l 1,2,-1 + 902 276 l 2,3,4 + 902 307 902 307 890 335 c 128,-1,5 + 878 363 878 363 857 383.5 c 128,-1,6 + 836 404 836 404 808 416 c 128,-1,7 + 780 428 780 428 748 428 c 0,8,9 + 732 428 732 428 717 424.5 c 128,-1,10 + 702 421 702 421 688 414.5 c 128,-1,11 + 674 408 674 408 661.5 399 c 128,-1,12 + 649 390 649 390 638.5 379 c 128,-1,13 + 628 368 628 368 619 355.5 c 128,-1,14 + 610 343 610 343 604.5 329 c 128,-1,15 + 599 315 599 315 596 301.5 c 128,-1,16 + 593 288 593 288 593 274 c 2,17,-1 + 593 2 l 1,18,-1 + 475 3 l 1,19,-1 + 475 279 l 2,20,21 + 474 311 474 311 461.5 338.5 c 128,-1,22 + 449 366 449 366 428.5 386.5 c 128,-1,23 + 408 407 408 407 380 419.5 c 128,-1,24 + 352 432 352 432 320 432 c 0,25,26 + 304 432 304 432 289 428 c 128,-1,27 + 274 424 274 424 260 417.5 c 128,-1,28 + 246 411 246 411 233.5 402 c 128,-1,29 + 221 393 221 393 210 382 c 128,-1,30 + 199 371 199 371 191 358.5 c 128,-1,31 + 183 346 183 346 177 332.5 c 128,-1,32 + 171 319 171 319 167.5 305 c 128,-1,33 + 164 291 164 291 164 277 c 2,34,-1 + 164 6 l 1,35,-1 + 46 6 l 1,36,-1 + 46 547 l 1,37,-1 + 164 547 l 1,38,-1 + 164 500 l 1,39,40 + 181 512 181 512 200 521.5 c 128,-1,41 + 219 531 219 531 239 537.5 c 128,-1,42 + 259 544 259 544 279.5 548 c 128,-1,43 + 300 552 300 552 320 552 c 0,44,45 + 352 552 352 552 383 544 c 128,-1,46 + 414 536 414 536 441.5 522.5 c 128,-1,47 + 469 509 469 509 492.5 489.5 c 128,-1,48 + 516 470 516 470 534 445 c 1,49,50 + 554 469 554 469 578.5 488.5 c 128,-1,51 + 603 508 603 508 630 521 c 128,-1,52 + 657 534 657 534 687.5 541 c 128,-1,53 + 718 548 718 548 748 548 c 0,54,55 + 776 548 776 548 803 542.5 c 128,-1,56 + 830 537 830 537 855 527 c 128,-1,57 + 880 517 880 517 902 501.5 c 128,-1,58 + 924 486 924 486 942.5 467.5 c 128,-1,59 + 961 449 961 449 975.5 427 c 128,-1,60 + 990 405 990 405 1000.5 380.5 c 128,-1,61 + 1011 356 1011 356 1016.5 329 c 128,-1,62 + 1022 302 1022 302 1022 274 c 2,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: n +Encoding: 110 110 13 +Width: 641 +Flags: W +LayerCount: 2 +Fore +SplineSet +594 274 m 2,0,-1 + 594 0 l 1,1,-1 + 475 0 l 1,2,-1 + 475 276 l 2,3,4 + 474 307 474 307 461.5 335 c 128,-1,5 + 449 363 449 363 428.5 383.5 c 128,-1,6 + 408 404 408 404 380 416 c 128,-1,7 + 352 428 352 428 320 428 c 0,8,9 + 304 428 304 428 289 424.5 c 128,-1,10 + 274 421 274 421 260 414 c 128,-1,11 + 246 407 246 407 233.5 398.5 c 128,-1,12 + 221 390 221 390 210 378.5 c 128,-1,13 + 199 367 199 367 191 355 c 128,-1,14 + 183 343 183 343 177 329 c 128,-1,15 + 171 315 171 315 167.5 301.5 c 128,-1,16 + 164 288 164 288 164 274 c 2,17,-1 + 164 2 l 1,18,-1 + 46 2 l 1,19,-1 + 46 544 l 1,20,-1 + 164 544 l 1,21,-1 + 164 497 l 1,22,23 + 181 509 181 509 200 518 c 128,-1,24 + 219 527 219 527 239 534 c 128,-1,25 + 259 541 259 541 279.5 544.5 c 128,-1,26 + 300 548 300 548 320 548 c 0,27,28 + 348 548 348 548 374.5 542.5 c 128,-1,29 + 401 537 401 537 425.5 526.5 c 128,-1,30 + 450 516 450 516 472 500.5 c 128,-1,31 + 494 485 494 485 513 466.5 c 128,-1,32 + 532 448 532 448 547 426 c 128,-1,33 + 562 404 562 404 572.5 379.5 c 128,-1,34 + 583 355 583 355 588.5 328 c 128,-1,35 + 594 301 594 301 594 274 c 2,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: o +Encoding: 111 111 14 +Width: 631 +Flags: W +LayerCount: 2 +Fore +SplineSet +312 0 m 256,0,1 + 284 0 284 0 257.5 5.5 c 128,-1,2 + 231 11 231 11 206.5 21.5 c 128,-1,3 + 182 32 182 32 160 47 c 128,-1,4 + 138 62 138 62 119.5 80.5 c 128,-1,5 + 101 99 101 99 86 121 c 128,-1,6 + 71 143 71 143 60.5 167.5 c 128,-1,7 + 50 192 50 192 44.5 218.5 c 128,-1,8 + 39 245 39 245 39 273 c 256,9,10 + 39 301 39 301 44.5 328 c 128,-1,11 + 50 355 50 355 60.5 380 c 128,-1,12 + 71 405 71 405 86 426.5 c 128,-1,13 + 101 448 101 448 119.5 467 c 128,-1,14 + 138 486 138 486 160 501 c 128,-1,15 + 182 516 182 516 206.5 526 c 128,-1,16 + 231 536 231 536 257.5 542 c 128,-1,17 + 284 548 284 548 312 548 c 256,18,19 + 340 548 340 548 367.5 542 c 128,-1,20 + 395 536 395 536 419.5 526 c 128,-1,21 + 444 516 444 516 465.5 501 c 128,-1,22 + 487 486 487 486 506 467 c 128,-1,23 + 525 448 525 448 540 426.5 c 128,-1,24 + 555 405 555 405 565 380 c 128,-1,25 + 575 355 575 355 581 328.5 c 128,-1,26 + 587 302 587 302 587 273 c 256,27,28 + 587 245 587 245 581 218.5 c 128,-1,29 + 575 192 575 192 565 167.5 c 128,-1,30 + 555 143 555 143 540 121 c 128,-1,31 + 525 99 525 99 506 80.5 c 128,-1,32 + 487 62 487 62 465.5 47 c 128,-1,33 + 444 32 444 32 419.5 21.5 c 128,-1,34 + 395 11 395 11 367.5 5.5 c 128,-1,35 + 340 0 340 0 312 0 c 256,0,1 +312 119 m 0,36,37 + 344 119 344 119 372.5 131.5 c 128,-1,38 + 401 144 401 144 422 165 c 128,-1,39 + 443 186 443 186 455.5 214 c 128,-1,40 + 468 242 468 242 468 273 c 0,41,42 + 468 305 468 305 455.5 333.5 c 128,-1,43 + 443 362 443 362 422 383 c 128,-1,44 + 401 404 401 404 373 416 c 0,45,46 + 344 429 344 429 312 429 c 0,47,48 + 281 429 281 429 253 416.5 c 128,-1,49 + 225 404 225 404 204 383 c 128,-1,50 + 183 362 183 362 170.5 334 c 128,-1,51 + 158 306 158 306 158 273 c 0,52,53 + 158 242 158 242 170.5 214 c 128,-1,54 + 183 186 183 186 204 165 c 128,-1,55 + 225 144 225 144 253 131.5 c 128,-1,56 + 281 119 281 119 312 119 c 0,36,37 +EndSplineSet +Validated: 1 +EndChar + +StartChar: p +Encoding: 112 112 15 +Width: 641 +Flags: W +LayerCount: 2 +Fore +SplineSet +322 428 m 0,0,1 + 291 428 291 428 262.5 415.5 c 128,-1,2 + 234 403 234 403 213 382 c 128,-1,3 + 192 361 192 361 180.5 333.5 c 128,-1,4 + 169 306 169 306 169 274 c 0,5,6 + 169 242 169 242 180.5 214.5 c 128,-1,7 + 192 187 192 187 213 166 c 128,-1,8 + 234 145 234 145 262.5 132.5 c 128,-1,9 + 291 120 291 120 322 120 c 0,10,11 + 354 120 354 120 382 132.5 c 128,-1,12 + 410 145 410 145 431 166 c 128,-1,13 + 452 187 452 187 464.5 214.5 c 128,-1,14 + 477 242 477 242 477 274 c 0,15,16 + 477 305 477 305 464.5 333 c 128,-1,17 + 452 361 452 361 431 382 c 128,-1,18 + 410 403 410 403 382 415.5 c 128,-1,19 + 354 428 354 428 322 428 c 0,0,1 +166 497 m 1,20,21 + 183 509 183 509 202 518 c 128,-1,22 + 221 527 221 527 241 534 c 128,-1,23 + 261 541 261 541 282 544.5 c 128,-1,24 + 303 548 303 548 322 548 c 0,25,26 + 350 548 350 548 376.5 542.5 c 128,-1,27 + 403 537 403 537 428 526.5 c 128,-1,28 + 453 516 453 516 475 500.5 c 128,-1,29 + 497 485 497 485 515.5 466.5 c 128,-1,30 + 534 448 534 448 549 426 c 128,-1,31 + 564 404 564 404 574.5 379.5 c 128,-1,32 + 585 355 585 355 591 328.5 c 128,-1,33 + 597 302 597 302 597 274 c 0,34,35 + 597 246 597 246 591 219 c 128,-1,36 + 585 192 585 192 574.5 168 c 128,-1,37 + 564 144 564 144 549 122 c 128,-1,38 + 534 100 534 100 515.5 81 c 128,-1,39 + 497 62 497 62 475 47 c 128,-1,40 + 453 32 453 32 428 21.5 c 128,-1,41 + 403 11 403 11 377 5.5 c 128,-1,42 + 351 0 351 0 322 0 c 0,43,44 + 302 0 302 0 281.5 3.5 c 128,-1,45 + 261 7 261 7 241 14 c 128,-1,46 + 221 21 221 21 202 30 c 128,-1,47 + 183 39 183 39 166 51 c 1,48,-1 + 166 -195 l 1,49,-1 + 46 -195 l 1,50,-1 + 46 546 l 1,51,-1 + 166 546 l 1,52,-1 + 166 497 l 1,20,21 +EndSplineSet +Validated: 1 +EndChar + +StartChar: q +Encoding: 113 113 16 +Width: 641 +Flags: W +LayerCount: 2 +Fore +SplineSet +313 428 m 0,0,1 + 281 428 281 428 253.5 415.5 c 128,-1,2 + 226 403 226 403 205 382 c 128,-1,3 + 184 361 184 361 171.5 333.5 c 128,-1,4 + 159 306 159 306 159 274 c 0,5,6 + 159 242 159 242 171.5 214.5 c 128,-1,7 + 184 187 184 187 205 166 c 128,-1,8 + 226 145 226 145 253.5 132.5 c 128,-1,9 + 281 120 281 120 313 120 c 0,10,11 + 344 120 344 120 372.5 132.5 c 128,-1,12 + 401 145 401 145 421.5 166 c 128,-1,13 + 442 187 442 187 454.5 214.5 c 128,-1,14 + 467 242 467 242 467 274 c 0,15,16 + 467 305 467 305 454.5 333 c 128,-1,17 + 442 361 442 361 421.5 382 c 128,-1,18 + 401 403 401 403 372.5 415.5 c 128,-1,19 + 344 428 344 428 313 428 c 0,0,1 +469 497 m 1,20,-1 + 469 546 l 1,21,-1 + 590 546 l 1,22,-1 + 590 -195 l 1,23,-1 + 469 -195 l 1,24,-1 + 469 51 l 1,25,26 + 452 39 452 39 433.5 30 c 128,-1,27 + 415 21 415 21 394.5 14 c 128,-1,28 + 374 7 374 7 353.5 3.5 c 128,-1,29 + 333 0 333 0 313 0 c 0,30,31 + 285 0 285 0 258 5.5 c 128,-1,32 + 231 11 231 11 207 21.5 c 128,-1,33 + 183 32 183 32 161 47 c 128,-1,34 + 139 62 139 62 120.5 81 c 128,-1,35 + 102 100 102 100 86.5 122 c 128,-1,36 + 71 144 71 144 61 168 c 128,-1,37 + 51 192 51 192 45 219 c 128,-1,38 + 39 246 39 246 39 274 c 0,39,40 + 39 301 39 301 45 328 c 128,-1,41 + 51 355 51 355 61 379.5 c 128,-1,42 + 71 404 71 404 86.5 426 c 128,-1,43 + 102 448 102 448 120.5 466.5 c 128,-1,44 + 139 485 139 485 161 500.5 c 128,-1,45 + 183 516 183 516 207 526.5 c 128,-1,46 + 231 537 231 537 258 542.5 c 128,-1,47 + 285 548 285 548 313 548 c 0,48,49 + 333 548 333 548 353.5 544.5 c 128,-1,50 + 374 541 374 541 394.5 534 c 128,-1,51 + 415 527 415 527 433.5 518 c 128,-1,52 + 452 509 452 509 469 497 c 1,20,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: r +Encoding: 114 114 17 +Width: 511 +Flags: W +LayerCount: 2 +Fore +SplineSet +407 399 m 1,0,1 + 388 411 388 411 366.5 418.5 c 128,-1,2 + 345 426 345 426 320 426 c 0,3,4 + 304 426 304 426 289 422 c 128,-1,5 + 274 418 274 418 260 411.5 c 128,-1,6 + 246 405 246 405 233.5 396.5 c 128,-1,7 + 221 388 221 388 210 376.5 c 128,-1,8 + 199 365 199 365 191 352.5 c 128,-1,9 + 183 340 183 340 177 326.5 c 128,-1,10 + 171 313 171 313 167.5 299.5 c 128,-1,11 + 164 286 164 286 164 271 c 2,12,-1 + 164 0 l 1,13,-1 + 46 0 l 1,14,-1 + 46 541 l 1,15,-1 + 164 541 l 1,16,-1 + 164 495 l 1,17,18 + 181 507 181 507 200 516 c 128,-1,19 + 219 525 219 525 239 532 c 128,-1,20 + 259 539 259 539 279.5 542.5 c 128,-1,21 + 300 546 300 546 320 546 c 0,22,23 + 363 546 363 546 402.5 533 c 128,-1,24 + 442 520 442 520 476 496 c 1,25,-1 + 407 399 l 1,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: t +Encoding: 116 116 18 +Width: 506 +Flags: W +LayerCount: 2 +Fore +SplineSet +162 275 m 2,0,1 + 163 244 163 244 175.5 216 c 128,-1,2 + 188 188 188 188 208.5 166.5 c 128,-1,3 + 229 145 229 145 257.5 132 c 128,-1,4 + 286 119 286 119 317 119 c 0,5,6 + 341 119 341 119 364 127 c 128,-1,7 + 387 135 387 135 405 147 c 1,8,-1 + 475 50 l 1,9,10 + 441 27 441 27 400.5 13.5 c 128,-1,11 + 360 0 360 0 317 0 c 0,12,13 + 289 0 289 0 262.5 5.5 c 128,-1,14 + 236 11 236 11 211.5 21.5 c 128,-1,15 + 187 32 187 32 165 47 c 128,-1,16 + 143 62 143 62 124 80.5 c 128,-1,17 + 105 99 105 99 90.5 121 c 128,-1,18 + 76 143 76 143 65.5 167.5 c 128,-1,19 + 55 192 55 192 49.5 219 c 128,-1,20 + 44 246 44 246 44 274 c 2,21,-1 + 44 745 l 1,22,-1 + 162 745 l 1,23,-1 + 162 546 l 1,24,-1 + 353 546 l 1,25,-1 + 353 428 l 1,26,-1 + 162 425 l 1,27,-1 + 162 275 l 2,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: u +Encoding: 117 117 19 +Width: 643 +Flags: W +LayerCount: 2 +Fore +SplineSet +44 274 m 2,0,-1 + 44 549 l 1,1,-1 + 164 549 l 1,2,-1 + 164 272 l 2,3,4 + 164 240 164 240 176 212.5 c 128,-1,5 + 188 185 188 185 209 164.5 c 128,-1,6 + 230 144 230 144 258 132 c 128,-1,7 + 286 120 286 120 318 120 c 0,8,9 + 334 120 334 120 349 124 c 128,-1,10 + 364 128 364 128 378.5 134.5 c 128,-1,11 + 393 141 393 141 405 149.5 c 128,-1,12 + 417 158 417 158 427.5 169.5 c 128,-1,13 + 438 181 438 181 447 193.5 c 128,-1,14 + 456 206 456 206 462 219 c 128,-1,15 + 468 232 468 232 471.5 246.5 c 128,-1,16 + 475 261 475 261 475 274 c 2,17,-1 + 475 546 l 1,18,-1 + 593 546 l 1,19,-1 + 593 5 l 1,20,-1 + 475 5 l 1,21,-1 + 475 51 l 1,22,23 + 457 39 457 39 438.5 30 c 128,-1,24 + 420 21 420 21 399.5 14 c 128,-1,25 + 379 7 379 7 358.5 3.5 c 128,-1,26 + 338 0 338 0 318 0 c 0,27,28 + 290 0 290 0 263 6 c 128,-1,29 + 236 12 236 12 212 22 c 128,-1,30 + 188 32 188 32 166 47 c 128,-1,31 + 144 62 144 62 125 81 c 128,-1,32 + 106 100 106 100 91 122 c 128,-1,33 + 76 144 76 144 66 168.5 c 128,-1,34 + 56 193 56 193 50 219.5 c 128,-1,35 + 44 246 44 246 44 274 c 2,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: v +Encoding: 118 118 20 +Width: 607 +Flags: W +LayerCount: 2 +Fore +SplineSet +361 0 m 1,0,-1 + 243 0 l 1,1,-1 + 31 547 l 1,2,-1 + 158 547 l 1,3,-1 + 303 158 l 1,4,-1 + 447 547 l 1,5,-1 + 574 547 l 1,6,-1 + 361 0 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: x +Encoding: 120 120 21 +Width: 699 +Flags: W +LayerCount: 2 +Fore +SplineSet +33 547 m 1,0,-1 + 186 547 l 1,1,-1 + 349 360 l 1,2,-1 + 512 547 l 1,3,-1 + 664 547 l 1,4,-1 + 426 273 l 1,5,-1 + 664 0 l 1,6,-1 + 511 0 l 1,7,-1 + 349 186 l 1,8,-1 + 187 0 l 1,9,-1 + 33 0 l 1,10,-1 + 272 273 l 1,11,-1 + 33 547 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: y +Encoding: 121 121 22 +Width: 642 +Flags: W +LayerCount: 2 +Fore +SplineSet +592 546 m 1,0,-1 + 592 72 l 2,1,2 + 592 44 592 44 586.5 18 c 128,-1,3 + 581 -8 581 -8 571 -32.5 c 128,-1,4 + 561 -57 561 -57 545.5 -79 c 128,-1,5 + 530 -101 530 -101 511.5 -119.5 c 128,-1,6 + 493 -138 493 -138 471 -153 c 128,-1,7 + 449 -168 449 -168 424.5 -178 c 128,-1,8 + 400 -188 400 -188 373.5 -194 c 128,-1,9 + 347 -200 347 -200 318 -200 c 0,10,11 + 272 -200 272 -200 230 -185 c 128,-1,12 + 188 -170 188 -170 152.5 -143.5 c 128,-1,13 + 117 -117 117 -117 91.5 -80 c 128,-1,14 + 66 -43 66 -43 55 0 c 1,15,-1 + 182 0 l 1,16,17 + 193 -18 193 -18 207 -33 c 128,-1,18 + 221 -48 221 -48 239 -58.5 c 128,-1,19 + 257 -69 257 -69 277 -75 c 128,-1,20 + 297 -81 297 -81 318 -81 c 0,21,22 + 346 -81 346 -81 372 -71 c 128,-1,23 + 398 -61 398 -61 418.5 -42.5 c 128,-1,24 + 439 -24 439 -24 453 -0.5 c 128,-1,25 + 467 23 467 23 471 51 c 1,26,27 + 453 40 453 40 435 30.5 c 128,-1,28 + 417 21 417 21 397.5 14.5 c 128,-1,29 + 378 8 378 8 358 4 c 128,-1,30 + 338 0 338 0 318 0 c 0,31,32 + 290 0 290 0 263.5 6 c 128,-1,33 + 237 12 237 12 212.5 22 c 128,-1,34 + 188 32 188 32 166 47 c 128,-1,35 + 144 62 144 62 125 81 c 128,-1,36 + 106 100 106 100 91 122 c 128,-1,37 + 76 144 76 144 66 168.5 c 128,-1,38 + 56 193 56 193 50 219.5 c 128,-1,39 + 44 246 44 246 44 274 c 2,40,-1 + 44 549 l 1,41,-1 + 164 549 l 1,42,-1 + 164 273 l 2,43,44 + 164 242 164 242 176 214.5 c 128,-1,45 + 188 187 188 187 209 166 c 128,-1,46 + 230 145 230 145 258 132.5 c 128,-1,47 + 286 120 286 120 318 120 c 0,48,49 + 349 120 349 120 377.5 132.5 c 128,-1,50 + 406 145 406 145 427 166 c 128,-1,51 + 448 187 448 187 461 214.5 c 128,-1,52 + 474 242 474 242 474 274 c 2,53,-1 + 474 546 l 1,54,-1 + 592 546 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: z +Encoding: 122 122 23 +Width: 632 +Flags: W +LayerCount: 2 +Fore +SplineSet +222 118 m 1,0,-1 + 587 118 l 1,1,-1 + 587 0 l 1,2,-1 + 43 0 l 1,3,-1 + 43 118 l 1,4,-1 + 401 430 l 1,5,-1 + 43 430 l 1,6,-1 + 43 548 l 1,7,-1 + 587 548 l 1,8,-1 + 587 430 l 1,9,-1 + 222 118 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: R +Encoding: 82 82 24 +Width: 593 +Flags: W +LayerCount: 2 +Fore +SplineSet +454 349 m 1,0,1 + 444 367 444 367 430 381 c 128,-1,2 + 416 395 416 395 398.5 405 c 128,-1,3 + 381 415 381 415 361.5 420.5 c 128,-1,4 + 342 426 342 426 320 426 c 0,5,6 + 304 426 304 426 289 422 c 128,-1,7 + 274 418 274 418 260 411.5 c 128,-1,8 + 246 405 246 405 233.5 396.5 c 128,-1,9 + 221 388 221 388 210 376.5 c 128,-1,10 + 199 365 199 365 191 352.5 c 128,-1,11 + 183 340 183 340 177 326.5 c 128,-1,12 + 171 313 171 313 167.5 299.5 c 128,-1,13 + 164 286 164 286 164 271 c 2,14,-1 + 164 0 l 1,15,-1 + 46 0 l 1,16,-1 + 46 541 l 1,17,-1 + 164 541 l 1,18,-1 + 164 495 l 1,19,20 + 181 507 181 507 200 516 c 128,-1,21 + 219 525 219 525 239 532 c 128,-1,22 + 259 539 259 539 279.5 542.5 c 128,-1,23 + 300 546 300 546 320 546 c 0,24,25 + 357 546 357 546 392.5 535.5 c 128,-1,26 + 428 525 428 525 458.5 507 c 128,-1,27 + 489 489 489 489 514.5 463.5 c 128,-1,28 + 540 438 540 438 558 407 c 1,29,-1 + 454 349 l 1,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: T +Encoding: 84 84 25 +Width: 586 +Flags: W +LayerCount: 2 +Fore +SplineSet +162 275 m 2,0,1 + 163 244 163 244 175.5 216 c 128,-1,2 + 188 188 188 188 208.5 166.5 c 128,-1,3 + 229 145 229 145 257.5 132 c 128,-1,4 + 286 119 286 119 317 119 c 0,5,6 + 338 119 338 119 358 124.5 c 128,-1,7 + 378 130 378 130 395 140 c 128,-1,8 + 412 150 412 150 426.5 165 c 128,-1,9 + 441 180 441 180 451 197 c 1,10,-1 + 554 137 l 1,11,12 + 536 106 536 106 510.5 80.5 c 128,-1,13 + 485 55 485 55 454.5 37.5 c 128,-1,14 + 424 20 424 20 389 10 c 128,-1,15 + 354 0 354 0 317 0 c 0,16,17 + 289 0 289 0 262.5 5.5 c 128,-1,18 + 236 11 236 11 211.5 21.5 c 128,-1,19 + 187 32 187 32 165 47 c 128,-1,20 + 143 62 143 62 124 80.5 c 128,-1,21 + 105 99 105 99 90.5 121 c 128,-1,22 + 76 143 76 143 65.5 167.5 c 128,-1,23 + 55 192 55 192 49.5 219 c 128,-1,24 + 44 246 44 246 44 274 c 2,25,-1 + 44 745 l 1,26,-1 + 162 745 l 1,27,-1 + 162 546 l 1,28,-1 + 353 546 l 1,29,-1 + 353 428 l 1,30,-1 + 162 425 l 1,31,-1 + 162 275 l 2,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: s +Encoding: 115 115 26 +Width: 539 +Flags: W +LayerCount: 2 +Fore +SplineSet +328 317 m 0,0,1 + 364 313 364 313 395.5 299 c 128,-1,2 + 427 285 427 285 449.5 264 c 128,-1,3 + 472 243 472 243 484.5 216.5 c 128,-1,4 + 497 190 497 190 497 162 c 0,5,6 + 497 144 497 144 492 128.5 c 128,-1,7 + 487 113 487 113 478.5 98.5 c 128,-1,8 + 470 84 470 84 457 71.5 c 128,-1,9 + 444 59 444 59 428.5 47.5 c 128,-1,10 + 413 36 413 36 394 27.5 c 128,-1,11 + 375 19 375 19 354.5 13 c 128,-1,12 + 334 7 334 7 311.5 3.5 c 128,-1,13 + 289 0 289 0 266 0 c 0,14,15 + 231 0 231 0 195.5 10 c 128,-1,16 + 160 20 160 20 130 36.5 c 128,-1,17 + 100 53 100 53 75.5 73.5 c 128,-1,18 + 51 94 51 94 36 114 c 1,19,-1 + 135 171 l 1,20,21 + 142 161 142 161 156 149.5 c 128,-1,22 + 170 138 170 138 187.5 127 c 128,-1,23 + 205 116 205 116 225 109 c 128,-1,24 + 245 102 245 102 264 102 c 0,25,26 + 284 102 284 102 303.5 106.5 c 128,-1,27 + 323 111 323 111 339 120 c 128,-1,28 + 355 129 355 129 365.5 140 c 128,-1,29 + 376 151 376 151 376 164 c 256,30,31 + 376 177 376 177 365.5 187 c 128,-1,32 + 355 197 355 197 334.5 205.5 c 128,-1,33 + 314 214 314 214 282.5 220.5 c 128,-1,34 + 251 227 251 227 206 231 c 0,35,36 + 170 235 170 235 139 249.5 c 128,-1,37 + 108 264 108 264 85.5 285 c 128,-1,38 + 63 306 63 306 50.5 332 c 128,-1,39 + 38 358 38 358 38 387 c 0,40,41 + 38 404 38 404 43 420 c 128,-1,42 + 48 436 48 436 56.5 450 c 128,-1,43 + 65 464 65 464 78 477 c 128,-1,44 + 91 490 91 490 107 501 c 128,-1,45 + 123 512 123 512 141.5 520.5 c 128,-1,46 + 160 529 160 529 180.5 535.5 c 128,-1,47 + 201 542 201 542 223.5 545 c 128,-1,48 + 246 548 246 548 270 548 c 0,49,50 + 289 548 289 548 306 545.5 c 128,-1,51 + 323 543 323 543 340.5 538.5 c 128,-1,52 + 358 534 358 534 375 527.5 c 128,-1,53 + 392 521 392 521 407.5 513.5 c 128,-1,54 + 423 506 423 506 437 497 c 128,-1,55 + 451 488 451 488 463.5 478 c 128,-1,56 + 476 468 476 468 485.5 457.5 c 128,-1,57 + 495 447 495 447 501 436 c 1,58,-1 + 402 380 l 1,59,60 + 395 389 395 389 381 400.5 c 128,-1,61 + 367 412 367 412 349 422.5 c 128,-1,62 + 331 433 331 433 311 440 c 128,-1,63 + 291 447 291 447 272 447 c 0,64,65 + 251 447 251 447 231.5 442.5 c 128,-1,66 + 212 438 212 438 196 429 c 128,-1,67 + 180 420 180 420 170 408.5 c 128,-1,68 + 160 397 160 397 160 385 c 256,69,70 + 160 372 160 372 170 362 c 128,-1,71 + 180 352 180 352 200 343.5 c 128,-1,72 + 220 335 220 335 252 329 c 128,-1,73 + 284 323 284 323 328 317 c 0,0,1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: exclam +Encoding: 33 33 27 +Width: 688 +Flags: W +LayerCount: 2 +Fore +SplineSet +250 547 m 1,0,-1 + 355 547 l 1,1,-1 + 355 450 l 1,2,-1 + 415 450 l 2,3,4 + 441 451 441 451 464.5 459 c 128,-1,5 + 488 467 488 467 505 480 c 128,-1,6 + 522 493 522 493 532 510 c 128,-1,7 + 542 527 542 527 542 547 c 1,8,-1 + 641 547 l 1,9,-1 + 641 0 l 1,10,-1 + 510 0 l 1,11,-1 + 510 356 l 1,12,-1 + 355 356 l 1,13,-1 + 355 0 l 1,14,-1 + 225 0 l 1,15,-1 + 225 356 l 1,16,-1 + 39 356 l 1,17,-1 + 39 450 l 1,18,-1 + 125 450 l 2,19,20 + 150 451 150 451 173 459.5 c 128,-1,21 + 196 468 196 468 213 481 c 128,-1,22 + 230 494 230 494 240 511 c 128,-1,23 + 250 528 250 528 250 547 c 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: f +Encoding: 102 102 28 +Width: 506 +Flags: W +LayerCount: 2 +Fore +SplineSet +164 471 m 1,0,-1 + 354 472 l 1,1,-1 + 354 353 l 1,2,-1 + 165 353 l 1,3,-1 + 164 0 l 1,4,-1 + 46 0 l 1,5,-1 + 46 471 l 2,6,7 + 46 499 46 499 51.5 526 c 128,-1,8 + 57 553 57 553 67.5 578 c 128,-1,9 + 78 603 78 603 92.5 624.5 c 128,-1,10 + 107 646 107 646 126 665 c 128,-1,11 + 145 684 145 684 166.5 698.5 c 128,-1,12 + 188 713 188 713 213 723.5 c 128,-1,13 + 238 734 238 734 264.5 739.5 c 128,-1,14 + 291 745 291 745 319 745 c 0,15,16 + 362 745 362 745 402 732 c 128,-1,17 + 442 719 442 719 477 695 c 1,18,-1 + 407 598 l 1,19,20 + 388 611 388 611 366 618.5 c 128,-1,21 + 344 626 344 626 319 626 c 0,22,23 + 288 626 288 626 259.5 613.5 c 128,-1,24 + 231 601 231 601 210 580 c 128,-1,25 + 189 559 189 559 176.5 530.5 c 128,-1,26 + 164 502 164 502 164 471 c 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: F +Encoding: 70 70 29 +Width: 585 +Flags: W +LayerCount: 2 +Fore +SplineSet +164 471 m 1,0,-1 + 354 472 l 1,1,-1 + 354 353 l 1,2,-1 + 165 353 l 1,3,-1 + 164 0 l 1,4,-1 + 46 0 l 1,5,-1 + 46 471 l 2,6,7 + 46 499 46 499 51.5 526 c 128,-1,8 + 57 553 57 553 67.5 578 c 128,-1,9 + 78 603 78 603 92.5 624.5 c 128,-1,10 + 107 646 107 646 126 665 c 128,-1,11 + 145 684 145 684 166.5 698.5 c 128,-1,12 + 188 713 188 713 213 723.5 c 128,-1,13 + 238 734 238 734 264.5 739.5 c 128,-1,14 + 291 745 291 745 319 745 c 0,15,16 + 356 745 356 745 391 735.5 c 128,-1,17 + 426 726 426 726 456.5 708 c 128,-1,18 + 487 690 487 690 512.5 665 c 128,-1,19 + 538 640 538 640 556 608 c 1,20,-1 + 453 548 l 1,21,22 + 443 566 443 566 428.5 580.5 c 128,-1,23 + 414 595 414 595 397 605 c 128,-1,24 + 380 615 380 615 360 620.5 c 128,-1,25 + 340 626 340 626 319 626 c 0,26,27 + 288 626 288 626 259.5 613.5 c 128,-1,28 + 231 601 231 601 210 580 c 128,-1,29 + 189 559 189 559 176.5 530.5 c 128,-1,30 + 164 502 164 502 164 471 c 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: j +Encoding: 106 106 30 +Width: 509 +Flags: W +LayerCount: 2 +Fore +SplineSet +399 744 m 0,0,1 + 411 744 411 744 422.5 739.5 c 128,-1,2 + 434 735 434 735 441.5 727 c 128,-1,3 + 449 719 449 719 454 708 c 128,-1,4 + 459 697 459 697 459 686 c 0,5,6 + 459 673 459 673 454 662 c 128,-1,7 + 449 651 449 651 441.5 643 c 128,-1,8 + 434 635 434 635 422.5 630.5 c 128,-1,9 + 411 626 411 626 399 626 c 0,10,11 + 386 626 386 626 375.5 630.5 c 128,-1,12 + 365 635 365 635 357.5 643 c 128,-1,13 + 350 651 350 651 345 662 c 128,-1,14 + 340 673 340 673 340 686 c 0,15,16 + 340 698 340 698 345 708.5 c 128,-1,17 + 350 719 350 719 357.5 727 c 128,-1,18 + 365 735 365 735 375.5 739.5 c 128,-1,19 + 386 744 386 744 399 744 c 0,0,1 +459 77 m 2,20,21 + 459 49 459 49 453 22.5 c 128,-1,22 + 447 -4 447 -4 437 -28.5 c 128,-1,23 + 427 -53 427 -53 411.5 -75 c 128,-1,24 + 396 -97 396 -97 377.5 -115.5 c 128,-1,25 + 359 -134 359 -134 337 -149 c 128,-1,26 + 315 -164 315 -164 291 -174.5 c 128,-1,27 + 267 -185 267 -185 240 -190.5 c 128,-1,28 + 213 -196 213 -196 185 -196 c 0,29,30 + 143 -196 143 -196 102.5 -183 c 128,-1,31 + 62 -170 62 -170 28 -146 c 1,32,-1 + 97 -48 l 1,33,34 + 117 -62 117 -62 139 -69.5 c 128,-1,35 + 161 -77 161 -77 185 -77 c 0,36,37 + 217 -77 217 -77 245 -64.5 c 128,-1,38 + 273 -52 273 -52 294 -30.5 c 128,-1,39 + 315 -9 315 -9 327.5 19 c 128,-1,40 + 340 47 340 47 340 79 c 2,41,-1 + 340 548 l 1,42,-1 + 459 548 l 1,43,-1 + 459 77 l 2,20,21 +EndSplineSet +Validated: 1 +EndChar + +StartChar: J +Encoding: 74 74 31 +Width: 588 +Flags: W +LayerCount: 2 +Fore +SplineSet +479 744 m 0,0,1 + 491 744 491 744 502 739.5 c 128,-1,2 + 513 735 513 735 521 727 c 128,-1,3 + 529 719 529 719 533.5 708 c 128,-1,4 + 538 697 538 697 538 686 c 0,5,6 + 538 673 538 673 533.5 662 c 128,-1,7 + 529 651 529 651 521 643 c 128,-1,8 + 513 635 513 635 502 630.5 c 128,-1,9 + 491 626 491 626 479 626 c 0,10,11 + 466 626 466 626 455.5 630.5 c 128,-1,12 + 445 635 445 635 437.5 643 c 128,-1,13 + 430 651 430 651 425 662 c 128,-1,14 + 420 673 420 673 420 686 c 0,15,16 + 420 698 420 698 425 708.5 c 128,-1,17 + 430 719 430 719 437.5 727 c 128,-1,18 + 445 735 445 735 455.5 739.5 c 128,-1,19 + 466 744 466 744 479 744 c 0,0,1 +538 78 m 2,20,21 + 538 50 538 50 532.5 23.5 c 128,-1,22 + 527 -3 527 -3 517 -28 c 128,-1,23 + 507 -53 507 -53 492 -75 c 128,-1,24 + 477 -97 477 -97 458 -115.5 c 128,-1,25 + 439 -134 439 -134 417.5 -149 c 128,-1,26 + 396 -164 396 -164 371.5 -174.5 c 128,-1,27 + 347 -185 347 -185 320 -190.5 c 128,-1,28 + 293 -196 293 -196 265 -196 c 0,29,30 + 229 -196 229 -196 194 -186.5 c 128,-1,31 + 159 -177 159 -177 128.5 -159 c 128,-1,32 + 98 -141 98 -141 72 -115.5 c 128,-1,33 + 46 -90 46 -90 28 -59 c 1,34,-1 + 131 0 l 1,35,36 + 142 -17 142 -17 156 -31 c 128,-1,37 + 170 -45 170 -45 187.5 -55 c 128,-1,38 + 205 -65 205 -65 224.5 -71 c 128,-1,39 + 244 -77 244 -77 265 -77 c 0,40,41 + 297 -77 297 -77 325.5 -64.5 c 128,-1,42 + 354 -52 354 -52 375 -30.5 c 128,-1,43 + 396 -9 396 -9 408 19 c 128,-1,44 + 420 47 420 47 420 79 c 2,45,-1 + 420 548 l 1,46,-1 + 538 548 l 1,47,-1 + 538 78 l 2,20,21 +EndSplineSet +Validated: 1 +EndChar + +StartChar: six +Encoding: 54 54 32 +Width: 624 +Flags: W +LayerCount: 2 +Fore +SplineSet +43 273 m 2,0,-1 + 43 476 l 2,1,2 + 43 504 43 504 48.5 531 c 128,-1,3 + 54 558 54 558 64.5 582 c 128,-1,4 + 75 606 75 606 89.5 628 c 128,-1,5 + 104 650 104 650 123 669 c 128,-1,6 + 142 688 142 688 164 702.5 c 128,-1,7 + 186 717 186 717 210.5 727.5 c 128,-1,8 + 235 738 235 738 261.5 743.5 c 128,-1,9 + 288 749 288 749 316 749 c 0,10,11 + 362 749 362 749 404.5 734.5 c 128,-1,12 + 447 720 447 720 482.5 693 c 128,-1,13 + 518 666 518 666 543 629.5 c 128,-1,14 + 568 593 568 593 580 549 c 1,15,-1 + 453 549 l 1,16,17 + 443 568 443 568 428.5 583 c 128,-1,18 + 414 598 414 598 396.5 608 c 128,-1,19 + 379 618 379 618 358.5 624 c 128,-1,20 + 338 630 338 630 317 630 c 0,21,22 + 288 630 288 630 262 619.5 c 128,-1,23 + 236 609 236 609 215.5 591.5 c 128,-1,24 + 195 574 195 574 182 549.5 c 128,-1,25 + 169 525 169 525 165 497 c 1,26,27 + 182 509 182 509 200.5 518 c 128,-1,28 + 219 527 219 527 238 534 c 128,-1,29 + 257 541 257 541 277 544.5 c 128,-1,30 + 297 548 297 548 317 548 c 0,31,32 + 344 548 344 548 371 542.5 c 128,-1,33 + 398 537 398 537 422.5 526.5 c 128,-1,34 + 447 516 447 516 469 501 c 128,-1,35 + 491 486 491 486 509.5 467 c 128,-1,36 + 528 448 528 448 543.5 426 c 128,-1,37 + 559 404 559 404 569.5 379.5 c 128,-1,38 + 580 355 580 355 585.5 328.5 c 128,-1,39 + 591 302 591 302 591 273 c 0,40,41 + 591 246 591 246 585.5 219 c 128,-1,42 + 580 192 580 192 570 168 c 128,-1,43 + 560 144 560 144 544.5 122 c 128,-1,44 + 529 100 529 100 510.5 81 c 128,-1,45 + 492 62 492 62 470 47 c 128,-1,46 + 448 32 448 32 423.5 21.5 c 128,-1,47 + 399 11 399 11 372.5 5.5 c 128,-1,48 + 346 0 346 0 317 0 c 256,49,50 + 289 0 289 0 262 5.5 c 128,-1,51 + 235 11 235 11 211 21.5 c 128,-1,52 + 187 32 187 32 165 47 c 128,-1,53 + 143 62 143 62 124 80.5 c 128,-1,54 + 105 99 105 99 90 121 c 128,-1,55 + 75 143 75 143 65 167.5 c 128,-1,56 + 55 192 55 192 49 218.5 c 128,-1,57 + 43 245 43 245 43 273 c 2,0,-1 +160 273 m 0,58,59 + 161 242 161 242 173.5 214 c 128,-1,60 + 186 186 186 186 207.5 165 c 128,-1,61 + 229 144 229 144 257 131.5 c 128,-1,62 + 285 119 285 119 317 119 c 256,63,64 + 349 119 349 119 377 131.5 c 128,-1,65 + 405 144 405 144 426 165.5 c 128,-1,66 + 447 187 447 187 459.5 215 c 128,-1,67 + 472 243 472 243 472 274 c 0,68,69 + 471 306 471 306 458.5 334 c 128,-1,70 + 446 362 446 362 425 382.5 c 128,-1,71 + 404 403 404 403 376.5 415.5 c 128,-1,72 + 349 428 349 428 317 428 c 0,73,74 + 285 428 285 428 257 415.5 c 128,-1,75 + 229 403 229 403 207.5 382 c 128,-1,76 + 186 361 186 361 173 333 c 128,-1,77 + 160 305 160 305 160 273 c 0,58,59 +EndSplineSet +Validated: 1 +EndChar + +StartChar: five +Encoding: 53 53 33 +Width: 588 +Flags: W +LayerCount: 2 +Fore +SplineSet +159 626 m 1,0,-1 + 159 521 l 1,1,2 + 187 535 187 535 216.5 541.5 c 128,-1,3 + 246 548 246 548 278 548 c 0,4,5 + 306 548 306 548 333 542 c 128,-1,6 + 360 536 360 536 384.5 526 c 128,-1,7 + 409 516 409 516 431 501 c 128,-1,8 + 453 486 453 486 471.5 467 c 128,-1,9 + 490 448 490 448 505.5 426.5 c 128,-1,10 + 521 405 521 405 531 380 c 128,-1,11 + 541 355 541 355 547 328.5 c 128,-1,12 + 553 302 553 302 553 273 c 256,13,14 + 553 245 553 245 547 218.5 c 128,-1,15 + 541 192 541 192 531 167.5 c 128,-1,16 + 521 143 521 143 505.5 121 c 128,-1,17 + 490 99 490 99 471.5 80.5 c 128,-1,18 + 453 62 453 62 431 47 c 128,-1,19 + 409 32 409 32 384.5 21.5 c 128,-1,20 + 360 11 360 11 333.5 5.5 c 128,-1,21 + 307 0 307 0 278 0 c 0,22,23 + 242 0 242 0 207.5 10 c 128,-1,24 + 173 20 173 20 142 37.5 c 128,-1,25 + 111 55 111 55 85.5 80 c 128,-1,26 + 60 105 60 105 42 137 c 1,27,-1 + 145 197 l 1,28,29 + 156 179 156 179 170 164.5 c 128,-1,30 + 184 150 184 150 201.5 140 c 128,-1,31 + 219 130 219 130 238.5 124.5 c 128,-1,32 + 258 119 258 119 278 119 c 0,33,34 + 310 119 310 119 338.5 131.5 c 128,-1,35 + 367 144 367 144 388 165 c 128,-1,36 + 409 186 409 186 421.5 214 c 128,-1,37 + 434 242 434 242 434 273 c 0,38,39 + 434 305 434 305 421.5 333.5 c 128,-1,40 + 409 362 409 362 388 383 c 128,-1,41 + 367 404 367 404 339 416 c 128,-1,42 + 311 428 311 428 278 428 c 0,43,44 + 257 428 257 428 240 426 c 128,-1,45 + 223 424 223 424 208 417.5 c 128,-1,46 + 193 411 193 411 181 400 c 128,-1,47 + 169 389 169 389 159 371 c 1,48,-1 + 41 412 l 1,49,-1 + 42 744 l 1,50,-1 + 552 744 l 1,51,-1 + 552 626 l 1,52,-1 + 159 626 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: nine +Encoding: 57 57 34 +Width: 625 +Flags: W +LayerCount: 2 +Fore +SplineSet +585 476 m 2,0,-1 + 586 273 l 2,1,2 + 586 245 586 245 580 218 c 128,-1,3 + 574 191 574 191 564 167 c 128,-1,4 + 554 143 554 143 538.5 121 c 128,-1,5 + 523 99 523 99 504.5 80.5 c 128,-1,6 + 486 62 486 62 464 47 c 128,-1,7 + 442 32 442 32 418 21.5 c 128,-1,8 + 394 11 394 11 367 5.5 c 128,-1,9 + 340 0 340 0 312 0 c 0,10,11 + 266 0 266 0 223.5 15 c 128,-1,12 + 181 30 181 30 146 56.5 c 128,-1,13 + 111 83 111 83 85.5 119.5 c 128,-1,14 + 60 156 60 156 48 200 c 1,15,-1 + 175 200 l 1,16,17 + 186 181 186 181 200.5 166 c 128,-1,18 + 215 151 215 151 232.5 141 c 128,-1,19 + 250 131 250 131 270 125 c 128,-1,20 + 290 119 290 119 312 119 c 0,21,22 + 340 119 340 119 366 129.5 c 128,-1,23 + 392 140 392 140 412.5 157.5 c 128,-1,24 + 433 175 433 175 446.5 199.5 c 128,-1,25 + 460 224 460 224 464 252 c 1,26,27 + 446 240 446 240 428 231 c 128,-1,28 + 410 222 410 222 390.5 215 c 128,-1,29 + 371 208 371 208 351.5 204.5 c 128,-1,30 + 332 201 332 201 312 201 c 0,31,32 + 284 201 284 201 257 206.5 c 128,-1,33 + 230 212 230 212 205.5 222.5 c 128,-1,34 + 181 233 181 233 159 248.5 c 128,-1,35 + 137 264 137 264 118.5 282.5 c 128,-1,36 + 100 301 100 301 84.5 323 c 128,-1,37 + 69 345 69 345 59 369.5 c 128,-1,38 + 49 394 49 394 43 420.5 c 128,-1,39 + 37 447 37 447 37 476 c 256,40,41 + 37 504 37 504 42.5 530.5 c 128,-1,42 + 48 557 48 557 58.5 581.5 c 128,-1,43 + 69 606 69 606 84 627.5 c 128,-1,44 + 99 649 99 649 118 668.5 c 128,-1,45 + 137 688 137 688 159 702.5 c 128,-1,46 + 181 717 181 717 205 727.5 c 128,-1,47 + 229 738 229 738 256 743.5 c 128,-1,48 + 283 749 283 749 312 749 c 256,49,50 + 340 749 340 749 366.5 743.5 c 128,-1,51 + 393 738 393 738 417.5 727.5 c 128,-1,52 + 442 717 442 717 464 702.5 c 128,-1,53 + 486 688 486 688 504.5 669 c 128,-1,54 + 523 650 523 650 538 628 c 128,-1,55 + 553 606 553 606 563.5 582 c 128,-1,56 + 574 558 574 558 579.5 531 c 128,-1,57 + 585 504 585 504 585 476 c 2,0,-1 +468 476 m 0,58,59 + 468 507 468 507 455 535 c 128,-1,60 + 442 563 442 563 420.5 584 c 128,-1,61 + 399 605 399 605 371 617.5 c 128,-1,62 + 343 630 343 630 312 630 c 0,63,64 + 280 630 280 630 251.5 617.5 c 128,-1,65 + 223 605 223 605 202 583.5 c 128,-1,66 + 181 562 181 562 169 534.5 c 128,-1,67 + 157 507 157 507 157 475 c 0,68,69 + 157 444 157 444 169.5 415.5 c 128,-1,70 + 182 387 182 387 203 366.5 c 128,-1,71 + 224 346 224 346 251.5 333.5 c 128,-1,72 + 279 321 279 321 312 321 c 256,73,74 + 344 321 344 321 372 333.5 c 128,-1,75 + 400 346 400 346 421.5 367 c 128,-1,76 + 443 388 443 388 455.5 416 c 128,-1,77 + 468 444 468 444 468 476 c 0,58,59 +EndSplineSet +Validated: 1 +EndChar + +StartChar: one +Encoding: 49 49 35 +Width: 311 +Flags: W +LayerCount: 2 +Fore +SplineSet +263 0 m 1,0,-1 + 132 0 l 1,1,-1 + 132 554 l 1,2,-1 + 34 554 l 1,3,-1 + 32 648 l 1,4,5 + 58 649 58 649 81 657 c 128,-1,6 + 104 665 104 665 121 678.5 c 128,-1,7 + 138 692 138 692 147.5 709.5 c 128,-1,8 + 157 727 157 727 157 744 c 1,9,-1 + 263 744 l 1,10,-1 + 263 0 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: copyright +Encoding: 169 169 36 +Width: 821 +Flags: W +LayerCount: 2 +Fore +SplineSet +411 0 m 256,0,1 + 373 0 373 0 336.5 8 c 128,-1,2 + 300 16 300 16 266.5 30 c 128,-1,3 + 233 44 233 44 203.5 64 c 128,-1,4 + 174 84 174 84 148.5 109.5 c 128,-1,5 + 123 135 123 135 103 164.5 c 128,-1,6 + 83 194 83 194 69 227.5 c 128,-1,7 + 55 261 55 261 47 297.5 c 128,-1,8 + 39 334 39 334 39 372 c 0,9,10 + 39 411 39 411 47 447 c 128,-1,11 + 55 483 55 483 69 517 c 128,-1,12 + 83 551 83 551 103 580.5 c 128,-1,13 + 123 610 123 610 148.5 635 c 128,-1,14 + 174 660 174 660 203.5 680.5 c 128,-1,15 + 233 701 233 701 266.5 715 c 128,-1,16 + 300 729 300 729 336.5 736.5 c 128,-1,17 + 373 744 373 744 411 744 c 256,18,19 + 449 744 449 744 485.5 736.5 c 128,-1,20 + 522 729 522 729 555.5 715 c 128,-1,21 + 589 701 589 701 618.5 680.5 c 128,-1,22 + 648 660 648 660 673.5 635 c 128,-1,23 + 699 610 699 610 719 580.5 c 128,-1,24 + 739 551 739 551 753.5 517 c 128,-1,25 + 768 483 768 483 775.5 447 c 128,-1,26 + 783 411 783 411 783 372 c 0,27,28 + 783 334 783 334 775.5 297.5 c 128,-1,29 + 768 261 768 261 753.5 227.5 c 128,-1,30 + 739 194 739 194 719 164.5 c 128,-1,31 + 699 135 699 135 673.5 109.5 c 128,-1,32 + 648 84 648 84 618.5 64 c 128,-1,33 + 589 44 589 44 555.5 30 c 128,-1,34 + 522 16 522 16 485.5 8 c 128,-1,35 + 449 0 449 0 411 0 c 256,0,1 +411 93 m 0,36,37 + 440 93 440 93 467 98.5 c 128,-1,38 + 494 104 494 104 519.5 115 c 128,-1,39 + 545 126 545 126 567.5 141 c 128,-1,40 + 590 156 590 156 608.5 175 c 128,-1,41 + 627 194 627 194 642 216.5 c 128,-1,42 + 657 239 657 239 668 264 c 128,-1,43 + 679 289 679 289 684.5 316.5 c 128,-1,44 + 690 344 690 344 690 372 c 0,45,46 + 690 401 690 401 684.5 428.5 c 128,-1,47 + 679 456 679 456 668 481 c 128,-1,48 + 657 506 657 506 642 528.5 c 128,-1,49 + 627 551 627 551 608.5 569.5 c 128,-1,50 + 590 588 590 588 567.5 603 c 128,-1,51 + 545 618 545 618 519.5 629 c 128,-1,52 + 494 640 494 640 467 645.5 c 128,-1,53 + 440 651 440 651 411 651 c 0,54,55 + 383 651 383 651 355.5 645.5 c 128,-1,56 + 328 640 328 640 302.5 629 c 128,-1,57 + 277 618 277 618 255 603 c 128,-1,58 + 233 588 233 588 214 569.5 c 128,-1,59 + 195 551 195 551 180 528.5 c 128,-1,60 + 165 506 165 506 154.5 481 c 128,-1,61 + 144 456 144 456 138 428.5 c 128,-1,62 + 132 401 132 401 132 372 c 0,63,64 + 132 344 132 344 138 316.5 c 128,-1,65 + 144 289 144 289 154.5 264 c 128,-1,66 + 165 239 165 239 180 216.5 c 128,-1,67 + 195 194 195 194 214 175 c 128,-1,68 + 233 156 233 156 255 141 c 128,-1,69 + 277 126 277 126 302.5 115 c 128,-1,70 + 328 104 328 104 355.5 98.5 c 128,-1,71 + 383 93 383 93 411 93 c 0,36,37 +593 478 m 1,72,-1 + 513 432 l 1,73,74 + 505 445 505 445 494 456 c 128,-1,75 + 483 467 483 467 470 474.5 c 128,-1,76 + 457 482 457 482 442 486 c 128,-1,77 + 427 490 427 490 411 490 c 0,78,79 + 387 490 387 490 365 481 c 128,-1,80 + 343 472 343 472 327 455.5 c 128,-1,81 + 311 439 311 439 301.5 417.5 c 128,-1,82 + 292 396 292 396 292 372 c 256,83,84 + 292 348 292 348 301.5 326.5 c 128,-1,85 + 311 305 311 305 327 288.5 c 128,-1,86 + 343 272 343 272 365 262.5 c 128,-1,87 + 387 253 387 253 411 253 c 0,88,89 + 427 253 427 253 442 257.5 c 128,-1,90 + 457 262 457 262 470 269.5 c 128,-1,91 + 483 277 483 277 494.5 288.5 c 128,-1,92 + 506 300 506 300 514 313 c 1,93,-1 + 592 268 l 1,94,95 + 578 244 578 244 558.5 224 c 128,-1,96 + 539 204 539 204 515.5 190.5 c 128,-1,97 + 492 177 492 177 465 169.5 c 128,-1,98 + 438 162 438 162 411 162 c 0,99,100 + 390 162 390 162 369.5 166.5 c 128,-1,101 + 349 171 349 171 330 179 c 128,-1,102 + 311 187 311 187 294 198.5 c 128,-1,103 + 277 210 277 210 262.5 224 c 128,-1,104 + 248 238 248 238 237 254.5 c 128,-1,105 + 226 271 226 271 218 290.5 c 128,-1,106 + 210 310 210 310 205.5 330.5 c 128,-1,107 + 201 351 201 351 201 372 c 256,108,109 + 201 393 201 393 205.5 414 c 128,-1,110 + 210 435 210 435 218 454 c 128,-1,111 + 226 473 226 473 237 489.5 c 128,-1,112 + 248 506 248 506 262.5 520 c 128,-1,113 + 277 534 277 534 294 546 c 128,-1,114 + 311 558 311 558 330 565.5 c 128,-1,115 + 349 573 349 573 369.5 577.5 c 128,-1,116 + 390 582 390 582 411 582 c 0,117,118 + 438 582 438 582 465 574.5 c 128,-1,119 + 492 567 492 567 515.5 553.5 c 128,-1,120 + 539 540 539 540 559 520.5 c 128,-1,121 + 579 501 579 501 593 478 c 1,72,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: two +Encoding: 50 50 37 +Width: 595 +Flags: W +LayerCount: 2 +Fore +SplineSet +248 118 m 1,0,-1 + 551 118 l 1,1,-1 + 551 0 l 1,2,-1 + 41 0 l 1,3,-1 + 40 116 l 1,4,-1 + 367 346 l 2,5,6 + 382 357 382 357 393.5 370 c 128,-1,7 + 405 383 405 383 414 399 c 128,-1,8 + 423 415 423 415 428 433 c 128,-1,9 + 433 451 433 451 433 471 c 0,10,11 + 433 503 433 503 420.5 531 c 128,-1,12 + 408 559 408 559 387 580 c 128,-1,13 + 366 601 366 601 338 613 c 128,-1,14 + 310 625 310 625 277 625 c 0,15,16 + 256 625 256 625 237 619.5 c 128,-1,17 + 218 614 218 614 200.5 604 c 128,-1,18 + 183 594 183 594 168.5 579.5 c 128,-1,19 + 154 565 154 565 144 548 c 1,20,-1 + 41 607 l 1,21,22 + 59 638 59 638 84.5 663.5 c 128,-1,23 + 110 689 110 689 141 707.5 c 128,-1,24 + 172 726 172 726 206.5 735 c 128,-1,25 + 241 744 241 744 277 744 c 0,26,27 + 305 744 305 744 332 738.5 c 128,-1,28 + 359 733 359 733 383.5 723 c 128,-1,29 + 408 713 408 713 430 698 c 128,-1,30 + 452 683 452 683 470.5 664.5 c 128,-1,31 + 489 646 489 646 504.5 624 c 128,-1,32 + 520 602 520 602 530 577.5 c 128,-1,33 + 540 553 540 553 546 526 c 128,-1,34 + 552 499 552 499 552 471 c 0,35,36 + 552 436 552 436 543 403.5 c 128,-1,37 + 534 371 534 371 518.5 342 c 128,-1,38 + 503 313 503 313 481.5 289 c 128,-1,39 + 460 265 460 265 433 246 c 2,40,-1 + 248 118 l 1,0,-1 +EndSplineSet +Validated: 1 +EndChar + +StartChar: w +Encoding: 119 119 38 +Width: 1070 +Flags: W +LayerCount: 2 +Fore +SplineSet +532 103 m 1,0,1 + 448 0 448 0 318 0 c 0,2,3 + 204 0 204 0 124 80 c 128,-1,4 + 44 160 44 160 44 274 c 2,5,-1 + 44 548 l 1,6,-1 + 164 548 l 1,7,-1 + 164 272 l 2,8,9 + 164 208 164 208 209 164 c 128,-1,10 + 254 120 254 120 318 120 c 0,11,12 + 380 120 380 120 427.5 169.5 c 128,-1,13 + 475 219 475 219 475 274 c 2,14,-1 + 474 548 l 1,15,-1 + 591 548 l 1,16,-1 + 591 274 l 2,17,18 + 591 218 591 218 637 169 c 128,-1,19 + 683 120 683 120 746 120 c 256,20,21 + 809 120 809 120 854 164 c 128,-1,22 + 899 208 899 208 900 272 c 2,23,-1 + 900 548 l 1,24,-1 + 1021 548 l 1,25,-1 + 1021 274 l 2,26,27 + 1021 160 1021 160 940 80 c 128,-1,28 + 859 0 859 0 746 0 c 0,29,30 + 615 0 615 0 532 103 c 1,0,1 +EndSplineSet +Validated: 1 +EndChar +EndChars +EndSplineFont diff --git a/fonts/Handbook/README.md b/fonts/Handbook/README.md new file mode 100644 index 0000000..5010dca --- /dev/null +++ b/fonts/Handbook/README.md @@ -0,0 +1,12 @@ +# DEC Handbook font + +This is a reconstruction of the font used on DEC processor handbook +covers and other manuals in the early 1970s. Some characters did not +appear in the originals (like "x") so they are made up in the style of +the others. + +This is a lower case only font. A few letters have alternate shapes, +with short and long curving parts. The long curve shapes are the +lower case letters; these are suitable for the end of a word (f r t) +and the start (j). The corresponding upper case letters are for use +in the middle of a word. diff --git a/fonts/README.md b/fonts/README.md new file mode 100644 index 0000000..f4df57e --- /dev/null +++ b/fonts/README.md @@ -0,0 +1,6 @@ +# DEC related fonts + +This subtree contains various fonts reconstructed from DEC documents. + +* Handbook -- the font used on DEC processor handbooks and manuals in +the earli 1970s, such as the PDP-11/20 processor handbook. diff --git a/teco/README.md b/teco/README.md new file mode 100644 index 0000000..46d5eda --- /dev/null +++ b/teco/README.md @@ -0,0 +1,14 @@ +# TECO in Python + +This is an implementation of TECO in Python 3. I originally wrote it +as a programming language learning exercise, so it's not really +polished, but it is functional. Since it uses Python 3, it has the +rather unusual property of supporting Unicode directly. + +Contents: +* teco.py -- the program. It supports a "GT40" style via wxPython, if +installed. "Curses" support (for ANSI terminals) is not yet +operational. +* bmp.tec -- a sample TECO macro showing Unicode support. It fills +the buffer with all the characters of the Unicode Basic Multinational +Plane. diff --git a/teco/bmp.tec b/teco/bmp.tec new file mode 100644 index 0000000..34437ae --- /dev/null +++ b/teco/bmp.tec @@ -0,0 +1,4 @@ +^d 16^r 0ua 10000/20 qbr @i/: / + 20@i/ +/> w + diff --git a/teco/teco.py b/teco/teco.py new file mode 100755 index 0000000..3807353 --- /dev/null +++ b/teco/teco.py @@ -0,0 +1,3400 @@ +#!/usr/bin/env python3 + +"""TECO for Python + +Copyright (C) 2006, 2014 by Paul Koning + +This is an implementation of DEC Standard TECO in Python. +It corresponds to PDP-11/VAX TECO V40, give or take a few details +that don't really carry over. +""" + +import os +import sys +import re +import time +import traceback +import glob +import warnings +import copy +import atexit +import threading +import tempfile + +try: + import curses + curses.initscr () + curses.endwin () + curses.def_shell_mode () + cursespresent = True +except ImportError: + cursespresent = False + +try: + import wx + wxpresent = True +except ImportError: + wxpresent = False + +# char codes +null = '\000' +ctrlc = '\003' +ctrle = '\005' +bs = '\010' +bell = '\007' +tab = '\011' +lf = '\012' +vt = '\013' +ff = '\014' +cr = '\015' +crlf = cr + lf +ctrls = '\023' +ctrlu = '\025' +ctrlx = '\030' +esc = '\033' +rub = '\177' +eol = lf + vt + ff # all these are TECO end of line (TODO) + +# global variables +screen = None +display = None +dsem = None +exiting = False + +# Other useful constants +VERSION = 40 + +# There is no good match for the CPU and OS types. Based on the +# features, PDP-11 makes sense, since this TECO looks like TECO-11. +# The implementation of ^B says we'd like to call it RSX/VMS, but +# that won't work because various code (like TECO.TEC) will use that +# as a hint to construct filenames with RMS format switches in them, +# and those look like Unix directory names, so all hell will break +# loose. The best answer, therefore, is to call it RT-11, which +# has neither directories nor file version numbers nor filename +# switches. RSX/VMS has all of those, and RSTS/E has all except +# versions -- but any of those would give Unix filename handlers +# conniption fits... +CPU = 0 # Pretend to be a PDP-11, that's closest +OS = 7 # OS is Unix, but pretend it's RT-11 + +# unbuffered input: Python Cookbook V2 section 2.23 +try: + from msvcrt import getch + rubchr = '\010' +except ImportError: + rubchr = '\177' + def getch (): + """Get a character in raw (unechoed, single character) mode. + """ + import tty, termios + fd = sys.stdin.fileno () + old_settings = termios.tcgetattr (fd) + try: + tty.setraw (fd) + ch = sys.stdin.read (1) + finally: + termios.tcsetattr (fd, termios.TCSADRAIN, old_settings) + return ch + +# Enhanced traceback, from Python Cookbook section 8.6, slightly tweaked +maxstrlen = 200 +def print_exc_plus (): + '''Print all the usual traceback information, followed by a listing of + all the local variables in each frame. + + Variable values are truncated to 200 characters max for readability, + and converted to printable characters in standard TECO fashion. + ''' + tb = sys.exc_info ()[2] + while tb.tb_next: + tb = tb.tb_next + stack = [ ] + f = tb.tb_frame + while f: + stack.append (f) + f = f.f_back + stack.reverse () + endwin () + traceback.print_exc () + print("Locals by frame, innermost last") + if stack[0].f_code.co_name == "?": + del stack[0] + for frame in stack: + print() + print("Frame %s in %s at line %s" % (frame.f_code.co_name, + frame.f_code.co_filename, + frame.f_lineno)) + for key, value in list(frame.f_locals.items ()): + print("\t%20s = " % key, end=' ') + try: + value = printable (str (value)) + if len (value) > maxstrlen: + value = value[:maxstrlen] + "..." + print(value) + except: + print("") + +# Transform a generic binary string to a printable one. Try to +# optimize this because sometimes it is fed big strings. +# tab through cr are printed as is; other control chars are uparrowed +# except for esc of course. +# Taken from Python Cookbook, section 1.18 +_printre = re.compile ("[\000-\007\016-\037\177]") +_printdict = { } +for c in range (0o40): + _printdict[chr (c)] = '^' + chr (c + 64) +_printdict[esc] = '$' +_printdict[rub] = "^?" + +def _makeprintable (m): + return _printdict[m.group (0)] + +def printable(s): + """Convert the supplied string to a printable string, + by converting all unusual control characters to uparrow + form, and escape to $ sign. + """ + return _printre.sub (_makeprintable, s) + +# Error handling +class err (Exception): + '''Base class for TECO errors. + + Specific errors are derived from this class; the class name is + the three-letter code for the error, and the class doc string + is the event message string. + ''' + def __init__ (self, teco, *a): + self.teco = teco + self.args = tuple (printable (arg) for arg in a) + teco.clearargs () + + def show (self): + endwin () + detail = self.teco.eh & 3 + if detail == 1: + print("?%s" % self.__class__.__name__) + else: + if self.args: + msg = self.__class__.__doc__ % self.args + else: + msg = self.__class__.__doc__ + print("?%s %s" % (self.__class__.__name__, msg)) + if self.teco.eh & 4: + print(printable (self.teco.failedcommand ()), "?") + +class ARG (err): 'Improper Arguments' +class BNI (err): '> not in iteration' +class FER (err): 'File Error' +class FNF (err): 'File not found "%s"' +class ICE (err): 'Illegal ^E Command in Search Argument' +class IEC (err): 'Illegal character "%s" after E' +class IFC (err): 'Illegal character "%s" after F' +class IFN (err): 'Illegal character "%s" in filename' +class IIA (err): 'Illegal insert arg' +class ILL (err): 'Illegal command "%s"' +class ILN (err): 'Illegal number' +class INP (err): 'Input error' +class IPA (err): 'Negative or 0 argument to P' +class IQC (err): 'Illegal " character' +class IQN (err): 'Illegal Q-register name "%s"' +class IRA (err): 'Illegal radix argument to ^R' +class ISA (err): 'Illegal search arg' +class ISS (err): 'Illegal search string' +class IUC (err): 'Illegal character "%s" following ^' +class MAP (err): "Missing '" +class MLA (err): 'Missing Left Angle Bracket' +class MLP (err): 'Missing (' +class MRA (err): 'Missing Right Angle Bracket' +class MRP (err): 'Missing )' +class NAB (err): 'No arg before ^_' +class NAC (err): 'No arg before ,' +class NAE (err): 'No arg before =' +class NAP (err): 'No arg before )' +class NAQ (err): 'No arg before "' +class NAS (err): 'No arg before ;' +class NAU (err): 'No arg before U' +class NCA (err): 'Negative argument to ,' +class NFI (err): 'No file for input' +class NFO (err): 'No file for output' +class NPA (err): 'Negative or 0 argument to P' +class NYA (err): 'Numeric argument with Y' +class NYI (err): 'Not Yet Implemented' +class OFO (err): 'Output file already open' +class OUT (err): 'Output error' +class PES (err): 'Attempt to Pop Empty Stack' +class POP (err): 'Attempt to move Pointer Off Page with "%s"' +class SNI (err): '; not in iteration' +class SRH (err): 'Search failure "%s"' +class TAG (err): 'Missing Tag !%s!' +class UTC (err): 'Unterminated command "%s"' +class UTM (err): 'Unterminated macro' +class XAB (err): 'Execution aborted' +class YCA (err): 'Y command aborted' + +# Other exceptions used for misc purposes +class ExitLevel (Exception): pass +class ExitExecution (Exception): pass + +# text reformatting for screen display +tabre = re.compile (tab) +_tabadjust = 0 +def _untabify (m): + global _curcol, _tabadjust + pos = m.start () + _tabadjust + count = 8 - (pos & 7) + if _curcol > pos: + _curcol += count - 1 + _tabadjust += count - 1 + return " " * count + +def untabify (line, curpos, width): + """Convert tabs to spaces, and wrap the line as needed into chunks + of the specified width. Returns the list of chunks, and the row + and column corresponding to the supplied curpos. There is always + at least one chunk, which may have an empty string if the supplied + line was empty. + + Each chunk is a pair of text and wrap flag. Wrap flag is True + if this chunk of text is wrapped, i.e., it does not end with a + carriage return, and False if it is the end of the line. + + Note that a trailing cr and/or lf is stripped from the input line. + """ + global _curcol, _tabadjust + _curcol = curpos + _tabadjust = 0 + line = tabre.sub (_untabify, printable (line.rstrip (crlf))) + currow = 0 + if True: # todo: truncate vs. wrap mode + lines = [ ] + while len (line) > width: + lines.append ((line[:width], True)) + line = line[width:] + if _curcol > width: + currow += 1 + _curcol -= width + lines.append ((line, False)) + return lines, currow, _curcol + +# Property makers +def commonprop (name, doc=None): + """Define a property that references an attribute of 'teco' + (the common state object for TECO). + """ + def _fget (obj): + return getattr (obj.teco, name) + def _fset (obj, val): + return setattr (obj.teco, name, val) + _fget.__name__ = "get_%s" % name + _fset.__name__ = "set_%s" % name + return property (_fget, _fset, doc=doc) + +def bufprop (name, doc=None): + """Define a property that references an attribute of 'buffer' + (the text buffer object for TECO). + """ + def _fget (obj): + return getattr (obj.buffer, name) + def _fset (obj, val): + return setattr (obj.buffer, name, val) + _fget.__name__ = "get_%s" % name + _fset.__name__ = "set_%s" % name + return property (_fget, _fset, doc=doc) + +# Global state handling +class teco (object): + '''This class defines the global state for TECO, i.e., the state + that is independent of the macro level. It also points to state + that is kept in separate classes, such as the buffer, the command + input, and the command level for the interactive level. + ''' + def __init__(self): + self.radix = 10 + self.ed = 0 + self.eh = 0 + self.es = 0 + if wxpresent: + self.etfixed = 1024 # Display available + elif cursespresent: + self.etfixed = 512 # text terminal "watch" available + else: + self.etfixed = 0 # neither available + self.et = 128 + self.etfixed + self.eu = -1 + self.ev = 0 + setattr (self, ctrlx, 0) # ^X flag + self.trace = False + self.laststringlen = 0 + self.qregs = { } + self.lastsearch = "" + self.lastfilename = "" + self.qstack = [ ] + self.clearargs () + self.interactive = command_level (self) + self.buffer = buffer (self) + self.cmdhandler = command_handler (self) + self.screenok = False + self.incurses = False + self.watchparams = [ 8, 80, 24, 0, 0, 0, 0, 0 ] + self.curline = 16 + + buf = bufprop ("text") + dot = bufprop ("dot") + end = bufprop ("end") + + def doop (self, c): + """Process a pending arithmetic operation, if any. + self.arg is left with the current term value. + """ + if self.op: + if self.op in '+-' and self.arg is None: + self.arg = 0 + if self.num is None: + raise ILL (self, c) + if self.op == '+': + self.arg += self.num + elif self.op == '-': + self.arg -= self.num + elif self.op == '*': + self.arg *= self.num + elif self.op == '/': + if not self.num: + raise ILL (self, '/') + self.arg //= self.num + elif self.op == '&': + self.arg &= self.num + elif self.op == '#': + self.arg |= self.num + else: + self.arg = self.num + + def getterm (self, c): + """Get the current term, i.e., the innermost expression + part in parentheses. + """ + self.doop (c) + ret = self.arg + self.num = None + self.op = None + self.arg = None + return ret + + def leftparen (self): + """Proces a left parenthesis command, by pushing the current + partial expression state onto the operation stack. + """ + self.opstack.append ((self.arg, self.op)) + self.arg = None + self.op = None + + def rightparen (self): + """Process a right parenthesis command, by setting the current + right-hand side to the expression term value, and popping the + operation stack state for the left hand and operation (if any). + """ + if self.opstack: + try: + self.num = self.getterm (')') + except err: + raise NAP (self) + self.arg, self.op = self.opstack.pop () + else: + raise MLP (self) + + def operator (self, c): + """Process an arithmetic operation character. + """ + if self.num is None: + if c in "+-" and self.arg is None: + self.op = c + return + else: + raise ILL (self, c) + self.doop (c) + self.num = None + self.op = c + + def digit (self, c): + """Process a decimal digit. 8 and 9 generate an error if + the current radix is octal. + """ + if self.num is None: + self.num = 0 + n = int (c) + if n >= self.radix: + raise ILN (self) + self.num = self.num * self.radix + n + + def getarg (self, c): + """Get a complete argument, or None if there isn't one. + If there are left parentheses that have not yet been matched, + that is an error. + or - alone are taken to be +1 and -1 + respectively. + """ + if self.opstack: + raise MRP (self) + if self.op and self.op in '+-' and self.num is None and self.arg is None: + self.num = 1 + return self.getterm (c) + + def getoptarg (self, c): + """Get an optional argument. Unlike getarg, this is legal + while we're in an incomplete expression. This method is used + for commands that do something if given an argument, but return + a value if not. This way, the second case can be used as + an element of an expression. + """ + if self.op and self.op in '+-' and self.num is None and self.arg is None: + self.num = 1 + if self.num is None: + return None + return self.getarg (c) + + def setval (self, val): + """Set the command result value into the expression state. + """ + self.num = val + self.clearmods () + + def bitflag (self, name): + """Process a bit-flag type command, i.e., one that is read by + supplying no argument, set by supplying one, and has its bits + fiddled by two arguments. + """ + n = self.getoptarg (name) + if n is None: + self.setval (getattr (self, name)) + else: + if self.arg2 is not None: + n = (getattr (self, name) | n) & (~self.arg2) + if n & 32768: + # Sign extend upper 16 bits + n |= -32768 + fixed = getattr (self, name + "fixed", 0) + self.clearargs () + setattr (self, name, n | fixed) + + def numflag (self, name): + """Process a numeric flag type command, i.e., one that is + read by supplying no argument, and set by supplying the new value. + """ + n = self.getoptarg (name) + if n is None: + self.setval (getattr (self, name)) + else: + self.clearargs () + setattr (self, name, n) + + def lineargs(self, c): + """Process the argument(s) for a command that references lines. + If one argument is present, that is taken as a line count + displacement from dot. If two arguments are present, that is + the start and end of the the range. + """ + m, n = self.arg2, self.getarg (c) + if n is None: + n = 1 + if m is None: + if n > 0: + m, n = self.dot, self.buffer.line (n) + else: + m, n = self.buffer.line (n), self.dot + else: + if m < 0 or n > self.end or m > n: + raise POP (self, c) + return (m, n) + + def clearmods (self): + """Clear modifier flags (colon and at sign). + """ + self.colons = 0 + self.atmod = False + + def clearargs (self): + """Reinitialize all expression state, as well as modifiers. + """ + self.opstack = [ ] + self.arg = None + self.arg2 = None + self.num = None + self.op = None + self.clearmods () + + def failedcommand (self): + """Return the last failed interactive command, i.e., the last + command up to the point where execution was aborted. + """ + return self.interactive.failedcommand () + + def lastcommand (self): + """Return the last interactive command, in full. + """ + return self.interactive.lastcommand () + + def mainloop (self): + """This is the TECO command loop. It fetches the command string, + handles special immediate action forms, and otherwise executes + the command as supplied. Errors are handled by catching the + TECO error exception, and printing the error information as + controlled by the EH flag. + """ + preverror = False + try: + while True: + if not self.cmdhandler.eifile: + if screen: + y, x = screen.getmaxyx () + screen.untouchwin () + screen.move (y - 1, 0) + screen.clrtoeol () + screen.refresh () + curses.reset_shell_mode () + self.incurses = False + self.screenok = False + self.updatedisplay () + # clear "in startup mode" flag + self.et &= ~128 + self.autoverify (self.ev) + sys.stdout.write ("*") + sys.stdout.flush () + cmdline = self.cmdhandler.teco_cmdstring () + self.clearargs () + if cmdline and cmdline[-1] != esc: + # it was an immediate action command -- handle that + cmd = cmdline[0] + if cmd == '*': + try: + q = self.interactive.qreg (cmdline[1]) + except err as e: + e.show () + else: + q.setstr (self.lastcommand ()) + continue + elif cmd == '?': + if preverror: + print(printable (self.failedcommand ())) + continue + elif cmd == lf: + cmdline = "lt" + else: + cmdline = "-lt" + try: + preverror = False + self.runcommand (cmdline) + except ExitExecution: + pass + except SystemExit: + endwin () + enddisplay () + break + except err as e: + preverror = True + e.show () + ###print_exc_plus () # *** for debug + # Turn off any EI + self.cmdhandler.ei ("") + except: + print_exc_plus () + except: + print_exc_plus () + + def runcommand (self, s): + """Execute the specified TECO command string as an interactive + level command. + """ + self.interactive.run (s) + + def screentext (self, height, width, curlinenum): + """Given a screen height and width in characters, and the + line on which we want 'dot' to appear, determine the text that + fits on the screen. + + Returns a three-element tuple: lines, row, and column corresponding + to dot. + + Lines is a list; each list element is a pair of text and + wrap flag. Wrap flag is True if this chunk of text is wrapped, + i.e., it does not end with a carriage return, and False if + it is the end of the line. + """ + curlinestart = self.buffer.line (0) + curcol = self.dot - curlinestart + line = self.buf[curlinestart:self.buffer.line(1)] + lines, currow, curcol = untabify (line, curcol, width) + n = 1 + # First add on lines after the current line, up to the + # window height, if we have that many + while len (lines) < height: + start, end = self.buffer.line (n), self.buffer.line (n + 1) + if start >= self.end: + break + line, i, i = untabify (self.buf[start:end], 0, width) + lines += line + n += 1 + # Next, add lines before the current line, until we have + # enough to put the cursor onto the line where we want it, + # but also try to fill the screen + n = 0 + while currow < curlinenum or len (lines) < height: + start, end = self.buffer.line (-n - 1), self.buffer.line (-n) + if not end: + break + line, i, i = untabify (self.buf[start:end], 0, width) + lines = line + lines + currow += len (line) + n += 1 + # Now trim things, since (a) the topmost line may have wrapped + # so the cursor may be lower than we want it to be, and (b) + # we now probably have more lines than we want at the end + # of the screen. + trim = min (currow - curlinenum, len (lines) - height) + if trim > 0: + lines = lines[trim:] + currow -= trim + if len (lines) > height: + lines = lines[:height] + return lines, currow, curcol + + def enable_curses (self): + """Enable curses (VT100 style screen watch) mode, if available + in this Python installation. This is a NOP if curses is not + available. + """ + global screen + if not cursespresent: + return + if not screen: + atexit.register (endwin) + screen = curses.initscr () + curses.noecho () + curses.nonl () + curses.raw () + curses.def_prog_mode () + else: + curses.reset_prog_mode () + self.incurses = True + self.watchparams[2], self.watchparams[1] = screen.getmaxyx () + + def watch (self): + """Do a screen watch operation, i.e., update the screen to + reflect the buffer contents around the current dot, in curses mode. + """ + if not cursespresent: + return + self.enable_curses () + curlinenum = self.curline + width, height = self.watchparams[1], self.watchparams[2] + lines, currow, curcol = self.screentext (height, width, curlinenum) + if currow >= height: + currow = height - 1 + if curcol >= width: + curcol = width - 1 + for row, line in enumerate (lines): + line, wrap = line + screen.addstr (row, 0, line) + screen.clrtoeol () + screen.clrtobot () + if not self.screenok: + screen.clearok (1) + self.screenok = True + screen.move (currow, curcol) + screen.refresh () + + # Interface to the display thread + def startdisplay (self): + """Start the wxPython display (GT40 emulation, essentially). + This is a NOP if wxPython is not available. + """ + if not display: + atexit.register (enddisplay) + # Release the main thread, allowing it to start the display + dsem.release () + else: + self.updatedisplay () + + def updatedisplay (self): + """Refresh the GT40 style display to reflect the current + buffer state around dot. + """ + if display: + display.show () + + def hidedisplay (self): + """Turn off (hide) the GT40 display. + """ + if display: + display.show (False) + + def autoverify (self, flag): + """Handle automatic verify for the ES and EV flags. The input + is the flag in question. + """ + if flag: + if flag == -1: + flag = 0 + ch = flag & 255 + if ch: + if ch < 32: + ch = lf + else: + ch = chr (ch) + flag >>= 8 + start = self.buffer.line (-flag) + end = self.buffer.line (flag + 1) + sys.stdout.write (printable (self.buf[start:self.dot])) + if ch: + sys.stdout.write (ch) + sys.stdout.write (printable (self.buf[self.dot:end])) + sys.stdout.flush () + self.screenok = False + +# A metaclass to allow non-alphanumeric methods to be defined, which +# is handy when you use method names directly for command character +# processing. Inspired by the Python Cookbook, chapter 20 intro. +def _repchar (m): + return chr (int (m.group (1), 8)) +class Anychar (type): + def __new__ (cls, cname, cbases, cdict): + newnames = {} + charre = re.compile ("char([0-7]{3})") + for name in cdict: + newname, cnt = charre.subn (_repchar, name) + if cnt: + fun = cdict[name] + newnames[newname] = fun + cdict.update (newnames) + return super (Anychar, cls).__new__ (cls, cname, cbases, cdict) + +class qreg (object): + '''Queue register object. Stores text and numeric parts, with + methods to access each part. + ''' + def __init__ (self): + self.num = 0 + self.text = "" + + def getnum (self): + return self.num + + def setnum (self, val): + self.num = val + + def getstr (self): + return self.text + + def setstr (self, val): + self.text = val + + def appendstr (self, val): + self.text += val + +# Atexit handlers. These are guarded so they can be called even +# if the corresponding module isn't present. +def endwin (): + """Close down curses mode. + """ + global screen + if screen: + try: + curses.endwin () + except: + pass + screen = None + +def enddisplay (): + """Stop wxPython display. + """ + global display + if display: + display.stop () + +if wxpresent: + pointsize = 12 + + class displayApp (): + """This class wraps the App main loop for wxPython. + + Due to limitations in some OS (Mac OS at least), this + class must be created in the main thread -- the first + thread of the process. Furthermore, the "start" method + will create the application and run the main loop, and will + not return until application exit. So for any other things + that need to run in the meantime, like user interaction, + the caller will need to create an additional thread. + + This class creates a 24 by 80 character window, and initializes + some common state such as the font used to display text + in the window. + """ + + def __init__ (self, teco): + self.running = False + self.teco = teco + self.displayline = 16 + + def start (self): + """Start the wx App main loop. + This finds a font, then opens up a Frame initially + sized for 80 by 24 characters. + """ + global display + self.app = wx.App () + self.font = wx.Font (pointsize, wx.FONTFAMILY_MODERN, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL) + dc = wx.MemoryDC () + dc.SetFont (self.font) + self.fontextent = dc.GetTextExtent ("a") + cw, ch = self.fontextent + self.margin = cw + cw = cw * 80 + self.margin * 2 + ch = ch * 24 + self.margin * 2 + self.frame = displayframe (self, wx.ID_ANY, "TECO display", + wx.Size (cw, ch)) + self.frame.Show (True) + self.running = True + self.app.MainLoop () + # Come here only on application exit. + display = None + + def show (self, show = True): + """If the display is active, this refreshes it to display + the current text around dot. If "show" is False, it tells + the display to go hide itself. + """ + if self.running: + self.frame.doShow = show + self.frame.doRefresh = True + wx.WakeUpIdle () + + def stop (self): + """Stop the display thread by closing the Frame. + """ + if self.running: + self.running = False + self.frame.AddPendingEvent (wx.CloseEvent (wx.wxEVT_CLOSE_WINDOW)) + + class displayframe (wx.Frame): + """Simple text display window class derived from wxFrame. + It handles repaint, close, and timer events. The timer + event is used for the blinking text cursor. + + When instantiated, this class creats the window using the + supplied size, and starts the cursor blink timer. + """ + def __init__ (self, display, id, name, size): + framestyle = (wx.MINIMIZE_BOX | + wx.MAXIMIZE_BOX | + wx.RESIZE_BORDER | + wx.SYSTEM_MENU | + wx.CAPTION | + wx.CLOSE_BOX | + wx.FULL_REPAINT_ON_RESIZE) + wx.Frame.__init__ (self, None, id, name, style = framestyle) + self.SetClientSize (size) + timerId = 666 + self.Bind (wx.EVT_PAINT, self.OnPaint) + self.Bind (wx.EVT_CLOSE, self.OnClose) + self.Bind (wx.EVT_TIMER, self.OnTimer) + self.Bind (wx.EVT_IDLE, self.OnIdle) + self.display = display + self.cursor = None, None, False + self.timer = wx.Timer (self, timerId) + self.timer.Start (500) + self.cursorState = True + self.doRefresh = False + self.SetBackgroundColour (wx.WHITE) + + def OnIdle (self, event = None): + """Used to make a refresh happen, if one has been requested. + """ + if self.doRefresh: + self.doRefresh = False + self.Show (self.doShow) + if self.doShow: + self.Refresh () + + def OnTimer (self, event = None): + """Draw a GT40-TECO style cursor: vertical line with + a narrow horizontal line across the bottom, essentially + an upside-down T. + + If dot is between a CR and LF, the cursor is drawn upside + down (right side up T) at the left margin. + """ + x, y, flip = self.cursor + if x is not None: + cw, ch = self.display.fontextent + if self.cursorState: + pen = wx.BLACK_PEN + else: + pen = wx.WHITE_PEN + self.cursorState = not self.cursorState + dc = wx.ClientDC (self) + dc.SetPen (pen) + if flip: + dc.DrawLine (x, y, x, y - ch) + dc.DrawLine (x - cw / 2, y - ch, x + cw / 2 + 1, y - ch) + else: + dc.DrawLine (x, y, x, y - ch) + dc.DrawLine (x - cw / 2, y, x + cw / 2 + 1, y) + + def OnPaint (self, event = None): + """This is the event handler for window repaint events, + which is also done on window resize. It fills the window + with the buffer contents, centered on dot. + + Line wrap is indicated in GT40 fashion: the continuation line + segments have a right-pointing arrow in the left margin. + """ + dc = wx.PaintDC (self) + dc.Clear () + dc.SetFont (self.display.font) + w, h = dc.GetSize () + w -= 2 * self.display.margin + h -= 2 * self.display.margin + cw, ch = self.display.fontextent + w //= cw + h //= ch + lines, currow, curcol = self.display.teco.screentext (h, w, h // 2) + if curcol > len (lines[currow][0]): + self.cursor = self.display.margin, \ + (currow + 2) * ch + self.display.margin, \ + True + else: + self.cursor = curcol * cw + self.display.margin, \ + (currow + 1) * ch + self.display.margin, \ + False + wrap = False + dc.SetPen (wx.BLACK_PEN) + for row, line in enumerate (lines): + y = self.display.margin + row * ch + if wrap: + y2 = y + ch - ch / 2 + dc.DrawLine (1, y2, cw - 1, y2) + dc.DrawLines ([ wx.Point (cw / 2, y2 - cw / 3), + wx.Point (cw - 1, y2), + wx.Point (cw / 2, y2 + cw / 3 + 1)]) + line, wrap = line + dc.DrawText (line, self.display.margin, y) + + def OnClose (self, event = None): + """Close the GT40 window, and stop the cursor blink timer. + """ + self.timer.Stop () + self.cursor = None, None + self.Destroy () + +# Nice hairy regexp for scanning across bracketed constructs looking +# for the end of a range (conditional or iteration). It doesn't bother +# looking for parentheses since none of the constructs we have to scan +# for ("else" or condition end, or iteration end, or label) are allowed +# inside parentheses -- and it isn't the job of this scanner to catch +# illegal commands. For the same reason, it doesn't do things like +# look for missing arguments, or invalid q-reg names, etc. +# +# The recipe here goes like this: the first half is for @-modified commands, +# so it matches string arguments wrapped in matching delimiters. +# The second half is the corresponding set of rules for non-@-modified +# commands, so they have escape as the string terminator, except for +# those oddballs that use something else, like ctrl/a. It also covers +# the cases of commands that don't take string arguments and thus +# don't care about @ modifiers +# +# The indenting is meant to show grouping. This pattern must be compiled +# with the "verbose" flag. +# +# This pattern is subsequently modified to make three very similar patterns: +# one to scan across iterations, one to scan across conditionals, and +# one to search for tags (labels). A single base pattern is used to +# form all three, so I don't have to keep three almost-identical copies +# of these things in sync. +basepat = """ + # First any commands that take string arguments, @ modified flavor + (?:(?:@(?:\\:*(?:(?:f(?:(?:[cns_](.).*?\\1.*?\\1)| + (?:[br](.).*?\\2)| + .))| + (?:e(?:[bginrw_](.).*?\\3|.))| + # Control A and Control U in uparrow form + (?:\\^(?:(?:a(.).*?\\4)| + (?:u\\.?.(.).*?\\5)|.))| + # Tag start is included here, so tags are skipped + # The ! is removed for tag search so tags are + # not skipped there. + (?:[\001!inos_](.).*?\\6)| + (?:\025\\.?.(.).*?\\7))))| + # Next commands that take string arguments, no @ + (?:(?:f(?:(?:[cns_].*?\033.*?\033)| + (?:[br].*?\033)| + .))| + (?:e(?:[bginrw_].*?\033|.))| + # Control A, Control U, Control ^ in uparrow form + (?:\\^(?:(?:a.*?\001)| + (?:u\\.?..*?\025)| + (?:\\^.)|.))| + (?:[inos_].*?\033)| + (?:\001.*?\001)| + # At this point we insert one of several subexpressions, + # depending on what we need: a pattern to skip tags, + # or a pattern to skip condition starts, or both, or + # neither + ### insert here + (?:\025\\.?..*?\033)| + (?:\036.)| + (?:[][%gmqux]\\.?.)| + # The tilde is replaced by the terminator character set + [^~]))* + """ +# These two can be inserted into basepat at "### insert here" +marker = "### insert here" +exclpat = "(?:!.*?!)|" +dqpat = '(?:".)|' + +# These are the terminator sets, inserted at two places into basepat to +# specify what set of characters terminates the scan +iterset = "<>" +condset = "\"|\'<>" +tagset = "!<>" + +# Construct the three patterns +iterpat = basepat.replace (marker, exclpat + dqpat).replace ('~', iterset) +condpat = basepat.replace (marker, exclpat).replace ('~', condset) +tagpat = basepat.replace ("!", "").replace (marker, dqpat).replace ('~', tagset) + +iterre = re.compile (iterpat, re.IGNORECASE | re.DOTALL | re.VERBOSE) +condre = re.compile (condpat, re.IGNORECASE | re.DOTALL | re.VERBOSE) +tagre = re.compile (tagpat, re.IGNORECASE | re.DOTALL | re.VERBOSE) + +class iter (object): + '''State for command iterations. + ''' + def __init__ (self, teco, cmd, count): + self.start = cmd.cmdpos + self.count = count + self.cmd = cmd + self.teco = teco + + def again (self, atend = True, delta = 1): + if self.count: + self.count -= delta + if not self.count: + if not atend: + self.cmd.skipiter () + if self.teco.trace: + sys.stdout.write ('>') + sys.stdout.flush () + self.cmd.iterstack.pop () + return + self.cmd.cmdpos = self.start + self.teco.clearargs () + +# assorted regular expressions used below: + +# patterns for \ command, for the three possible radix values +decre = re.compile (r'[+-]?\d+') +octre = re.compile (r'[+-]?[0-7]+') +hexre = re.compile (r'[+-]?[0-9a-f]+', re.IGNORECASE) + +# Patterns for the string builder, with and without ^x to control-x +# conversion. Note that a single replacer function is used with +# either pattern, so bldpat must be a superset of buildpatnoup, +# and the common groups must come first and in the same order. +_bldpat = re.compile(''' + (?:(?:(?:\\^[qr])|[\021\022])(.))| # ^Qx or ^Rx + (?:(?:(?:\\^e)|\005)q(\\.?.))| # ^EQq + (?:(?:(?:\\^e)|\005)u(\\.?.))| # ^EUq + (?:(?:(?:\\^v)|\026)(.))| # ^Vx + (?:(?:(?:\\^w)|\027)(.))| # ^Wx + (?:\\^(.)) # ^x + ''', re.IGNORECASE |re.DOTALL | re.VERBOSE) +_bldpatnoup = re.compile(''' + (?:[\021\022](.))| # ^Qx or ^Rx + (?:\005q(\\.?.))| # ^EQq + (?:\005u(\\.?.))| # ^EUq + (?:\026(.))| # ^Vx + (?:\027(.)) # ^Wx + ''', re.IGNORECASE | re.DOTALL | re.VERBOSE) + +# pattern for the search string to search regexp converter +_searchpat = re.compile (''' + # A regexp special character (must be quoted) + ([][\\\\^$.?+(){}])| + # ^ES -- One or more spaces/tabs; ^EX -- any char + # These two do not accept ^N + ((?:\005[sx])|\030)| + # Check for leading ^N (inverse match) + (?:(\016)? + (?: + # ^EGq -- table match, with optional ^N + (?:\005g(\\.?.))| + # All other special match characters + ((?:\005[abcdlrvwx])|\023)))| + # Check for ^EE -- regexp match (teco.py addition) + (?:\005e(.+)) + ''', re.IGNORECASE | re.DOTALL | re.VERBOSE) + +# Substitution dictionary for the special match characters +# +# These are regexp subexpressions corresponding to TECO match patterns +_searchdict2 = { ctrle + "s" : "[ \t]+", + ctrle + "x" : ".", + ctrlx : "." } + +# These are rexexp character class expressions, so they go inside +# [...], or [^...] if ^N was present in the TECO string +_searchdict5 = { ctrle + "a" : "A-Za-z", + ctrle + "b" : "\\W", + ctrle + "c" : "\\w$_.", + ctrle + "d" : "\d", + ctrle + "l" : eol, + ctrle + "r" : "\\w", + ctrle + "v" : "a-z", + ctrle + "w" : "A-Z", + ctrls : "\\W"} + +class command_level(metaclass=Anychar): + '''This state handles a single command level (interactive or macro + execution) for TECO. + + Any method with a one-character name is the handler for the + corresponding TECO command. Two-character methods are for two- + character TECO command names (the dispatch is via the one-character + method matching the start character; for example method "fb" is + invoked via method "f"). + + TECO command characters that are not valid Python symbol names + are represented by methods with "charnnn" in the name. The metaclass + creates synonyms for those methods with the real name, which is + the character with octal char code nnn. For example, char042 is + the " (double quote) command method, and fchar074 is the f< command + method. + ''' + def __init__ (self, teco, q = None): + self.qregs = q or { } + self.teco = teco + self.enlist = [ ] + self.enstring = "" + self.iterstack = [ ] + + # Define a bunch of properties for cleaner access to state that + # is kept in other places. + # First the ones that are common across all command levels, and + # are kept by the "teco" class: + atmod = commonprop ("atmod") + arg2 = commonprop ("arg2") + colons = commonprop ("colons") + ctrlxflag = commonprop (ctrlx) + edflag = commonprop ("ed") + etflag = commonprop ("et") + radix = commonprop ("radix") + laststringlen = commonprop ("laststringlen") + lastsearch = commonprop ("lastsearch") + lastfilename = commonprop ("lastfilename") + trace = commonprop ("trace") + buffer = commonprop ("buffer") + screenok = commonprop ("screenok") + + # Now the ones that relate to the text buffer, so they are kept + # by the "buffer" class: + buf = bufprop ("text") + dot = bufprop ("dot") + end = bufprop ("end") + eoflag = bufprop ("eoflag") + ffflag = bufprop ("ffflag") + + def do (self, c): + """Execute the single teco command named by the argument + (a single character, or a two-character string for TECO + commands that have two character names). The method for that + command is invoked, if it exists; otherwise error ILL + (Illegal command) is raised. + + The command name is passed as argument to the method, which is + useful when several commands (e.g., all the digits) are + bound to a single method. + """ + c = c.lower () + try: + op = getattr (self, c) + except AttributeError: + raise ILL (self.teco, c) + op (c) + + def tracechar (self, c): + """Show the supplied character (or string) as trace text, + if tracing is enabled. + """ + if self.trace: + sys.stdout.write (printable (c)) + sys.stdout.flush () + + def peeknextcmd (self): + """Look at the next command character, without advancing + the current command pointer. + """ + try: + return self.command[self.cmdpos] + except IndexError: + return "" + + def nextcmd (self): + """Get the next command character; if there isn't one, + error UTC (Unterminated Command) is raised. + """ + c = self.peeknextcmd () + if not c: + raise UTC (self.teco) + self.tracechar (c) + self.cmdpos += 1 + return c + + def colon (self): + """Return True if colon modifier(s) are present. + """ + return self.colons != 0 + + def getarg (self, c, default = None): + '''Get the command argument. If there is no argument, the + default argument governs what happens. If no default is + supplied, the function returns None. If a default value is + supplied, that value is returned. Otherwise, the default argument + should be an exception class, and that exception is raised. + This function is used for cases where the command does not return + a value; it requires that any argument is complete (matching + parentheses, right hand side present for a pending operator). + ''' + ret = self.teco.getarg (c) + if default is not None: + self.clearargs () + if ret is None: + # Yuck. If exceptions were new style classes + # I wouldn't need this ugly mess! + if type (default) is type (Exception): + raise default (self.teco) + ret = default + return ret + + def getoptarg (self, c): + '''Get the command argument. Return None if it was not present. + This function may be called when we are in the middle of an + expression; that is intended for the case where a command may return + a value that is then in turn part of an expression. + ''' + return self.teco.getoptarg (c) + + def getargs (self, c, default = None): + """Get the command argument pair, as a pair. If there was + only one argument, the first element of the pair is None. + If there was no argument at all, or nothing after the comma, + the supplied default is used for the second element of the pair + in the same way as for method getarg. + """ + arg2 = self.arg2 + return arg2, self.getarg (c, default) + + def getargc (self, c, default = None): + """Get the command argument and the colon modifier, as a pair. + If there was no argument, the supplied default is used for the + first element of the pair in the same way as for method getarg. + """ + col = self.colon () + return self.getarg (c, default), col + + def getargsc (self, c, default = None): + """Get the command argument pair and the colon flag, as a tuple. + If there was only one argument, the first element of the pair is None. + If there was no argument at all, or nothing after the comma, + the supplied default is used for the second element of the pair + in the same way as for method getarg. + """ + arg2 = self.arg2 + col = self.colon () + return arg2, self.getarg (c, default), col + + def setval (self, n): + """Set the command result value into the expression state. + """ + self.teco.setval (n) + + def clearargs (self): + """Clear the expression state and command modifiers. + """ + self.teco.clearargs () + + def clearmods (self): + """Clear the command modifier flags (colon and at sign). + """ + self.teco.clearmods () + + def bitflag (self, c): + """Process a bit flag command, such as ET. See teco.bitflag + for details. + """ + self.teco.bitflag (c) + + def numflag (self, c): + """Process a numeric flag command, such as EV. See teco.numflag + for details. + """ + self.teco.numflag (c) + + def strarg (self, c, term = esc): + """Return the string argument for the command. If the at sign + modifier is in effect, the next character in the command string + is the delimiter. Otherwise, the term argument specifies the + delimiter, or ESC is used if term is omitted. + """ + if self.atmod: + term = self.nextcmd () + self.atmod = False + s = self.cmdpos + try: + e = self.command.index (term, s) + except ValueError: + raise UTC (self.teco, c) + self.cmdpos = e + 1 + self.tracechar (self.command[s:self.cmdpos]) + return self.command[s:e] + + def strargs (self, c): + """Return a pair of string arguments for the command. If the at + sign modifier is in effect, the next character in the command + string is the delimiter. Otherwise, the delimiter is ESC. + """ + term = esc + if self.atmod: + term = self.peeknextcmd () + s1 = self.strarg (c) + return s1, self.strarg (c, term) + + def makecontrol (self, c): + """Return the control character correponding to the supplied + character; for example, 'a' produces control/A. + """ + n = ord (c) + if 0o100 <= n <= 0o137 or 0o141 <= n <= 0o172: + return chr (n & 31) + else: + raise IUC (self.teco, chr (n)) + + def _strbuildrep (self, m): + if m.group (1): + # ^Qx or ^Rx is literally x + return m.group (1) + elif m.group (2): + # ^EQq is text of Q-reg q + return self.qregstr (m.group (2)) + elif m.group (3): + # ^EUq is character whose code is in numeric Q-reg q + return chr (self.qreg (m.group (3)).getnum ()) + elif m.group (4): + # ^Vx is lowercase x + return m.group (4).lower () + elif m.group (5): + # ^Vx is uppercase x + return m.group (5).upper () + else: + # ^x is control-x + return self.makecontrol (m.group (6)) + + def strbuild (self, s): + """TECO string builder. This processes uparrow/char combinations, + unless bit 0 in ED is set. It also handles string build + characters such as ^Qx (literal x), ^EQq (text in q-reg q), etc. + """ + if self.edflag & 1: + pat = _bldpatnoup + else: + pat = _bldpat + return pat.sub (self._strbuildrep, s) + + def _str2rerep (self, m): + if m.group (1): + return '\\' + m.group (1) + elif m.group (2): + return _searchdict2[m.group (2).lower ()] + + inverse = m.group (3) is not None + if m.group (4): + # ^EGq -- table match + charset = set (self.qregstr (m.group (4))) + pfx = sfx = '' + if not charset: + return "" + if not inverse and len (charset) == 1: + c = ''.join (charset) + if c in "][\\^$.?+(){}": + c = '\\' + c + return c + if ']' in charset: + charset -= set (']') + pfx = ']' + if '\\' in charset: + charset -= set ('\\') + pfx += '\\' + if '-' in charset: + sfx = '-' + charset -= set ('-') + c = pfx + ''.join (charset) + sfx + elif m.group (5): + c = _searchdict5[m.group (5).lower ()] + else: + # ^EE -- regexp pattern. Return it exactly as written. + return m.group (6) + if inverse: + return "[^%s]" % c + else: + return "[%s]" % c + + def str2re (self, s): + """Convert a TECO search string to the equivalent + regular expression string. + """ + reflags = re.DOTALL + if self.ctrlxflag == 0: + reflags |= re.IGNORECASE + return re.compile (_searchpat.sub (self._str2rerep, s), reflags) + + def isinteractive (self): + '''Return True if executing at the interactive level + as opposed to in a macro. + ''' + return self is self.teco.interactive + + def skip (self, pat): + '''Skip based on a regexp, starting at the current command + position. Updates command position to be one character beyond + the end of the match, and returns the character after the match, + if any. If no match, returns None. + + The reason for passing over an extra character is that the regexp + is coded to terminate on one of the characters we want to look + for -- for example, ! < > for tag search. It would make sense + to include that set at the end of the regexp, but if you do that + then the match attempt can take a very long time if there is no + match. (It seems to take exponential time!) To avoid that, + the regexp instead describes what we want to skip, and then + picks up, skips over, and returns the character after that. + ''' + m = pat.match (self.command, self.cmdpos) + if not m: + return None + self.cmdpos = m.end () + 1 + try: + return self.command[self.cmdpos - 1] + except IndexError: + return None + + def skipiter (self): + '''Skip across nested iterations to the end of the current + iteration. + ''' + level = 1 + while level > 0: + tail = self.skip (iterre) + if not tail: + raise UTC (self.teco, '<') + if tail == '<': + level += 1 + else: + level -= 1 + + def skipcond (self, c): + '''Skip across conditional code for the specified end string. + Nested conditionals are skipped. Nested iterations are + skipped but scanned, because iterations can overlap conditionals. + ''' + while True: + tail = self.skip (condre) + if not tail: + raise MAP (self.teco) + if tail in c: + break + else: + # We stopped on something other than what we wanted to skip to. + # There are two possibilities: it is the start of an inner + # range (either condition or iteration), or it is the end + # of some range. + # + # We can't just recursively skip nested ranges because + # of this warped case: + # < 0A"A C > ' + # + # So instead, nested conditions are just skipped, but + # iterations are handled by stacking a simulated start of + # iteration with a repeat count of one onto the iteration + # stack and continuing the scan in-line. The count of + # one means that this case also works somewhat sanely: + # "A < xxx ' > + # I suspect that's not legal, but who knows... + if tail == '<': + self.iterstack.append (iter (self.teco, self, 1)) + elif tail == '"': + self.cmdpos += 1 + self.skipcond ("'") + elif tail == '>': + # Found an iteration end. Pop it off the iteration stack + try: + self.iterstack.pop () + except IndexError: + raise BNI (self.teco) + + def findtag (self, c): + '''Search for the specified tag, starting at the current + command position. Nested iterations are skipped (not searched), + so if the tag is in one of those it will not be found. + ''' + while True: + tail = self.skip (tagre) + if not tail: + raise TAG (self.teco, c) + if tail == '!': + term = '!' + if self.command[self.cmdpos-2] == '@': + term = self.nextcmd () + if self.command.startswith (c + term, self.cmdpos): + self.cmdpos += len (c) + 1 + return + try: + e = self.command.index (term, self.cmdpos) + self.cmdpos = e + 1 + except ValueError: + raise UTC (self.teco, '!') + elif tail == '<': + p = self.cmdpos + self.skipiter () + else: + # Found an iteration end. Pop it off the iteration stack + try: + self.iterstack.pop () + except IndexError: + raise BNI (self.teco) + + def run (self, s): + self.command = s + self.cmdpos = 0 + self.iterstack = [ ] + try: + while self.cmdpos < len (self.command): + c = self.nextcmd () + self.do (c) + except ExitLevel: + pass + except KeyboardInterrupt: + raise XAB (self.teco) + + def search (self, s, n, start, end, colon, topiffail = True, + nextpage = None): + """Search in the current buffer for a given string. + Stop on the abs(n)th occurrence. If n is negative, search + is backward, starting at 'end'; otherwise it is forward, + starting at 'start'. The search range is bounded by + the range (start, end). If 'nextpage' is specified, it is + called if we run out of stuff to match in the current buffer, + continuing until end of file. Note that 'nextpage' is only + meaningful for forward searches (n > 0); it is ignored for + backward searches. + + Note: start and end are the range of buffer positions where + the match is allowed to begin, inclusive. + + If the search succeeds, dot is set to the end of the + match string, and the ^S variable is set to the negative of + the matched length. (I.e., .+^S is the start of the match.) + Finally, if 'colon' is true, the current arg is set to -1. + + If the search fails, a bunch of things can happen. + + If topiffail is True or omitted, and the 16 bit is clear in + the ED flag, dot is set to zero. + + If 'colon' is true, the current arg is set to 0. + The same happens if we're in an iteration, and the next command + character is a semicolon. + + Otherwise, if we're in an iteration, a warning message is + generated and the iteration is exited (as if a semicolon + had been next). If we're not in an iteration, an error + ?SRH is generated. + """ + rep = abs (n) + if n < 0: + pos = end + laststart = None + # We don't allow paging for reverse searches + nextpage = None + else: + pos = start + if s: + s = self.strbuild (s) + self.lastsearch = s + else: + s = self.lastsearch + re = self.str2re (s) + # Bind the buffer text to a local variable to help speed + # up the inner loop + buf = self.buf + while rep: + if n < 0: + # This is painful. There is no reverse search for + # regular expressions, so we do it the hard way, + # by repeatedly matching, stepping backwards one + # character at a time... + # + # Note to self: a different way that's probably faster + # but harder to do: reverse the string, reverse the + # regexp pattern, "unreverse" any [...] and [...]+ + # inside the regexp, and do an ordinary search with those. + # Then some extra work is needed to find any matches + # that straddle the search start point (i.e., dot). + tmatch = re.match (buf, pos) + if tmatch and not (laststart and tmatch.end () > laststart): + match = tmatch + laststart = match.start () + else: + if pos: + pos -= 1 + continue + match = None + else: + match = re.search (buf, pos) + if match and not start <= match.start () <= end: + match = None + if match is None: + # If we have a nextpage function and we're not + # at the end of the input file, keep going + if nextpage and self.eoflag == 0: + nextpage () + buf = self.buf + start = 0 + pos = 0 + end = self.end + continue + if topiffail and (self.edflag & 16) == 0: + self.buffer.goto (0) + if colon: + self.setval (0) + return False + elif self.iterstack: + self.setval (0) + if self.peeknextcmd () != ';': + print("%Search fail in iter") + # pretend there was a ; + self.do (';') + return False + else: + raise SRH (self.teco, s) + rep -= 1 + + # We found what we were looking for. "match" is a regexp + # match object for the matched string. + self.buffer.goto (match.end ()) + self.laststringlen = -(match.end () - match.start ()) + # Supply the success value if asked for, or if a ; follows + if colon or self.iterstack and self.peeknextcmd () == ';': + self.setval (-1) + self.teco.autoverify (self.teco.es) + return True + + def failedcommand (self): + """Return the command string up to the point where execution + was aborted. + """ + return self.command[:self.cmdpos] + + def lastcommand (self): + """Return the command string, in full. + """ + return self.command + + def qregname (self): + """Parse a Q-register name from the command string. If the + next character is dot, the name is dot plus the character + after that; otherwise it is just the next character. + + Note that the name is not validated here; the caller does that + if necessary. + """ + c = self.nextcmd () + if c == '.': + c += self.nextcmd () + return c.lower () + + def qdict (self, c): + """Return the Q-reg dictionary referenced by the supplied Q-reg + name. If the Q-reg name begins with dot, this is the local + Q-reg dictionary for the current command level; otherwise it + is the TECO-global dictionary. + + Note that the per-level dictionary is not necessarily unique + to the level; a colon-modified M command creates a new one, + an unmodified M command binds to the one of the invoking level. + """ + if c.isalnum (): + return self.teco.qregs + elif c[0] == '.' and c[1].isalnum (): + return self.qregs + else: + raise IQN (self.teco, c) + + def qreg (self, c = None): + """Return the Q-reg named by the argument, or by the command + string if the argument is omitted. If the Q-reg does not yet + exist, it is created (with no text and 0 numeric value). + """ + if c: + c = c.lower () + else: + c = self.qregname () + qd = self.qdict (c) + if c not in qd: + qd[c] = qreg () + return qd[c] + + def qregstr (self, c = None): + '''Return the string value of the specified Q-register, + or the last filename string if *, or the last search string + if _ was specified for the Q-register name. + ''' + if c is None: + t = self.peeknextcmd () + if t in "*_": + c = t + self.nextcmd () + if c == '*': + return self.lastfilename + elif c == '_': + return self.lastsearch + else: + return self.qreg (c).getstr () + + def setqreg (self, q): + """Set the Q-reg named by the command string to be the supplied + Q-reg. This is used by the ]q (pop Q-reg) command. + """ + c = self.qregname () + qd = self.qdict (c) + qd[c] = q + + # From here on we have the actual command handlers. Their names + # come in two forms. Commands whose names are alphabetic are + # given by functions whose names are simply the command name. + # Other commands are given by functions whose names contain + # "charnnn" where nnn is the octal character code. + + # a few control chars, and space, are nop + def nop (self, c): pass + char000 = nop # null (^@) + char070 = nop # bell (^G) + char012 = nop # line feed (^J) + char014 = nop # form feed (^L) + char015 = nop # carriage return (^M) + char040 = nop # space + + def char001 (self, c): # ^A + """^A command -- print text. + """ + s = self.strarg (c, '\001') + sys.stdout.write (s) + sys.stdout.flush () + self.screenok = False + self.clearargs () + + def char002 (self, c): # ^B + """Return the current date. Since we pretend to be RT-11 it + would make sense to return the RT-11 format date, but that + utterly falls apart starting with 2004 (32 years from 1972) + so use the RSX/VMS format instead, which is substantially + more Y2K-proof. + """ + now = time.localtime () + self.setval ((now.tm_year - 1900) * 512 + now.tm_mon * 32 + now.tm_mday) + + def char003 (self, c): # ^C + """^C command -- exit TECO if done at the interactive level; + stop execution and return to interactive prompt otherwise. + """ + if self.isinteractive (): + self.exit () + else: + raise ExitExecution + + def char004 (self, c): # ^D + """^D command -- set radix to decimal. + """ + self.radix = 10 + self.clearargs () + + def char005 (self, c): # ^E + """^E command -- return form feed flag. + """ + self.setval (self.ffflag) + + def char006 (self, c): # ^F + """^F command -- return switch register. We just make it zero + for lack of switches... + """ + self.setval (0) + + def char010 (self, c): # ^H + """Return the current time of day. Match ^B, so we'll do + RSX/VMS format here, too. Amusingly, that happens to be + the RT-11 format, too. + """ + now = time.localtime () + self.setval (now.tm_hour * 3600 + now.tm_min * 60 + now.tm_sec) + + def char011 (self, c): # tab + """Tab command -- insert text including the leading tab. + """ + s = self.strarg (c) + self.buffer.insert (tab + s) + self.clearargs () + + def char016 (self, c): # ^N + """^N command -- return end of file flag. + """ + self.setval (self.eoflag) + + def char017 (self, c): # ^O + """^O command -- set radix to octal. + """ + self.radix = 8 + self.clearargs () + + def char021 (self, c): # ^Q + """^Q command -- return character offset corresponding to + the line offset supplied as the argument. + """ + self.setval (self.buffer.line (self.getarg (c, 1))) + + def char022 (self, c): # ^R + """^R -- Set the radix to the supplied value, which must + be 8, 10, or 16. + """ + r = self.getoptarg (c) + if r is None: + self.clearmods () + self.setval (self.radix) + else: + self.clearargs () + if r in (8, 10, 16): + self.radix = r + else: + raise IRA (self.teco) + + def char023 (self, c): # ^S + """^S command -- return the negative of the length of the + last string matched, set as replacement, or inserted. + """ + self.setval (self.laststringlen) + + def char024 (self, c): # ^T + """^T command. If an argument is given, output the character + with that numeric value (in raw mode if colon is present). + Otherwise, read a character from input and return its + numeric code. + + If bit 5 in ET is set, return -1 if there is no input; otherwise + wait for it. (TODO) + """ + colon = self.colon () + n = self.getoptarg (c) + if n is None: + self.clearmods () + if (self.etflag & 32) and self.teco.cmdhandler.eifile is None: + # TODO -- nowait char fetch from terminal + n = -1 + else: + n = ord (self.teco.cmdhandler.getch ()) + self.setval (n) + else: + self.clearargs () + if colon: + sys.stdout.write (chr (n)) + else: + sys.stdout.write (printable (chr (n))) + self.screenok = False + sys.stdout.flush () + + def char025 (self, c): # ^U + """^U command -- set Q-reg text. + """ + q = self.qreg () + s = self.strarg (c) + if self.colon (): + q.appendstr (s) + else: + q.setstr (s) + self.clearargs () + + def char026 (self, c): # ^V + pass + + def char027 (self, c): # ^W + pass + + char030 = numflag # ^X + + def char031 (self, c): # ^Y + """^Y command -- synonym of ^S+.,. + """ + self.clearargs () + self.arg2 = self.dot + self.laststringlen + self.setval (self.dot) + + def char032 (self, c): # ^Z + """^Z command -- This is supposed to be total Q-reg text size. + Just return 0 for now. + """ + self.setval (0) + + def char033 (self, c): # esc + """ESCAPE -- exit the current level if $$, otherwise clear + out any expression value and modifiers. + """ + try: + if self.peeknextcmd () == esc: + raise ExitLevel + except UTC: + pass + self.clearargs () + + def char036 (self, c): # ^^ + """^^ command -- return the numeric value of the following character + in the command string. + """ + self.setval (ord (self.nextcmd ())) + + def char037 (self, c): # ^_ + """^_ command -- return one's complement of the argument. + """ + self.setval (~self.getarg (c, NAB)) + + def char041 (self, c): # ! + """! command -- tag (O command target) or comment. + """ + self.strarg (c, '!') + + def char042 (self, c): # " + '''" command -- conditional execution range start. + ''' + n = self.getarg (c, NAQ) + if 0 <= n < 0x110000: + nc = chr (n) + else: + nc = "" + c = self.nextcmd ().lower () + if c == 'a': + cond = nc.isalpha () + elif c == 'c': + cond = nc.isalnum () or nc in "$._" + elif c == 'd': + cond = nc.isdigit () + elif c in "efu=": + cond = n == 0 + elif c in "g>": + cond = n > 0 + elif c in "lst<": + cond = n < 0 + elif c in "n": + cond = n != 0 + elif c == 'r': + cond = nc.isalnum () + elif c == 'v': + cond = nc.islower () + elif c == 'w': + cond = nc.isupper () + else: + raise IQC (self.teco) + if not cond: + self.skipcond ("|'") + self.tracechar (self.command[self.cmdpos - 1]) + + def char045 (self, c): # % + """% command -- increment Q-reg numeric value by the specified + amount, and return the result. + """ + n = self.getoptarg (c) + if n is None: + n = 1 + q = self.qreg () + n += q.getnum () + q.setnum (n) + self.setval (n) + + def char047 (self, c): # ' + """' command -- conditional range end. + """ + pass + + def char050 (self, c): # ( + """( command -- expression grouping. + """ + self.teco.leftparen () + + def char051 (self, c): # ) + """) command -- expression grouping. + """ + self.teco.rightparen () + + def operator (self, c): + """Arithmetic operators. All the operators are bound to + this method; the command character (which is the argument) + distinguishes them. + """ + self.teco.operator (c) + + char043 = operator # # + char046 = operator # & + char052 = operator # * + char053 = operator # + + char055 = operator # - + char057 = operator # / + + def char054 (self, c): # , + """, command -- second operand marker. + """ + if self.arg2 is None: + n = self.getarg (c, ARG) + if n < 0: + raise NCA (self.teco) + self.arg2 = n + else: + raise ARG (self.teco) + + def char056 (self, c): # . + """. command -- current buffer position. + """ + self.setval (self.dot) + + def digit (self, c): + """Digits are handled by this method. All digit methods are + bound to this method, and distinguished by the command + character argument. + """ + self.teco.digit (c) + + char060 = digit + char061 = digit + char062 = digit + char063 = digit + char064 = digit + char065 = digit + char066 = digit + char067 = digit + char070 = digit + char071 = digit + + def char072 (self, c): # : + """: command -- modifier. + """ + self.colons = 1 + if self.peeknextcmd () == ':': + self.nextcmd () + self.colons = 2 + + def char073 (self, c): # ; + """; command -- iteration exit. + """ + n, colon = self.getargc (c, NAS) + if not self.iterstack: + raise SNI (self.teco) + if (not colon and n >= 0) or (colon and n < 0): + self.skipiter () + self.tracechar ('>') + self.iterstack.pop () + + def char074 (self, c): # < + """< command -- iteration start. + """ + n = self.getarg (c) + self.clearargs () + if n is None: + self.iterstack.append (iter (self.teco, self, 0)) + elif n <= 0: + self.skipiter () + self.tracechar ('>') + else: + self.iterstack.append (iter (self.teco, self, n)) + + def char075 (self, c): # = + """= command -- display the argument in decimal. + == command -- display the argument in octal. + === command -- display the argument in hex. + + CRLF is added after the value unless : modifier is given. + """ + n, colon = self.getargc (c, NAE) + if colon: + term = "" + else: + term = lf + if self.peeknextcmd () == '=': + self.nextcmd () + if self.peeknextcmd () == '=': + self.nextcmd () + sys.stdout.write ("%x%s" % (n, term)) + else: + sys.stdout.write ("%o%s" % (n, term)) + else: + sys.stdout.write ("%d%s" % (n, term)) + self.screenok = False + sys.stdout.flush () + + def char076 (self, c): # > + """< command -- iteration end. + """ + if not self.iterstack: + raise BNI (self.teco) + self.clearargs () + self.iterstack[-1].again () + + def char077 (self, c): # ? + """? command -- toggle trace flag. + """ + self.trace = not self.trace + + def char100 (self, c): # @ + """@ command -- modifier (explicitly supplied string delimiter). + """ + self.atmod = True + + def a (self, c): + """A command -- append (if no argument) or return numeric value + of character in the text buffer (if argument is given, which is + the offset from dot). + """ + n, colon = self.getargc (c) + if n is None: + self.clearargs () + ret = self.buffer.append () + if colon: + self.setval (ret) + else: + pos = self.dot + n + if 0 <= pos < self.end: + self.setval (ord (self.buf[pos])) + else: + self.setval (-1) + + def b (self, c): + """B command -- zero (start of buffer). + """ + self.setval (0) + + def c (self, c): + """C command -- move forward n characters. + """ + newpos = self.dot + self.getarg (c, 1) + if 0 <= newpos <= self.end: + self.buffer.goto (newpos) + else: + raise POP (self.teco, c) + + def d (self, c): + """D command -- delete n characters. If two arguments are + given, delete that range of characters. + """ + # TODO: two args + m, n = self.getargs (c, 1) + if m is None: + end = self.dot + n + if 0 <= end <= self.end: + if n < 0: + self.buffer.goto (end) + n = -n + if n: + self.buffer.delete (n) + else: + raise POP (self.teco, c) + else: + if 0 <= m <= n <= self.end: + self.buffer.goto (m) + self.buffer.delete (n - m) + else: + raise POP (self.teco, c) + self.clearmods () + + def e (self, c): + """E command -- two character command starting with E. + """ + c = self.nextcmd () + try: + self.do ('e' + c) + except ILL: + raise IEC (self.teco, c) + + def ea (self, c): + """EA command -- switch to alternate output stream. + """ + self.buffer.ea () + + def eb (self, c): + """EB command -- open file for editing (input/output, with + backup). + """ + fn = self.strbuild (self.strarg (c)) + colon = self.colon () + self.clearargs () + ret = self.buffer.eb (fn, colon) + if colon: + self.setval (ret) + + def ec (self, c): + """EC command -- finish with the current file. If input and + output files are open, write remainder of the input to output, + then close both. + """ + self.buffer.ec () + self.clearargs () + + ed = bitflag + eh = numflag + + def ef (self, c): + """EF command -- close current output file, without any writing. + """ + self.buffer.ef () + + def eg (self, c): + """EG command -- OS dependent action. + + Right now this does nothing. + """ + cmd = self.strbuild (self.strarg (c)) + colon = self.colon () + # TODO: do something + if colon: + self.setval (0) + + def ei (self, c): + """EI command -- read command input from a file. + """ + fn = self.strbuild (self.strarg (c)) + colon = self.colon () + self.clearargs () + ret = self.teco.cmdhandler.ei (fn, colon) + if colon: + self.setval (ret) + + def ej (self, c): + """EJ command -- return environment parameters. + """ + n = self.getarg (c, 0) + if n == -1: + self.setval (CPU * 256 + OS) + elif n == 0: + # Don't return too big a number or some things get confused + # We use the parent pid, because that's fairly constant + # for a given session -- just like the "job" number for + # classic DEC operating systems. + self.setval (os.getppid () & 255) + elif n == 1: + self.setval (0) + elif n == 2: + self.setval (os.getuid ()) + else: + raise ARG (self.teco) + + def ek (self, c): + """EK command -- discard output file. + """ + self.buffer.ek () + + def en (self, c): + """EN command -- set wildcard pattern to match, or return + next match value. + """ + cmd = self.strbuild (self.strarg (c)) + colon = self.colon () + if len (cmd): + self.enlist = glob.glob (cmd) + self.enstring = cmd + elif self.enlist: + self.lastfilename = self.enlist[0] + del self.enlist[0] + if colon: + self.setval (-1) + else: + if colon: + self.setval (0) + else: + raise FNF (self.teco, self.enstring) + + def eo (self, c): + """EO command -- return TECO version number. + """ + self.setval (VERSION) + + def ep (self, c): + """EP command -- set alternate input stream. + """ + self.buffer.ep () + + def er (self, c): + """ER command -- open input file. + """ + fn = self.strbuild (self.strarg (c)) + colon = self.colon () + self.clearargs () + ret = self.buffer.er (fn, colon) + if colon: + self.setval (ret) + + es = numflag + et = bitflag + eu = numflag + ev = numflag + + def ew (self, c): + """EW command -- open output file. + """ + fn = self.strbuild (self.strarg (c)) + colon = self.colon () + self.clearargs () + ret = self.buffer.ew (fn, colon) + if colon: + self.setval (ret) + + def ex (self, c): + """EX command -- finish with files (effect of EC command) + then exit TECO. + """ + self.ec (c) + self.exit () + + def exit (self): + # Release the main thread, allowing it to start the display + global exiting + exiting = True + if dsem: + dsem.release () + sys.exit () + + def ey (self, c = None): + """EY command -- yank unconditionally. + """ + self.buffer.yank (False) + + def f (self, c): + """F command -- two character command starting with F. + """ + c = self.nextcmd () + try: + self.do ('f' + c) + except ILL: + raise IFC (self.teco, c) + + def fchar047 (self, c): # f' + """F' command -- 'flow' to end of conditional. + """ + self.clearargs () + self.skipcond ("'") + self.tracechar ("'") + + def fchar074 (self, c): # f< + """F< command -- 'flow' to start of iteration. Not like + 'continue' in C, it starts another iteration without + decrementing the count of iterations to do. + """ + if not self.iterstack: + raise BNI (self.teco) + self.iterstack[-1].again (False, 0) + + def fchar076 (self, c): # f> + """F> command -- 'flow' to end of iteration. Like + 'continue' in C, it decrements the count of iterations + left to do, and does another if there are any left. + """ + if not self.iterstack: + raise ExitLevel + self.iterstack[-1].again (False) + + def fb (self, c): + """FB command -- bounded search. + """ + s = self.strarg (c) + m, n, colon = self.getargsc (c) + if m is None: + m = self.dot + n = m + self.buffer.line (n) + count = 1 + if m > n: + count = -1 + m, n = n, m + self.search (s, count, m, n, colon, False) + + def fc (self, c): + """FC command -- bounded search and replace. + """ + s, rep = self.strargs (c) + m, n, colon = self.getargsc (c) + self.clearargs () + if m is None: + m = self.dot + n = m + self.buffer.line (n) + count = 1 + if m > n: + count = -1 + m, n = n, m + if self.search (s, count, m, n, colon, False): + self.buffer.goto (self.dot + self.laststringlen) + self.buffer.delete (-self.laststringlen) + self.buffer.insert (rep) + + def fr (self, c): + """FR command -- replace string previously matched or + inserted with the specified string. + """ + rep = self.strarg (c) + self.buffer.goto (self.dot + self.laststringlen) + self.buffer.delete (-self.laststringlen) + self.buffer.insert (rep) + + def fs (self, c): + """FS command -- search and replace. + """ + s, rep = self.strargs (c) + colons = self.colons + topiffail = colons < 2 + m, n, colon = self.getargsc (c, 1) + if not n: + raise ISA (self.teco) + if m == 0: + m = None + topiffail = False + if n < 0: + start, end = 0, self.dot + if m is not None: + start = end - abs (m) + else: + start, end = self.dot, self.end + if m is not None: + end = start + abs (m) + if colons > 1: + start = self.dot + end = self.dot + nextpage = None + if c == "fn": + nextpage = self.buffer.page + elif c == "f_": + nextpage = self.y + if self.search (s, n, start, end, colon, topiffail, nextpage): + self.buffer.goto (self.dot + self.laststringlen) + self.buffer.delete (-self.laststringlen) + self.buffer.insert (rep) + + fn = fs + fchar137 = fs # f_ + + def fchar174 (self, c): # f| + """F| command -- 'flow' to the Else part of a conditional. + Exits the condition if there isn't an else part. + """ + self.clearargs () + self.skipcond ("|'") + + def g (self, c): + """G command -- get text from the specified Q-register and + put it in the text buffer. Print the text if colon-modified. + Special name * means the last file spec, _ means the last + search string. + """ + c = self.peeknextcmd () + s = self.qregstr () + if self.colon (): + sys.stdout.write (s) + sys.stdout.flush () + self.screenok = False + else: + self.buffer.insert (s) + self.clearargs () + + def h (self, c): + """H command -- represents the wHole buffer. + Synonym for B,Z. + """ + self.clearargs () + self.arg2 = 0 + self.setval (self.end) + + def i (self,c): + """I command -- insert a string. If no string argument is + supplied, inserts the character whose numeric value is + given as the numeric argument. + """ + n = self.getarg (c) + s = self.strarg (c) + if len (s) == 0: + if n is not None: + s = chr (n) + elif n is not None: + raise IIA (self.teco) + self.buffer.insert (s) + self.clearargs () + + def j (self, c): + """J command -- move to the specified offset in the buffer. + """ + self.buffer.goto (self.getarg (c, 0)) + + def k (self, c): + """K command -- delete n lines. If two arguments are given, + delete the range of characters between those two positions. + """ + m, n = self.teco.lineargs (c) + self.buffer.goto (m) + self.buffer.delete (n - m) + self.clearargs () + + def l (self, c): + """L command -- move the specified number of lines. + """ + self.buffer.goto (self.buffer.line (self.getarg (c, 1))) + + def m (self, c): + """M command -- macro execution. Executes the TECO commands + in the specified Q-register. If colon-modified, the new + execution level gets its own set of local Q-registers + (ones whose names start with . ) -- otherwise the new level + shares the local Q-registers of the current level. + """ + q = self.qreg () + if self.colon (): + i = command_level (self.teco, self.qregs) + self.clearmods () + else: + i = command_level (self.teco) + i.run (q.getstr ()) + + def o (self, c): + """O command -- go to the specified tag in the command string. + If an argument is supplied, go to that tag in the list of tags + given in the string argument, e.g., 2Ofoo,bar,baz$ goes to + tag !baz!. If the argument is out of range, execution just + continues. + """ + tag = self.strbuild (self.strarg (c)) + n = self.getarg (c) + self.clearargs () + if not len (tag): + raise ILL (self.teco, c) + if n is not None: + n -= 1 + tags = tag.split (',') + if not 0 <= n < len (tags): + return + tag = tags[n] + if self.iterstack: + self.cmdpos = self.iterstack[-1].start + else: + self.cmdpos = 0 + self.findtag (tag) + + def p (self, c): + """P command -- page ahead the specified number of pages + in the input file, writing to the output file in the process. + + PW command -- write the current buffer to the output file. + """ + m, n, colon = self.getargsc (c, 1) + c2 = self.peeknextcmd ().lower () + if m is not None or c2 == 'w': + if c2 == 'w': + self.nextcmd () + if m is not None: + part = m, n + repeat = 1 + else: + part = None + repeat = n + if n <= 0: + raise IPA (self.teco) + for i in range (repeat): + self.buffer.writepage (part) + else: + if n <= 0: + raise IPA (self.teco) + for i in range (n): + ret = self.buffer.page () + if colon: + self.setval (ret) + + def q (self, c): + """Q command -- return the numeric value in the specified Q-register. + If an argument is given, return the ASCII value of the + character in the text part of the Q-register at the specified + offset (counting from zero). + """ + colon = self.colon () + n = self.getoptarg (c) + q = self.qreg () + if colon: + self.clearmods () + self.setval (len (q.getstr ())) + elif n is not None: + self.clearargs () + qstr = q.getstr () + if 0 <= n < len (qstr): + n = ord (qstr[n]) + else: + n = -1 + self.setval (n) + else: + self.clearmods () + self.setval (q.getnum ()) + + def r (self, c): + """R command -- move backward by the specified number of + character positions. + """ + newpos = self.dot - self.getarg (c, 1) + if 0 <= newpos <= self.end: + self.buffer.goto (newpos) + else: + raise POP (self.teco, c) + + def s (self, c): + """S command -- search for a string. If colon modified, + return -1 if ok, 0 if no match. If :: modified, it's a + match operation rather than a search (pointer never moves). + """ + s = self.strarg (c) + colons = self.colons + topiffail = colons < 2 + m, n, colon = self.getargsc (c, 1) + if not n: + raise ISA (self.teco) + if m == 0: + m = None + topiffail = False + if n < 0: + start, end = 0, self.dot + if m is not None: + start = end - abs (m) + else: + start, end = self.dot, self.end + if m is not None: + end = start + abs (m) + if colons > 1: + start = self.dot + end = start + nextpage = None + if c == "n": + nextpage = self.buffer.page + elif c == "_": + nextpage = self.y + elif c == "e_": + nextpage = self.ey + self.search (s, n, start, end, colon, topiffail, nextpage) + + echar137 = s # e_ + n = s + char137 = s # _ + + def t (self, c): + """T command -- type the specified number of lines. + """ + m, n = self.teco.lineargs (c) + sys.stdout.write (printable (self.buf[m:n])) + sys.stdout.flush () + self.screenok = False + self.clearargs () + + def u (self, c): + """U command -- set the numeric part of the Q-register + to the specified value. + """ + q = self.qreg () + q.setnum (self.getarg (c, NAU)) + + def v (self, c): + """V command -- display the current line, with n lines to each + side of it if argument n is supplied, or m before and n after + if argument pair m,n is given. + """ + m, n = self.getargs (c, 1) + start = self.buffer.line (1 - (m or n)) + end = self.buffer.line (n) + sys.stdout.write (printable (self.buf[start:end])) + sys.stdout.flush () + self.teco.screenok = False + + def w (self, c): + """W command -- watch the buffer contents. + + If wxPython is available, a wxPython window is opened showing + the current buffer around dot, which will be updated as the + buffer changes or dot moves, until further notice. 0W will + stop the display. + + If wxPython is not available but curses is, the buffer contents + will be displayed using screen control sequences on the current + terminal. It is updated only when another W command is issued. + + Also, in that mode, :W does lots of magical things; refer to + the manual for all the details. + """ + m, n, colon = self.getargsc (c) + if wxpresent: + if n is None: + self.teco.startdisplay () + elif n == 0: + self.teco.hidedisplay () + elif cursespresent: + if colon: + if n is None: + n = 0 + if n & -256: + # insert until... + if not n & 1: + self.teco.watch () + term = m and [ m & 255, m >> 8 ] + if n & 2: + m.append (9) + while True: + ch = screen.getch () + if ch == 3: + if self.etflag & 32768: + self.etflag &= -32768 + else: + raise XAB (self.teco) + if (n & 64) or \ + (ch != 9 and ch < 32) or ch > 126 or \ + (term and ch in term): + break + c = chr (ch) + if n & 4: + c = c.upper () + self.buffer.insert (c) + if not n & 32: + self.teco.watch () + self.setval (ch) + return + if not 0 <= n <= 7: + raise ARG (self.teco) + if m is None: + self.setval (self.teco.watchparams[n]) + else: + if n: + self.teco.watchparams[n] = m + else: + if n is None: + endwin () + else: + if n == 0: + n = 16 + if n > 0: + self.teco.curline = n + else: + if n == -1000: + self.screenok = True + self.teco.watch () + else: + raise ILL (self.teco, c) + + def x (self, c): + """X command -- set the text part of the specified Q-register + from text in the buffer. If one numeric argument is present, + that is a number of lines. If two arguments are given, it + is the range of character positions in the buffer. If colon- + modified, the new text is appended to the existing Q-register + contents rather than replacing it. + """ + colon = self.colon () + m, n = self.teco.lineargs (c) + q = self.qreg () + text = self.buf[m:n] + if colon: + q.appendstr (text) + else: + q.setstr (text) + self.clearargs () + + def y (self, c = None): + """Y command -- read the next page. If the buffer is not + empty, and there is an output file, refuse the operation unless + bit 1 is set in ED. + """ + self.buffer.yank ((self.edflag & 2) == 0) + + def z (self, c): + """Z command -- the number of characters in the buffer, or in + other words, the character position corresponding to the + end of the buffer. + """ + self.setval (self.end) + + def char133 (self, c): # [ + """[ command -- push the specified Q-register onto the + Q-register stack. + """ + # We have to make a copy of the Q register so that any later + # changes to the existing one are not also reflected in the + # pushed copy. A shallow copy suffices. + self.teco.qstack.append (copy.copy (self.qreg ())) + + def char134 (self, c): # \ + r"""\ command -- number/string conversion. + + If an argument is supplied, convert that according to the + current radix, and insert it into the buffer. Note that ^S + is not updated to reflect that insertion. + + If no argument is present, parse a number from the current + buffer position according to the current radix, and return that + number as a result. Dot is moved across whatever was parsed. + """ + n = self.getoptarg (c) + if n is None: + self.clearmods () + if self.radix == 8: + m = octre.match (self.buf, self.dot) + elif self.radix == 10: + m = decre.match (self.buf, self.dot) + else: + m = hexre.match (self.buf, self.dot) + if m is None: + n = 0 + else: + n = int (m.group (0), self.radix) + self.dot = m.end () + self.setval (n) + else: + self.clearargs () + if self.radix == 8: + s = "%o" % n + elif self.radix == 10: + s = "%d" % n + else: + s = "%x" % n + self.buffer.insert (s) + + def char135 (self, c): # ] + """] command -- pop the Q-register stack into the specified + Q-register. + """ + colon = self.colon () + if self.teco.qstack: + q = self.teco.qstack.pop () + self.setqreg (q) + if colon: + self.setval (-1) + elif colon: + self.nextcmd () + self.setval (0) + else: + raise PES (self.teco) + + def char136 (self, c): # ^ + """^ command -- take the next character as a control character, + for example '^S' is the same as 'control-S'. + """ + self.do (self.makecontrol (self.nextcmd ())) + + def char174 (self, c): # | + """| command -- marks the start of the 'else' part of + a conditional execution block. + """ + self.skipcond ("'") + +class inputstream (object): + def __init__ (self, teco): + self.teco = teco + self.pages = "" + self.eoflag = -1 + self.ffflag = 0 + self.infile = False + + def open (self, fn, colon): + fn = os.path.expanduser (fn) + try: + infile = open (fn, "rt", encoding = "utf8", errors = "ignore") + self.teco.lastfilename = fn + except IOError as err: + if colon: + return 0 + if err.errno == 2: + raise FNF (self.teco, fn) + else: + raise FER (self.teco) + try: + indata = infile.read () + except IOError: + raise INP (self.teco) + infile.close () + self.pages = indata.split (ff) + self.infile = True # input file is "open" + self.infn = fn + self.eoflag = 0 + return -1 + + def readpage (self): + if self.pages: + ret = self.pages[0].replace (lf, crlf) + del self.pages[0] + if len (self.pages): + self.ffflag = -1 + self.eoflag = 0 + else: + self.ffflag = 0 + self.eoflag = -1 + return ret, -1 + else: + self.ffflag = 0 + self.eoflag = -1 + return "", 0 + +class outputstream (object): + def __init__ (self, teco): + self.teco = teco + self.outfile = None + + def open (self, fn, colon, scheck = True): + if self.outfile: + raise OFO (self.teco) + fn = os.path.expanduser (fn) + if scheck and not fn.lower ().endswith (".tmp") and os.path.isfile (fn): + print('%%Superseding existing file "%s"' % fn) + fd, self.tempfn = tempfile.mkstemp (text = True) + try: + self.outfile = open (fd, "wt", encoding = "utf8", errors = "ignore") + self.teco.lastfilename = fn + except IOError as err: + if colon: + return 0 + raise FER (self.teco) + self.outfn = fn + return -1 + +class buffer (object): + '''This class defines the TECO text buffer, and methods to manipulate + its contents. + ''' + def __init__ (self, teco): + self.text = "" + self.dot = 0 + self.teco = teco + self.ebflag = False + self.inputs = [ None, None ] + self.istream = 0 + self.outputs = [ None, None ] + self.ostream = 0 + + laststringlen = commonprop ("laststringlen") + + def insert (self, text): + self.text = self.text[:self.dot] + text + self.text[self.dot:] + self.dot += len (text) + self.laststringlen = -len (text) + + def delete (self, len): + self.text = self.text[:self.dot] + self.text[self.dot + len:] + + def goto (self, pos): + if pos < 0: pos = 0 + if pos > len (self.text): pos = len (self.text) + self.dot = pos + + def _end (self): + return len (self.text) + + end = property (_end) + + def _ffflag (self): + infile = self.inputs[self.istream] + if infile: + return infile.ffflag + else: + return 0 + + ffflag = property (_ffflag) + + def _eoflag (self): + infile = self.inputs[self.istream] + if infile: + return infile.eoflag + else: + return -1 + + eoflag = property (_eoflag) + + def line (self, linecnt): + pos = self.dot + if linecnt > 0: + while linecnt > 0: + try: + pos = self.text.index (lf, pos) + 1 + except ValueError: + return len (self.text) + linecnt -= 1 + return pos + else: + while linecnt <= 0: + try: + pos = self.text.rindex (lf, 0, pos) + except ValueError: + return 0 + linecnt += 1 + return pos + 1 + + def ea (self): + self.ostream = 1 + + def eb (self, fn,colon): + if self.outputs[self.ostream]: + raise OFO (self.teco) + ret = self.er (fn, colon) + if ret == -1: + ret = self.ew (fn, colon, False) + if ret == -1: + self.ebflag = True + return ret + + def ec (self): + infile = self.inputs[self.istream] + outfile = self.outputs[self.ostream] + if outfile: + if infile: + while self.page () < 0: + pass + else: + self.writepage () + self.text = "" + self.ef () + elif self.end: + raise NFO (self.teco) + + def ef (self): + infile = self.inputs[self.istream] + self.inputs[self.istream] = None + outfile = self.outputs[self.ostream] + if outfile: + if self.ebflag: + try: + os.remove (infile.infn + '~') + except: + pass + os.rename (infile.infn, infile.infn + '~') + self.ebflag = False + outfile.outfile.close () + self.outputs[self.ostream] = None + os.rename (outfile.tempfn, outfile.outfn) + + def ek (self): + outfile = self.outputs[self.ostream] + if outfile: + outfile.outfile.close () + self.outputs[self.ostream] = None + os.remove (outfile.tempfn) + self.ebflag = False + + def ep (self): + self.istream = 1 + + def er (self, fn, colon): + """ This opens an input file, reads the whole file, and breaks it + into pages. + I suppose that isn't really all that elegant, but unless the + file is humongous, it's fast enough these days, and it produces + the correct result. + """ + if not len (fn): + self.istream = 0 + return True + if not self.inputs[self.istream]: + self.inputs[self.istream] = inputstream (self.teco) + return self.inputs[self.istream].open (fn, colon) + + def ew (self, fn, colon, scheck = True): + """This opens an output file. It creates the output file using + a temporary name, in the directory specified. The actual + desired name is saved, and will be set when the file is closed. + """ + if not len (fn): + self.ostream = 0 + return True + if not self.outputs[self.ostream]: + self.outputs[self.ostream] = outputstream (self.teco) + return self.outputs[self.ostream].open (fn, colon, scheck) + + def yank (self, protect = True): + """Read another page into the text buffer. If 'protect' is + True or omitted, the operation is rejected if there is an + output file and the buffer is non-empty. + Returns -1 if there was more data to read, 0 if we were + at end of file already. + """ + if protect and self.outputs[self.ostream] and self.text: + raise YCA (self.teco) + self.text = "" + ret = self.append () + self.goto (0) + return ret + + def append (self): + """Append another page to the text buffer. + """ + infile = self.inputs[self.istream] + if not infile: + raise NFI (self.teco) + newstr, ret = infile.readpage () + self.text += newstr + return ret + + def writepage (self, part = None): + outfile = self.outputs[self.ostream] + if not outfile: + raise NFO (self.teco) + if part: + start, end = part + outfile.outfile.write (self.text[start:end].replace (crlf, lf)) + else: + outfile.outfile.write (self.text.replace (crlf, lf)) + + def page (self): + """Write out the current page, and read the next. + """ + infile = self.inputs[self.istream] + outfile = self.outputs[self.ostream] + self.writepage () + if infile and infile.ffflag: + outfile.outfile.write (ff) + return self.yank (False) + +class command_handler (object): + '''Class for handling TECO input. + + It handles terminal input as well as input from EI files, + either single characters, or a complete TECO command with + the usual special character processing. + ''' + def __init__ (self, teco): + self.eifile = None + self.teco = teco + + etflag = commonprop ("et") + + def ei (self, fn, colon = False): + """EI file opener. + + If the supplied file name does not contain a directory spec, + we look for the file in several places. The list of places to + look is given by environment variable TECO_PATH, if defined, + or PATH, if that is defined, or else Python's built in + default path. The first match is used; if all choices fail + then the EI fails (with a return status of 0 if colon-modified, + or error FNF otherwise). + """ + if fn: + fn = os.path.expanduser (fn) + if self.eifile: + self.eifile.close () + f = None + if not os.path.dirname (fn): + fn + for d in (os.environ.get("TECO_PATH",None) or + os.environ.get("PATH",None) or + os.defpath).split(os.pathsep): + realfn = os.path.join (d, fn) + try: + f = open (realfn, "r", encoding = "utf8", + errors = "ignore") + break + except IOError as err: + if err.errno == 2: + pass + else: + raise FER (self.teco) + else: + try: + f = open (fn, "r", encoding = "utf8", errors = "ignore") + realfn = fn + except IOError as err: + if err.errno == 2: + pass + else: + raise FER (self.teco) + if f: + self.eifile = f + elif colon: + return 0 + else: + raise FNF (self.teco, fn) + else: + if self.eifile: + self.eifile.close () + self.eifile = None + return -1 + + def getch (self, trap_ctrlc = True): + if self.eifile: + try: + c = self.eifile.read (1) + except IOError: + self.eifile = None + raise INP (self.teco) + if len (c): + if c == lf: + c = cr + return c + self.eifile.close () + self.eifile = None + if screen and self.teco.incurses: + c = screen.getch () + if c < 256: + c = chr (c) + else: + c = '\000' + else: + c = getch () + if c == ctrlc and trap_ctrlc: + if self.etflag & 32768: + self.etflag &= 32767 + else: + raise XAB (self.teco) + if c == cr: + sys.stdout.write (crlf) + elif c != rubchr: + sys.stdout.write (printable (c)) + sys.stdout.flush () + return c + + def teco_cmdstring (self): + '''Get a command string using the TECO input conventions. + Text is accumulated until a double escape is seen. Control/U + and rubout are processed. Double control/G exits with a null + command (which will cause the main loop to prompt again). + ''' + buf = "" + bellflag = False + escflag = False + immediate = True + while True: + c = self.getch (False) + if not self.eifile: + # Most special characters are only special if they + # come from the terminal, not from an EI file. + if immediate: + if c in "\010\012?": + print() + return c + elif c == '*': + c = self.getch (False) + if c.isalnum (): + print() + return '*' + c + buf = '*' + immediate = False + if c == bell: + if bellflag: + print() + return "" + bellflag = True + elif bellflag: + bellflag = False + if c == ' ': + buf = buf[:-1] + try: + start = buf.rindex (lf) + except ValueError: + start = 0 + print() + sys.stdout.write (printable (buf[start:])) + sys.stdout.flush () + continue + elif c == '*': + buf = buf[:-1] + print() + sys.stdout.write (printable (buf)) + sys.stdout.flush () + continue + if c == ctrlu: + print() + try: + ls = buf.rindex (lf) + buf = buf[:ls + 1] + except ValueError: + buf = "" + continue + elif c == rubchr: + if len (buf): + sys.stdout.write ("\010 \010") + if ord (buf[-1]) < 32 and buf[-1] != esc: + sys.stdout.write ("\010 \010") + buf = buf[:-1] + sys.stdout.flush () + continue + if c == esc: + buf += c + if escflag: + if not self.eifile: + print() + return buf + escflag = True + continue + else: + escflag = False + if c == cr: + buf += crlf + else: + buf += c + +# Here's a rather primitive (but functional) teco command handler. +# This one is used if we can't find a teco.tec anywhere. +defmacro = \ +"""0ed 0^x ^d z"e @o/end/' j +::@s/tec/"s 0u1 :@s*/i*"s -1u1 @fr// <::@s/^ea/; @fr//>' +j :@s/^es/"f hk @o/end/' b,.k :@s/=/"f hx1 hk +q1"f @eb/^eq1/ y @o/end/' +@er/^eq1/ y @o/end/' +@fr// .,zx1 @er/^eq1/ b,.x1 @ew/^eq1/ hk y @o/end/' +::@s/mun/"s :@s/^es/"f @^a/?How can I MUNG nothing? +/ ^c' b,.k :@s/,/"s @fr// 1+' 0"e zj' b,.x1 b,.k @ei/^eq1/ @o/end/' +::@s/mak/"f @^a/?Illegal command "/ ht @^a/" +/ ^c' :@s/^es/"f @^a/?How can I MAKE nothing? +/ ^c' b,.k z-4"e ::@s/love/"s @^a/Not war? +/ j'' hx1 hk @ew/^eq1/' +!end!""" + +def main (): + global t + t = teco () + arg0 = os.path.basename (sys.argv[0]).lower () + if arg0.endswith (".py"): + arg0 = arg0[:-3] + elif arg0.endswith (".pyc"): + arg0 = arg0[:-4] + cmdline = " ".join ([ arg0 ] + sys.argv[1:]) + t.buf = cmdline + if wxpresent: + # Need to create a new thread for interaction, then this + # (main) thread will own the window. + thr = threading.Thread (target = main2) + thr.start () + global display, dsem + dsem = threading.Semaphore (value = 0) + # Wait for someone to ask for a display + dsem.acquire () + if exiting: + return + # Now start the display + display = displayApp (t) + display.start () + else: + main2 () + +def main2 (): + #t.trace = True # *** for debug + if not t.cmdhandler.ei ("teco.tec", True): + try: + t.runcommand (defmacro) + except err as e: + e.show () + t.mainloop () + +if __name__ == "__main__": + main ()