version 1.5, 2004/12/27 20:05:53
|
version 1.9, 2004/12/31 11:01:21
|
Line 20
|
Line 20
|
|
|
\ short: u8 means utf-8 encoded address |
\ short: u8 means utf-8 encoded address |
|
|
|
s" malformed UTF-8 character" exception Constant UTF-8-err |
|
|
: u8len ( u8 -- n ) |
: u8len ( u8 -- n ) |
dup $80 u< IF drop 1 EXIT THEN \ special case ASCII |
dup $80 u< IF drop 1 EXIT THEN \ special case ASCII |
$800 2 >r |
$800 2 >r |
Line 31
|
Line 33
|
$7F and $40 >r |
$7F and $40 >r |
BEGIN dup r@ and WHILE r@ xor |
BEGIN dup r@ and WHILE r@ xor |
6 lshift r> 5 lshift >r >r count |
6 lshift r> 5 lshift >r >r count |
\ dup $C0 and $80 <> abort" malformed character" |
dup $C0 and $80 <> IF UTF-8-err throw THEN |
$3F and r> or |
$3F and r> or |
REPEAT rdrop ; |
REPEAT rdrop ; |
|
|
Line 43
|
Line 45
|
REPEAT $7F xor 2* or r> |
REPEAT $7F xor 2* or r> |
BEGIN over $80 u>= WHILE tuck c! 1+ REPEAT nip ; |
BEGIN over $80 u>= WHILE tuck c! 1+ REPEAT nip ; |
|
|
|
\ plug-in so that char and '<char> work for UTF-8 |
|
|
|
[ifundef] char@ \ !! bootstrapping help |
|
Defer char@ ( addr u -- char addr' u' ) |
|
:noname over c@ -rot 1 /string ; IS char@ |
|
[then] |
|
|
|
:noname ( addr u -- char addr' u' ) |
|
\ !! the if here seems to work around some breakage, but not |
|
\ entirely; e.g., try 'ç' with LANG=C. |
|
dup 1 u<= IF defers char@ EXIT THEN |
|
over + >r u8@+ swap r> over - ; IS char@ |
|
|
\ scan to next/previous character |
\ scan to next/previous character |
|
|
: u8>> ( u8addr -- u8addr' ) |
: u8>> ( u8addr -- u8addr' ) |
Line 57
|
Line 72
|
$7F and $40 >r |
$7F and $40 >r |
BEGIN dup r@ and WHILE r@ xor |
BEGIN dup r@ and WHILE r@ xor |
6 lshift r> 5 lshift >r >r defers key |
6 lshift r> 5 lshift >r >r defers key |
\ dup $C0 and $80 <> abort" malformed character" |
dup $C0 and $80 <> IF UTF-8-err throw THEN |
$3F and r> or |
$3F and r> or |
REPEAT rdrop ; |
REPEAT rdrop ; |
|
|
Line 71
|
Line 86
|
|
|
\ input editor |
\ input editor |
|
|
: save-cursor ( -- ) 27 emit '7 emit ; |
[IFUNDEF] #esc 27 Constant #esc [THEN] |
: restore-cursor ( -- ) 27 emit '8 emit ; |
|
|
: save-cursor ( -- ) #esc emit '7 emit ; |
|
: restore-cursor ( -- ) #esc emit '8 emit ; |
: .rest ( addr pos1 -- addr pos1 ) |
: .rest ( addr pos1 -- addr pos1 ) |
restore-cursor 2dup type ; |
restore-cursor 2dup type ; |
: .all ( span addr pos1 -- span addr pos1 ) |
: .all ( span addr pos1 -- span addr pos1 ) |
restore-cursor >r 2dup swap type r> ; |
restore-cursor >r 2dup swap type r> ; |
|
|
: <u8ins> ( max span addr pos1 u8char -- max span addr pos2 ) |
: <u8ins> ( max span addr pos1 u8char -- max span addr pos2 ) |
>r >string over r@ u8len + swap move 2dup chars + r@ swap u8!+ drop |
>r 2over r@ u8len + u< IF rdrop bell EXIT THEN |
|
>string over r@ u8len + swap move 2dup chars + r@ swap u8!+ drop |
r> u8len >r rot r@ chars + -rot r> chars + ; |
r> u8len >r rot r@ chars + -rot r> chars + ; |
: (u8ins) ( max span addr pos1 u8char -- max span addr pos2 ) |
: (u8ins) ( max span addr pos1 u8char -- max span addr pos2 ) |
<u8ins> .all .rest ; |
<u8ins> .all .rest ; |
: u8back ( max span addr pos1 -- max span addr pos2 f ) |
: u8back ( max span addr pos1 -- max span addr pos2 f ) |
dup IF over + u8<< over - 0 max .all .rest |
dup IF over + u8<< over - 0 max .all .rest |
ELSE #bell emit THEN 0 ; |
ELSE bell THEN 0 ; |
: u8forw ( max span addr pos1 -- max span addr pos2 f ) |
: u8forw ( max span addr pos1 -- max span addr pos2 f ) |
2 pick over <> IF over + u8@+ u8emit over - ELSE #bell emit THEN 0 ; |
2 pick over <> IF over + u8@+ u8emit over - ELSE bell THEN 0 ; |
: (u8del) ( max span addr pos1 -- max span addr pos2 ) |
: (u8del) ( max span addr pos1 -- max span addr pos2 ) |
over + dup u8<< tuck - >r over - |
over + dup u8<< tuck - >r over - |
>string over r@ + -rot move |
>string over r@ + -rot move |
Line 97
|
Line 115
|
: <u8del> ( max span addr pos1 -- max span addr pos2 0 ) |
: <u8del> ( max span addr pos1 -- max span addr pos2 0 ) |
2 pick over <> |
2 pick over <> |
IF u8forw drop (u8del) .all 2 spaces .rest |
IF u8forw drop (u8del) .all 2 spaces .rest |
ELSE #bell emit THEN 0 ; |
ELSE bell THEN 0 ; |
: u8eof 2 pick over or 0= IF bye ELSE <u8del> THEN ; |
: u8eof 2 pick over or 0= IF bye ELSE <u8del> THEN ; |
|
|
: u8first-pos ( max span addr pos1 -- max span addr 0 0 ) |
: u8first-pos ( max span addr pos1 -- max span addr 0 0 ) |