The BEST QL Editor
- Derek_Stewart
- Font of All Knowledge
- Posts: 4869
- Joined: Mon Dec 20, 2010 11:40 am
- Location: Sunny Runcorn, Cheshire, UK
Re: The BEST QL Editor
Hi,
If the Pointer System is so bad, then what should I be using?
If the Pointer System is so bad, then what should I be using?
Regards, Derek
Re: The BEST QL Editor
The software from many called Pointer Interface (this is just the part which allows for a mouse pointer and none destructable windows) is since Qpac2 the Extended Environment and includes the Pointer Interface, Wman (Window Manager) which allows sub windows etc., the Thing system AND the Hotkey System (Great). This all plays together and it is GREAT!
Of course it is different from all currently used GUIs. But that's okay. The Exteded Environment has been implemented when GUIs where invented. Tony Tebby has had another approach, which is IMHO better, than the GUIs you are using (must use) nowadays. E.g. the Hit (left mouse button) and Do (right mouse button). With Do normally a menu pops up, as if you e.g. click the right mouse button in the Windows File Explorer, i.e. a (now called) context menu. I have seen this first on the QL, Windows have had this feature (for some programs) 1 or 2 years later. But it's even better: If you do a Hit in a menu of a Qpac2 program (menu), the menu stays open and the other program starts. If you do a Do, the current Qpac2 menu, the menu disappears, and the menu you have clicked opens.
Then there's the excellent HOT_KEY system (ERT HOT_KEY(...)) with it's hotkey stuffer!!! Have you ever tried to get the full pathname of a file listed in the File Explorer of Windows(!). In the Files menu of QPac2 you just have to click on the file (directory) and you can insert the full pathname with <ALT>–<SPACE> (and the one before with <SHIFT>–<ALT>–<SPACE>!) in any prompt of a program, which requires a file name. That's the reason, why I normally do not use (need) Jochen Merz's file chooser extension (I can do it IMHO more easy with the Files menu).
Of course it is different from all currently used GUIs. But that's okay. The Exteded Environment has been implemented when GUIs where invented. Tony Tebby has had another approach, which is IMHO better, than the GUIs you are using (must use) nowadays. E.g. the Hit (left mouse button) and Do (right mouse button). With Do normally a menu pops up, as if you e.g. click the right mouse button in the Windows File Explorer, i.e. a (now called) context menu. I have seen this first on the QL, Windows have had this feature (for some programs) 1 or 2 years later. But it's even better: If you do a Hit in a menu of a Qpac2 program (menu), the menu stays open and the other program starts. If you do a Do, the current Qpac2 menu, the menu disappears, and the menu you have clicked opens.
Then there's the excellent HOT_KEY system (ERT HOT_KEY(...)) with it's hotkey stuffer!!! Have you ever tried to get the full pathname of a file listed in the File Explorer of Windows(!). In the Files menu of QPac2 you just have to click on the file (directory) and you can insert the full pathname with <ALT>–<SPACE> (and the one before with <SHIFT>–<ALT>–<SPACE>!) in any prompt of a program, which requires a file name. That's the reason, why I normally do not use (need) Jochen Merz's file chooser extension (I can do it IMHO more easy with the Files menu).
http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX

