1% This is for checking how the underlying Lisp copes with 2% printing (and exploding) strings and symbols that contain 3% multi-byte characters - ie utf-8 sequences for characters with 4% code over U+007f. 5 6% The output is a little tedious to decode, but this is intended to 7% illustrate a collection of cases both as regards the actual 8% output generated and the calculation of "output columns" and hence 9% the way in which lines get wrapped. 10 11% At present this is only expected to give even partly sensible 12% results with CSL. 13 14lisp; 15 16 17nil 18 19on echo; 20 21 22nil 23 24 25% test line overflow 26 27<< 28% This test dispays a sequence of characters in clumps of 7 interleaved 29% with numbers showing the output column that has been reached. The 30% three instances use a letter "a" which provides a simple reference case. 31% then there is a "pi", a "forall" symbol and a double-struck capical B: 32% those use two, three and four bytes. Note that the #Bopf; may not be 33% available in the font you use unless it is somewhat specialised. 34% Note that #Zopf;, #Qopf; and #Ropf; are often used to denote the integers, 35% rationals an dreals, and that #Bopf; is a similar font effect. 36% 37% If things work well then the display should be similar in all cases, 38% both in term of the column values printed and the position 39% where line-breaks are inserted. If (eg) a sequence of utf-8 bytes ends up 40% counted as multiple "columns" that could lead to differences. 41% 42% First try printing strings. 43 linelength 72; 44 terpri(); terpri(); 45 prin2 "Check linelength effect with strings"; 46 terpri(); 47 prin2 ".. each of the following 4 blocks should show the sama layout"; 48 foreach x in list("a", "#pi;", "#ForAll;", "#Bopf;") do << 49 terpri(); 50 for i := 1:11 do << 51 for j := 1:7 do prin2 x; 52 prin2 posn() >> >>; 53 terpri(); terpri(); 54% Now the same but printing symbols (using prin2). 55 prin2 "Check linelength effect with symbols"; 56 terpri(); 57 prin2 ".. each of the following 4 blocks should show the sama layout"; 58 foreach x in list('a, '#pi;, '#ForAll;, '#Bopf;) do << 59 terpri(); 60 for i := 1:11 do << 61 for j := 1:7 do prin2 x; 62 prin2 posn() >> >>; 63 64% This section uses prin1 and variations on explode to process first strings 65% and then symbols with various contents. For prin1 the requirement is that 66% the output be re-inputable. 67% The string here is intended to contain a jolly mix of potential issues. 68 w1 := "2AbCd #pi; #ForAll; #Bopf; #hash;pi; #quot; #gamma; #Gamma;"; 69 foreach x in list(w1, intern w1) do << 70 terpri(); 71 prin2 "Test using "; 72 if stringp x then prin2 "strings" else prin2 "symbols"; 73 terpri(); 74% prin2 is used just to display the information "naturally" (at least 75% if you have an utf-8 capable terminal with enough fonts installed. 76 prin2 "Raw: "; prin2 x; print posn(); 77 78% prin1 should generate re-inputable material, and to assure that it 79% renders extended characters as hex sequence such as "#1234;". Within a 80% string if such a sequence literally occured then the initial "#" is expanded 81% to be "#hash;". In strings any double quote mark is doubled, while in 82% symbols special characters are preceeded by an exclamation mark. 83 prin2 "prin1: "; prin1 x; print posn(); 84 85% explode2 should be rather like prin2 except that it generates a list of 86% characters. Note that this means that multi-byte sequences in the data will 87% need to be rendered as single multi-byte character objects. E.g. 88% explode2 "#alpha;" => (#alpha;), a list of length 1. 89% spaces) it must explode2 as 90 prin2 "explode2: "; prin1 explode2 x; print posn(); 91 92% explode is like prin1 except that it can end up with extended characters... 93% thus 94% explode "#alpha;" => (!" !#alpha; !"), a list of length 3. The only joker 95% here is that if the string contains a literal sequence "# w o r d ;" (without 96% the spaces) then that has to end up as (!" !# h a s h !; w o r d !; !") 97% so it can be re-inputable. 98 prin2 "explode: "; prin1 explode x; print posn(); 99% explodecn is like explodec but returns a list of the numeric codes of 100% the characters involved. E.g. 101% explodecn "#alpha;" => (945) 102 princ "explodecn: "; prin1 explodecn x; print posn(); 103% exploden is like explode but returns a list of integer codes. 104% Note some codes can be bigger than 0xff. 105 princ "exploden: "; prin1 exploden x; print posn(); 106% explode2uc (and explode2lc, explode2ucn, explode2lcn) are like 107% explode2 except that they folds characters to upper or lower case. 108% There are two issues here. The first is whether #alpha; will change to 109% #Alpha; (and similarly for all other non-Latin letters), the second 110% is that the names for special characters will need to retain their 111% regular case, so for instance #Alpha; must appear not #ALPHA; even 112% after conversion to upper case. If in fact extended characters are 113% printed in hex not using names much of that worry evaporates. 114% In some - perhaps all - locales only a-x and A-Z will be changed 115% by case folding... 116 princ "explode2uc: "; prin1 explode2uc x; print posn(); 117 princ "explode2lc: "; prin1 explode2lc x; print posn() >>; 118 terpri() >>; 119 120 121 122Check linelength effect with strings 123.. each of the following 4 blocks should show the sama layout 124aaaaaaa7aaaaaaa15aaaaaaa24aaaaaaa33aaaaaaa42aaaaaaa51aaaaaaa60aaaaaaa69a 125aaaaaa6aaaaaaa14aaaaaaa23 126πππππππ7πππππππ15πππππππ24πππππππ33πππππππ42πππππππ51πππππππ60πππππππ69π 127ππππππ6πππππππ14πππππππ23 128∀∀∀∀∀∀∀7∀∀∀∀∀∀∀15∀∀∀∀∀∀∀24∀∀∀∀∀∀∀33∀∀∀∀∀∀∀42∀∀∀∀∀∀∀51∀∀∀∀∀∀∀60∀∀∀∀∀∀∀69∀ 129∀∀∀∀∀∀6∀∀∀∀∀∀∀14∀∀∀∀∀∀∀23 130715243342516069 13161423 132 133Check linelength effect with symbols 134.. each of the following 4 blocks should show the sama layout 135aaaaaaa7aaaaaaa15aaaaaaa24aaaaaaa33aaaaaaa42aaaaaaa51aaaaaaa60aaaaaaa69a 136aaaaaa6aaaaaaa14aaaaaaa23 137πππππππ7πππππππ15πππππππ24πππππππ33πππππππ42πππππππ51πππππππ60πππππππ69π 138ππππππ6πππππππ14πππππππ23 139∀∀∀∀∀∀∀7∀∀∀∀∀∀∀15∀∀∀∀∀∀∀24∀∀∀∀∀∀∀33∀∀∀∀∀∀∀42∀∀∀∀∀∀∀51∀∀∀∀∀∀∀60∀∀∀∀∀∀∀69∀ 140∀∀∀∀∀∀6∀∀∀∀∀∀∀14∀∀∀∀∀∀∀23 141715243342516069 14261423 143Test using strings 144Raw: 2AbCd π ∀ #pi; " γ Γ27 145prin1: "2AbCd #03c0; #2200; #01d539; #hash;pi; "" #03b3; #0393;"64 146explode2: (!2 !A b !C d ! !#03c0; ! !#2200; ! !#01d539; ! !# p i !; 147! !" ! !#03b3; ! !#0393;)28 148explode: (!" !2 !A b !C d ! !#03c0; ! !#2200; ! !#05d539; ! !# h a s 149h !; p i !; ! !" !" ! !#03b3; ! !#0393; !")46 150explodecn: (50 65 98 67 100 32 960 32 8704 32 120121 32 35 112 105 59 32 15134 32 947 32 915)17 152exploden: (34 50 65 98 67 100 32 960 32 8704 32 382265 32 35 104 97 115 153104 59 112 105 59 32 34 34 32 947 32 915 34)44 154explode2uc: (!2 !A !B !C !D ! !#03c0; ! !#2200; ! !#05d539; ! !# h a 155s h !; !P !I !; ! !" ! !#03b3; ! !#0393;)44 156explode2lc: (!2 a b c d ! !#03c0; ! !#2200; ! !#05d539; ! !# h a s h 157!; p i !; ! !" ! !#03b3; ! !#0393;)38 158 159Test using symbols 160Raw: 2AbCd π ∀ #pi; " γ Γ27 161prin1: 162!2!Ab!Cd! !#03c0;! !#2200;! !#01d539;! !#pi!;! !"! !#03b3;! !#0393;67 163explode2: (!2 !A b !C d ! !#03c0; ! !#2200; ! !#01d539; ! !# p i !; 164! !" ! !#03b3; ! !#0393;)28 165explode: (!! !2 !! !A b !! !C d !! ! !! !#03c0; !! ! !! !#2200; !! ! 166!! !#05d539; !! ! !! !# p i !! !; !! ! !! !" !! ! !! !#03b3; !! ! !! 167!#0393;)8 168explodecn: (50 65 98 67 100 32 960 32 8704 32 120121 32 35 112 105 59 32 16934 32 947 32 915)17 170exploden: (33 50 33 65 98 33 67 100 33 32 33 960 33 32 33 8704 33 32 33 171382265 33 32 33 35 112 105 33 59 33 32 33 34 33 32 33 947 33 32 33 915) 17271 173explode2uc: (!! !2 !A !B !C !D ! !#03c0; ! !#2200; ! !#05d539; ! !# 174!P !I !; ! !" ! !#03b3; ! !#0393;)37 175explode2lc: (!! !2 a b c d ! !#03c0; ! !#2200; ! !#05d539; ! !# p i 176!; ! !" ! !#03b3; ! !#0393;)31 177 178 179nil 180 181 182end; 183 184nil 185Tested on x86_64-pc-windows CSL 186Time (counter 1): 0 ms 187 188End of Lisp run after 0.00+0.04 seconds 189real 0.23 190user 0.00 191sys 0.04 192