1\ extended characters (either 8bit or UTF-8, possibly other encodings)
2\ and their fixed-size variant
3
4\ Copyright (C) 2005,2006,2007 Free Software Foundation, Inc.
5
6\ This file is part of Gforth.
7
8\ Gforth is free software; you can redistribute it and/or
9\ modify it under the terms of the GNU General Public License
10\ as published by the Free Software Foundation, either version 3
11\ of the License, or (at your option) any later version.
12
13\ This program is distributed in the hope that it will be useful,
14\ but WITHOUT ANY WARRANTY; without even the implied warranty of
15\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16\ GNU General Public License for more details.
17
18\ You should have received a copy of the GNU General Public License
19\ along with this program. If not, see http://www.gnu.org/licenses/.
20
21\ We can do some of these (and possibly faster) by just using the
22\ utf-8 words with an appropriate setting of max-single-byte, but I
23\ like to see how an 8bit setting without UTF-8 stuff looks like.
24
25Defer xemit ( xc -- ) \ xchar-ext
26\G Prints an xchar on the terminal.
27Defer xkey ( -- xc ) \ xchar-ext
28\G Reads an xchar from the terminal. This will discard all input
29\G events up to the completion of the xchar.
30Defer xchar+ ( xc-addr1 -- xc-addr2 ) \ xchar-ext
31\G Adds the size of the xchar stored at @var{xc-addr1} to this address,
32\G giving @var{xc-addr2}.
33Defer xchar- ( xc-addr1 -- xc-addr2 ) \ xchar-ext
34\G Goes backward from @var{xc_addr1} until it finds an xchar so that
35\G the size of this xchar added to @var{xc_addr2} gives
36\G @var{xc_addr1}.
37Defer +x/string ( xc-addr1 u1 -- xc-addr2 u2 ) \ xchar	plus-x-slash-string
38\G Step forward by one xchar in the buffer defined by address
39\G @var{xc-addr1}, size @var{u1} pchars. @var{xc-addr2} is the address
40\G and u2 the size in pchars of the remaining buffer after stepping
41\G over the first xchar in the buffer.
42Defer x\string- ( xc-addr1 u1 -- xc-addr1 u2 ) \ xchar	x-back-string-minus
43\G Step backward by one xchar in the buffer defined by address
44\G @var{xc-addr1} and size @var{u1} in pchars, starting at the end of
45\G the buffer. @var{xc-addr1} is the address and @var{u2} the size in
46\G pchars of the remaining buffer after stepping backward over the
47\G last xchar in the buffer.
48Defer xc@ ( xc-addr -- xc ) \ xchar-ext	xc-fetch
49\G Fetchs the xchar @var{xc} at @var{xc-addr1}.
50Defer xc!+? ( xc xc-addr1 u1 -- xc-addr2 u2 f ) \ xchar-ext	xc-store-plus-query
51\G Stores the xchar @var{xc} into the buffer starting at address
52\G @var{xc-addr1}, @var{u1} pchars large. @var{xc-addr2} points to the
53\G first memory location after @var{xc}, @var{u2} is the remaining
54\G size of the buffer. If the xchar @var{xc} did fit into the buffer,
55\G @var{f} is true, otherwise @var{f} is false, and @var{xc-addr2}
56\G @var{u2} equal @var{xc-addr1} @var{u1}. XC!+?  is safe for buffer
57\G overflows, and therefore preferred over XC!+.
58Defer xc@+ ( xc-addr1 -- xc-addr2 xc ) \ xchar-ext	xc-fetch-plus
59\G Fetchs the xchar @var{xc} at @var{xc-addr1}. @var{xc-addr2} points
60\G to the first memory location after @var{xc}.
61Defer xc-size ( xc -- u ) \ xchar-ext
62\G Computes the memory size of the xchar @var{xc} in pchars.
63Defer x-size ( xc-addr u1 -- u2 ) \ xchar
64\G Computes the memory size of the first xchar stored at @var{xc-addr}
65\G in pchars.
66Defer x-width ( xc-addr u -- n ) \ xchar-ext
67\G @var{n} is the number of monospace ASCII pchars that take the same
68\G space to display as the the xchar string starting at @var{xc-addr},
69\G using @var{u} pchars; assuming a monospaced display font,
70\G i.e. pchar width is always an integer multiple of the width of an
71\G ASCII pchar.
72Defer -trailing-garbage ( xc-addr u1 -- addr u2 ) \ xchar-ext
73\G Examine the last XCHAR in the buffer @var{xc-addr} @var{u1}---if
74\G the encoding is correct and it repesents a full pchar, @var{u2}
75\G equals @var{u1}, otherwise, @var{u2} represents the string without
76\G the last (garbled) xchar.
77
78\ derived words, faster implementations are probably possible
79
80: x@+/string ( xc-addr1 u1 -- xc-addr2 u2 xc )
81    \ !! check for errors?
82    over >r +x/string
83    r> xc@ ;
84
85: xhold ( xc -- )
86    \G Put xc into the pictured numeric output
87    dup xc-size negate chars holdptr +!
88    holdptr @ dup holdbuf u< -&17 and throw
89    8 xc!+? 2drop drop ;
90
91\ fixed-size versions of these words
92
93: char- ( c-addr1 -- c-addr2 )
94    [ 1 chars ] literal - ;
95
96: +string ( c-addr1 u1 -- c-addr2 u2 )
97    1 /string ;
98: string- ( c-addr1 u1 -- c-addr1 u2 )
99    1- ;
100
101: c!+? ( c c-addr1 u1 -- c-addr2 u2 f )
102    dup 1 chars u< if \ or use < ?
103	rot drop false
104    else
105	>r dup >r c!
106	r> r> 1 /string true
107    then ;
108
109: c-size ( c -- 1 )
110    drop 1 ;
111
112: set-encoding-fixed-width ( -- )
113    ['] emit is xemit
114    ['] key is xkey
115    ['] char+ is xchar+
116    ['] char- is xchar-
117    ['] +string is +x/string
118    ['] string- is x\string-
119    ['] c@ is xc@
120    ['] c!+? is xc!+?
121    ['] count is xc@+
122    ['] c-size is xc-size
123    ['] c-size is x-size
124    ['] nip IS x-width
125    ['] noop is -trailing-garbage
126;
127