Re: The BEST QL Editor
I didn't realize this was over 40 years old. I thought it was created in the 90s, not early 80s. Did Tony create it at the same time as TK2?ql_freak wrote: Sat Sep 20, 2025 1:15 am The Exteded Environment has been implemented when GUIs where invented.
- Derek_Stewart
- Font of All Knowledge
- Posts: 4869
- Joined: Mon Dec 20, 2010 11:40 am
- Location: Sunny Runcorn, Cheshire, UK
Re: The BEST QL Editor
Hi,
I am sorry to imply that I did not know what the Pointer System is, which I meant: PTR_GEN, WMAN, HOT_REXT, and QPAC2, which make it The Extended Environment.
I used all this since Qjump introduced QRAM, which I bought and he update QPAC2, which included the Pointer System. This is all free now.
If I want to use a GUI system on the QL, there is only one option - The Pointer System and QPAC2, QD, QMENU, QBASIC which makes the QL a nice GUI based system in less than 512K or ram, no other system can do this.
The best non GUI editor in my opinion is QED, and maybe TheEDitorSE a close second. GUI Editors, QD, I can not think of any other
But then all the software is free, so have it all and decide which is our best option.
Again my question is, if the Pointer System written by Tony Tebby, is so bad, as he seemed to write good software. What should I be using?
I am sorry to imply that I did not know what the Pointer System is, which I meant: PTR_GEN, WMAN, HOT_REXT, and QPAC2, which make it The Extended Environment.
I used all this since Qjump introduced QRAM, which I bought and he update QPAC2, which included the Pointer System. This is all free now.
If I want to use a GUI system on the QL, there is only one option - The Pointer System and QPAC2, QD, QMENU, QBASIC which makes the QL a nice GUI based system in less than 512K or ram, no other system can do this.
The best non GUI editor in my opinion is QED, and maybe TheEDitorSE a close second. GUI Editors, QD, I can not think of any other
But then all the software is free, so have it all and decide which is our best option.
Again my question is, if the Pointer System written by Tony Tebby, is so bad, as he seemed to write good software. What should I be using?
Regards, Derek
Re: The BEST QL Editor
Digging a bit in memory and old paperwork:
Its first incarnation came with QRAM, and that should have been 1987 or 1988 - So, not quite 40 years old. But to establish itself from a GUI toolkit that drove QJump programs to the publicly accepted WIMP for the QL took another, like 3-5 years. I can't just now find the first release date of the QPTR toolkit that provided the API to third-party developers.
TK2 is a different story - that entered the market as early as 1985, one year after the launch.
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: The BEST QL Editor
I dont know when QPTR was first released to the public, but from the original source code (V0.00) it looks like QJump's JR Oakley wrote most of it back in 1987.tofro wrote: Sat Sep 20, 2025 7:45 amDigging a bit in memory and old paperwork:
Its first incarnation came with QRAM, and that should have been 1987 or 1988 - So, not quite 40 years old. But to establish itself from a GUI toolkit that drove QJump programs to the publicly accepted WIMP for the QL took another, like 3-5 years. I can't just now find the first release date of the QPTR toolkit that provided the API to third-party developers.
<>
Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
Re: The BEST QL Editor
The first ad for QPTR was published in QL-World in May 1987.pjw wrote: Sat Sep 20, 2025 8:35 amI dont know when QPTR was first released to the public, but from the original source code (V0.00) it looks like QJump's JR Oakley wrote most of it back in 1987.
And yes, QPTR was written by Jonathan Oakley; in retrospect, some things could certainly have been done differently and more simply. Apart from Wolfgang Lenerz, I don't know anyone who uses QPTR. I used it once and found it extremely confusing and complicated. Never again. QPTR was certainly well-intentioned, but from a commercial perspective, I think it was a disaster. Jonathan Oakley probably spent weeks if not months on it.
As I gathered from my letters from TT, the Pointer Interface came first; the Window Manager came much later and, theoretically, isn't necessary for simpler things. TT hasn't commented on whether this was already started under Sinclair (although I've asked several times).
Would TT do the Pointer Environment the same way again today? After all, some things were changed before the initial release. For example, in the beginning, the secondaries could be located outside the primary. That would be very nice these days and is common practice with other GUIs.
The new abbreviations (e.g. SMS.INFO vs. MT.INF) are already present in the source files of the Pointer Environment and QPTR. This suggests that the SMS kernel was either finished very early (1985) or that someone took the trouble to replace the abbreviations everywhere, which would have been a huge task if it wasn't done automatically.
BTW: The pointer interface (ptr_gen) was changed and expanded every few weeks during the QRAM era. That's why I never understood why Sandy put it into the EPROM of his SuperQBoard/Mouse. Even the first QRAM version shipped with the SQB had a more up-to-date ptr_gen. So you had to load it anyway. At least that's how it was with my SQB.
7000 4E75
Re: The BEST QL Editor
Can you remember the filename of it? I'll have a look.NormanDunbar wrote: Fri Sep 19, 2025 5:11 pmThere is indeed. I have one but as I literally moved house a couple of days ago, I know not where it is!SandySuperQDave wrote:My actual question: Is there a list of S*BASIC tokens anywhere?
Somewhere, I have a program written in Super basic to decide a QSaved file back into plain text. That file, which is well commented, should give you all the token details you need.
Sorry Im not much help here, I do know Dilwyn updated it to cope with the new Binary and Hexadecimal floating point values, perhaps he can help?
Cheers,
Norm.
Page 198 of the Jan Jones SuperBASIC book, after floating point format tokens, I have the following handwritten:
* HEX values: six bytes $E masked into top four bits
* BIN values: six bytes $D masked into top four bits
* stored as floating point, but withtop 4 bits changed to indicate HEX or BINary values.
--
All things QL - https://dilwyn.theqlforum.com
All things QL - https://dilwyn.theqlforum.com
Re: The BEST QL Editor
Possibly this - looks like it needs Norman's DJtoolkit:dilwyn wrote: Sat Sep 20, 2025 11:45 amCan you remember the filename of it? I'll have a look.NormanDunbar wrote: Fri Sep 19, 2025 5:11 pmThere is indeed. I have one but as I literally moved house a couple of days ago, I know not where it is!SandySuperQDave wrote:My actual question: Is there a list of S*BASIC tokens anywhere?
Somewhere, I have a program written in Super basic to decide a QSaved file back into plain text. That file, which is well commented, should give you all the token details you need.
Sorry Im not much help here, I do know Dilwyn updated it to cope with the new Binary and Hexadecimal floating point values, perhaps he can help?
Cheers,
Norm.
Page 198 of the Jan Jones SuperBASIC book, after floating point format tokens, I have the following handwritten:
* HEX values: six bytes $E masked into top four bits
* BIN values: six bytes $D masked into top four bits
* stored as floating point, but withtop 4 bits changed to indicate HEX or BINary values.
Code: Select all
100 REMark _SAV file decoder
110 :
120 CLS
130 PRINT 'SAV File Decoder'\\
140 INPUT 'Which _sav file ? ';sav$
150 IF sav$ = '' THEN STOP: END IF
160 :
170 initialise
180 decode_header
190 IF NOT _quit
200 decode_name_table
210 decode_program
220 END IF
230 RELEASE_HEAP float_buffer
240 CLOSE #3
250 :
260 DEFine PROCedure decode_header
270 LOCal head$(4), name_table_length
280 _quit = 0
290 OPEN_IN #3,sav$
300 head$ = FETCH_BYTES(#3, 4)
310 IF (head$ <> 'Q1' & CHR$(0) & CHR$(0)) AND (head$ <> 'Q1' & CHR$(2) & CHR$(192)) AND (head$ <> 'Q1'& CHR$(3) & CHR$(128))
320 PRINT head$, head$(1);head$(2)!!CODE(head$(3))!CODE(head$(4))\
330 PRINT sav$ & ' is not a SAV file, or has a new flag.'
340 CLOSE #3
350 _quit = 1
360 RETurn
370 END IF
380 name_table_entries = GET_WORD(#3)
390 name_table_length = GET_WORD(#3)
400 program_lines = GET_WORD(#3)
410 max_name_size = name_table_length - (4 * name_table_entries) / name_table_entries
420 :
430 PRINT sav$
440 PRINT 'Number of name table entries : '; name_table_entries
450 PRINT 'Name table length : '; name_table_length
460 PRINT 'Number of program lines : '; program_lines
470 PRINT
480 :
490 DIM name_table$(name_table_entries -1, max_name_size)
500 float_buffer = RESERVE_HEAP(6)
510 _quit = (float_buffer < 1)
520 END DEFine decode_header
530 :
540 DEFine PROCedure decode_name_table
550 LOCal x, name_type, line_no, name_length, name$, lose_it$(1)
560 LOCal num_procs, num_fns
570 num_procs = 0
580 num_fns = 0
590 FOR x = 0 TO name_table_entries -1
600 name_type = GET_WORD(#3)
610 line_no = GET_WORD(#3)
620 name_length = GET_WORD(#3)
630 name$ = FETCH_BYTES(#3, name_length)
640 IF name_length && 1
650 lose_it$ = INKEY$(#3)
660 END IF
670 IF name_type = 5122 THEN num_procs = num_procs + 1
680 IF name_type >= 5377 AND name_type <= 5379
690 num_fns = num_fns + 1
700 END IF
710 PRINT x;' Name type = '; HEX$(name_type, 16) & ' ';
720 PRINT 'Line number = '; line_no & ' ';
730 PRINT 'Name length = '; name_length; ' ';
740 PRINT 'Name = <' & name$ & '>'
750 name_table$(x) = name$
760 END FOR x
770 PRINT 'There are ' & num_procs & ' PROCs'
780 PRINT 'There are ' & num_fns & ' FNs'
790 END DEFine decode_name_table
800 :
810 :
820 DEFine PROCedure decode_program
830 LOCal x, type_byte, program_line
840 :
850 REMark WORD = size change
860 REMark LONG = $8D00.line number
870 REMark rest of line
880 :
890 REPeat program_line
900 IF EOF(#3) THEN EXIT program_line: END IF
910 line_size = line_size + GET_WORD(#3)
920 IF line_size > 65536 THEN line_size = line_size - 65536: END IF
930 IF GET_WORD(#3) <> HEX('8d00')
940 PRINT 'Program out of step.'
950 CLOSE #3
960 STOP
970 END IF
980 PRINT GET_WORD(#3); ' ';
990 line_done = 0
1000 REPeat line_contents
1010 type_byte = CODE(INKEY$(#3))
1020 SELect ON type_byte
1030 = HEX('80'): multi_spaces
1040 = HEX('81'): keywords
1050 = HEX('84'): symbols
1060 = HEX('85'): operators
1070 = HEX('86'): monadics
1080 = HEX('88'): names
1090 = HEX('8B'): strings
1100 = HEX('8C'): text
1110 = HEX('8E'): separators
1120 = HEX('D0') TO HEX('DF') : floating_points 1 : REMark % binary number
1130 = HEX('E0') TO HEX('EF') : floating_points 2 : REMark $ hex number
1140 = HEX('F0') TO HEX('FF') : floating_points 3 : REMark floating point
1150 END SELect
1160 IF line_done THEN EXIT line_contents: END IF
1170 END REPeat line_contents
1180 END REPeat program_line
1190 END DEFine decode_program
1200 :
1210 :
1220 DEFine PROCedure multi_spaces
1230 :
1240 REMark $80.nn = print nn spaces
1250 :
1260 PRINT FILL$(' ', GET_BYTE(#3));
1270 END DEFine multi_spaces
1280 :
1290 :
1300 DEFine PROCedure keywords
1310 :
1320 REMark $81.nn = keyword$(nn)
1330 :
1340 PRINT keyword$(GET_BYTE(#3));' ';
1350 END DEFine keywords
1360 :
1370 :
1380 DEFine PROCedure symbols
1390 LOCal sym
1400 :
1410 REMark $84.nn = symbol$(nn)
1420 :
1430 sym = GET_BYTE(#3)
1440 PRINT symbol$(sym);
1450 line_done = (sym = 10)
1460 END DEFine symbols
1470 :
1480 :
1490 DEFine PROCedure operators
1500 :
1510 REMark $85.nn = operator$(nn)
1520 :
1530 PRINT operator$(GET_BYTE(#3));
1540 END DEFine operators
1550 :
1560 :
1570 DEFine PROCedure monadics
1580 :
1590 REMark $86.nn = monadic$(nn)
1600 :
1610 PRINT monadic$(GET_BYTE(#3));
1620 END DEFine monadic
1630 :
1640 :
1650 DEFine PROCedure names
1660 LOCal ignore
1670 :
1680 REMark $8800.nnnn = name_table$(nnnn)
1690 :
1700 ignore = GET_BYTE(#3)
1710 ignore = GET_WORD(#3)
1720 IF ignore > 32768 THEN ignore = ignore - 32768: END IF
1730 PRINT name_table$(ignore);
1740 END DEFine names
1750 :
1760 :
1770 DEFine PROCedure strings
1780 LOCal delim$(1), size
1790 :
1800 REMark $8B.delim.string_size = 'delim'; string; 'delim'
1810 :
1820 delim$ = INKEY$(#3)
1830 size = GET_WORD(#3)
1840 PRINT delim$; FETCH_BYTES(#3, size); delim$;
1850 IF size && 1
1860 size = GET_BYTE(#3)
1870 END IF
1880 END DEFine strings
1890 :
1900 :
1910 DEFine PROCedure text
1920 LOCal size
1930 :
1940 REMark $8C00.size = text
1950 :
1960 size = GET_BYTE(#3)
1970 size = GET_WORD(#3)
1980 PRINT FETCH_BYTES(#3, size);
1990 IF size && 1
2000 size = GET_BYTE(#3)
2010 END IF
2020 END DEFine text
2030 :
2040 :
2050 DEFine PROCedure separators
2060 :
2070 REMark $8E.nn = separator$(nn)
2080 :
2090 PRINT separator$(GET_BYTE(#3));
2100 END DEFine separators
2110 :
2120 :
2130 DEFine PROCedure floating_points (fp_type)
2140 REMark modified for % and $ SBASIC values 22.01.10 - DJ
2150 LOCal number$(6),fpt
2160 fpt = fp_type : REMark to avoid SEL ON last parameter issue later
2170 :
2180 REMark fp_type=...
2190 REMark $Dx.xx.xx.xx.xx.xx - %binary number
2200 REMark $Ex.xx.xx.xx.xx.xx - $hex number
2210 REMark $Fx.xx.xx.xx.xx.xx - need to mask out the first $F !
2220 :
2230 MOVE_POSITION #3, -1: REMark back up to the first byte
2240 number$ = FETCH_BYTES(#3, 6)
2250 number$(1) = CHR$( CODE(number$(1)) && 15)
2260 POKE_STRING float_buffer, number$
2270 SELect ON fpt
2280 =1 : PRINT '%';LTrim$(BIN$(PEEK_FLOAT(float_buffer),32));
2290 =2 : PRINT '$';LTrim$(HEX$(PEEK_FLOAT(float_buffer),32));
2300 =3 : PRINT PEEK_FLOAT(float_buffer);
2310 END SELect
2320 END DEFine floating_points
2330 :
2340 DEFine FuNction LTrim$(str$)
2350 REMark added 22.01.10 for % and $ values - DJ
2360 REMark remove leading zeros from binary or hex strings
2370 LOCal a,t$
2380 t$ = str$ : REMark full length by default
2390 FOR a = 1 TO LEN(t$)
2400 IF t$(a) <> '0' THEN t$ = t$(a TO LEN(t$)) : EXIT a
2410 NEXT a
2420 t$ = '0' : REMark in case it was all zeros
2430 END FOR a
2440 RETurn t$
2450 END DEFine LTrim$
2460 :
2470 DEFine PROCedure initialise
2480 LOCal x
2490 :
2500 _quit = 0
2510 last_line_size = 0
2520 line_size = 0
2530 name_table_entries = 0
2540 :
2550 RESTORE 2580
2560 DIM keyword$(31, 9)
2570 FOR x = 1 TO 31: READ keyword$(x): END FOR x
2580 DATA 'END', 'FOR', 'IF', 'REPeat', 'SELect', 'WHEN', 'DEFine'
2590 DATA 'PROCedure', 'FuNction', 'GO', 'TO', 'SUB', '', 'ERRor', ''
2600 DATA '', 'RESTORE', 'NEXT', 'EXIT', 'ELSE', 'ON', 'RETurn'
2610 DATA 'REMAINDER', 'DATA', 'DIM', 'LOCal', 'LET', 'THEN', 'STEP'
2620 DATA 'REMark', 'MISTake'
2630 :
2640 DIM symbol$(10)
2650 symbol$ = '=:#,(){} ' & CHR$(10)
2660 :
2670 DIM operator$(22, 5)
2680 FOR x = 1 TO 22: READ operator$(x): END FOR x
2690 DATA '+', '-', '*', '/', '>=', '>', '==', '=', '<>', '<=', '<'
2700 DATA '||', '&&', '^^', '^', '&', 'OR', 'AND', 'XOR', 'MOD'
2710 DATA 'DIV', 'INSTR'
2720 :
2730 DIM monadic$(4, 3)
2740 FOR x = 1 TO 4: READ monadic$(x): END FOR x
2750 DATA '+', '-', '~~', 'NOT'
2760 :
2770 DIM separator$(5, 2)
2780 FOR x = 1 TO 5: READ separator$(x): END FOR x
2790 DATA ',', ';', '\', '!', 'TO'
2800 :
2810 END DEFine initialise
2820 :
Last edited by dilwyn on Sat Sep 20, 2025 1:31 pm, edited 1 time in total.
Reason: Added note program needs DJtoolkit.
Reason: Added note program needs DJtoolkit.
--
All things QL - https://dilwyn.theqlforum.com
All things QL - https://dilwyn.theqlforum.com
Re: The BEST QL Editor
dilwyn wrote: Sat Sep 20, 2025 11:45 amQDOS/SMSQE Reference manual, page 18-11:NormanDunbar wrote: Fri Sep 19, 2025 5:11 pmSandySuperQDave wrote:My actual question: Is there a list of S*BASIC tokens anywhere?
Page 198 of the Jan Jones SuperBASIC book, after floating point format tokens, I have the following handwritten:
* HEX values: six bytes $E masked into top four bits
* BIN values: six bytes $D masked into top four bits
* stored as floating point, but withtop 4 bits changed to indicate HEX or BINary values.
Code: Select all
18.5.2. BASIC Token Values The following Section defines the token values used for the internal storage of a S*Basic program. tkb.space $80 spaces in the listing - two bytes: token, count tkw.keyw $81 all sorts of keywords: tkw.end $8101 END tkw.for $8102 FOR tkw.if $8103 IF tkw.rep $8104 REPeat tkw.sel $8105 SELect tkw.when $8106 WHEN tkw.def $8107 DEFine tkw.proc $8108 PROCedure tkw.fn $8109 FuNction tkw.go $810A GO tkw.to $810B TO tkw.sub $810C SUB tkw.err $810E ERRor tkw.rest $8111 RESTORE tkw.next $8112 NEXT tkw.exit $8113 EXIT tkw.else $8114 ELSE tkw.on $8115 ON tkw.ret $8116 RETurn tkw.rmdr $8117 REMAINDER tkw.data $8118 DATA tkw.dim $8119 DIM tkw.loc $811A LOCal tkw.let $811B LET tkw.then $811C THEN tkw.step $811D STEP tkw.rem $811E REMark tkw.mist $811F MISTake tkb.odds $84 All sorts of separators: tkw.lequ $8401 (LET) = tkw.coln $8402 : tkw.hash $8403 # tkw.comma $8404 , tkw.lpar $8405 ( QDOS/SMS Reference Manual v. 4.9 31.03.2025 Section 18 - 9 tkw.rpar $8406 ) tkw.lbrc $8407 { tkw.rbrc $8408 } tkw.space $8409 Space (significant) tkw.eol $840A End of line tkb.oper $85 All sorts of operators: tkw.plus $8501 + tkw.minus $8502 - tkw.mulf $8503 * tkw.divf $8504 / tkw.ge $8505 >= tkw.gt $8506 > tkw.apeq $8507 == tkw.eq $8508 = tkw.ne $8509 <> tkw.le $850A <= tkw.lt $850B < tkw.bor $850C tkw.band $850D && tkw.bxor $850E ^^ tkw.power $850F ^ tkw.cnct $8510 & tkw.or $8511 OR tkw.and $8512 AND tkw.xor $8513 XOR tkw.mod $8514 MOD tkw.div $8515 DIV tkw.instr $8516 INSTR tkw.neg $8601 Negate tkw.pos $8602 Positive!! tkw.bnot $8603 ~~ tkw.not $8604 ~ tkb.name $8800 Name: The name token is followed by a word index to the name table tkw.quote $8B22 String delimited by "quotes" tkw.apost $8B27 String delimited by 'apostrophes' tkw.text $8C00 Text (after REMark)The string and text tokens are followed by a word (nr. of chars) and the characters (with a pad byte if odd) tkb.lno $8D00 line number (word) tkb.seps $8E All sorts of formatting separators: tkw.scoma $8E01 Separator comma tkw.scoln $8E02 Semicolon tkw.bslsh $8E03 Backslash tkw.bar $8E04 Bar tkw.sto $8E05 Separator TO
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO