diff --git a/autotest/UnicodeInfo/UnicodeInfo.cpp b/autotest/UnicodeInfo/UnicodeInfo.cpp index 70a36d106..7245c394f 100644 --- a/autotest/UnicodeInfo/UnicodeInfo.cpp +++ b/autotest/UnicodeInfo/UnicodeInfo.cpp @@ -82,7 +82,7 @@ CONSOLE_APP_MAIN ASSERT(comb == UnicodeDecompose(code)); - Vector h = UnicodeDecompose(code, true); + WString h = UnicodeDecompose(code, true); if(h.GetCount() > 1) { DUMP(h); ASSERT(code == UnicodeCompose(h)); diff --git a/autotest/WStringSerialize/Etalon.log b/autotest/WStringSerialize/Etalon.log index 4f161b6c1..26eb9be16 100644 --- a/autotest/WStringSerialize/Etalon.log +++ b/autotest/WStringSerialize/Etalon.log @@ -1,103 +1,139 @@ -* C:\upp\out\autotest\CLANGx64.Debug.Debug_Full\WStringSerialize.exe 13.10.2021 09:17:22, user: cxl +* C:\upp\out\wchar_autotest\CLANGx64.Debug.Debug_Full\WStringSerialize.exe 13.10.2021 10:00:28, user: cxl x: - [0] = x - [1] = xx - [2] = xxx - [3] = xxxx - [4] = xxxxx - [5] = xxxxxx - [6] = xxxxxxx - [7] = xxxxxxxx - [8] = xxxxxxxxx - [9] = xxxxxxxxxx - [10] = xxxxxxxxxxx - [11] = xxxxxxxxxxxx - [12] = xxxxxxxxxxxxx - [13] = xxxxxxxxxxxxxx - [14] = xxxxxxxxxxxxxxx - [15] = xxxxxxxxxxxxxxxx - [16] = xxxxxxxxxxxxxxxxx - [17] = xxxxxxxxxxxxxxxxxx - [18] = xxxxxxxxxxxxxxxxxxx - [19] = xxxxxxxxxxxxxxxxxxxx - [20] = xxxxxxxxxxxxxxxxxxxxx - [21] = xxxxxxxxxxxxxxxxxxxxxx - [22] = xxxxxxxxxxxxxxxxxxxxxxx - [23] = xxxxxxxxxxxxxxxxxxxxxxxx - [24] = xxxxxxxxxxxxxxxxxxxxxxxxx - [25] = xxxxxxxxxxxxxxxxxxxxxxxxxx - [26] = xxxxxxxxxxxxxxxxxxxxxxxxxxx - [27] = xxxxxxxxxxxxxxxxxxxxxxxxxxxx - [28] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [29] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [30] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [31] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [32] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [33] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [34] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [35] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [36] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [37] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [38] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [39] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [40] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [41] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [42] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [43] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [44] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [45] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [46] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [47] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [48] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [49] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [50] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [51] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [52] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [53] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [54] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [55] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [56] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [57] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [58] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [59] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [60] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [61] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [62] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [63] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [64] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [65] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [66] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [67] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [68] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [69] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [70] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [71] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [72] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [73] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [74] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [75] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [76] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [77] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [78] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [79] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [80] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [81] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [82] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [83] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [84] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [85] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [86] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [87] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [88] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [89] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [90] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [91] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [92] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [93] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [94] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [95] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [96] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [97] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [98] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - [99] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + [0] = 0 + [1] = 01 + [2] = 012 + [3] = 0123 + [4] = 01234 + [5] = 012345 + [6] = 0123456 + [7] = 01234567 + [8] = 012345678 + [9] = 0123456789 + [10] = 012345678910 + [11] = 01234567891011 + [12] = 0123456789101112 + [13] = 012345678910111213 + [14] = 01234567891011121314 + [15] = 0123456789101112131415 + [16] = 012345678910111213141516 + [17] = 01234567891011121314151617 + [18] = 0123456789101112131415161718 + [19] = 012345678910111213141516171819 + [20] = 01234567891011121314151617181920 + [21] = 0123456789101112131415161718192021 + [22] = 012345678910111213141516171819202122 + [23] = 01234567891011121314151617181920212223 + [24] = 0123456789101112131415161718192021222324 + [25] = 012345678910111213141516171819202122232425 + [26] = 01234567891011121314151617181920212223242526 + [27] = 0123456789101112131415161718192021222324252627 + [28] = 012345678910111213141516171819202122232425262728 + [29] = 01234567891011121314151617181920212223242526272829 + [30] = 0123456789101112131415161718192021222324252627282930 + [31] = 012345678910111213141516171819202122232425262728293031 + [32] = 01234567891011121314151617181920212223242526272829303132 + [33] = 0123456789101112131415161718192021222324252627282930313233 + [34] = 012345678910111213141516171819202122232425262728293031323334 + [35] = 01234567891011121314151617181920212223242526272829303132333435 + [36] = 0123456789101112131415161718192021222324252627282930313233343536 + [37] = 012345678910111213141516171819202122232425262728293031323334353637 + [38] = 01234567891011121314151617181920212223242526272829303132333435363738 + [39] = 0123456789101112131415161718192021222324252627282930313233343536373839 + [40] = 012345678910111213141516171819202122232425262728293031323334353637383940 + [41] = 01234567891011121314151617181920212223242526272829303132333435363738394041 + [42] = 0123456789101112131415161718192021222324252627282930313233343536373839404142 + [43] = 012345678910111213141516171819202122232425262728293031323334353637383940414243 + [44] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344 + [45] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445 + [46] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546 + [47] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647 + [48] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 + [49] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 + [50] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 + [51] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 + [52] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 + [53] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 + [54] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 + [55] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 + [56] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 + [57] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 + [58] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 + [59] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 + [60] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 + [61] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 + [62] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 + [63] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 + [64] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 + [65] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 + [66] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 + [67] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 + [68] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 + [69] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 + [70] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 + [71] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 + [72] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 + [73] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 + [74] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 + [75] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 + [76] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 + [77] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 + [78] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 + [79] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 + [80] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 + [81] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 + [82] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 + [83] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 + [84] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 + [85] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 + [86] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 + [87] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 + [88] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 + [89] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 + [90] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 + [91] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 + [92] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 + [93] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 + [94] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 + [95] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 + [96] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 + [97] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 + [98] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 + [99] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 + [100] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 + [101] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 + [102] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 + [103] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 + [104] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 + [105] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 + [106] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 + [107] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 + [108] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 + [109] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 + [110] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 + [111] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 + [112] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 + [113] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 + [114] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 + [115] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 + [116] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 + [117] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 + [118] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 + [119] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 + [120] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 + [121] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 + [122] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 + [123] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 + [124] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 + [125] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 + [126] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 + [127] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 + [128] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 + [129] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 + [130] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 + [131] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 + [132] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 + [133] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 + [134] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 + [135] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 diff --git a/autotest/WStringSerialize/WStringSerialize.cpp b/autotest/WStringSerialize/WStringSerialize.cpp index 8fa95af27..cf077102e 100644 --- a/autotest/WStringSerialize/WStringSerialize.cpp +++ b/autotest/WStringSerialize/WStringSerialize.cpp @@ -7,6 +7,6 @@ CONSOLE_APP_MAIN Vector x; LoadFromFile(x, GetDataFile("wstring.bin")); DDUMPC(x); + ASSERT(StoreAsString(x) == LoadDataFile("wstring.bin")); CheckLogEtalon(); - RLOG("================= OK"); } diff --git a/autotest/WStringSerialize/wstring.bin b/autotest/WStringSerialize/wstring.bin index 6f7659b26..024b4d8dd 100644 Binary files a/autotest/WStringSerialize/wstring.bin and b/autotest/WStringSerialize/wstring.bin differ diff --git a/autotest/std_wstring/std_wstring.cpp b/autotest/std_wstring/std_wstring.cpp new file mode 100644 index 000000000..15d9ad1bc --- /dev/null +++ b/autotest/std_wstring/std_wstring.cpp @@ -0,0 +1,25 @@ +#include + +using namespace Upp; + +CONSOLE_APP_MAIN +{ + StdLogSetup(LOG_COUT|LOG_FILE); + + DDUMP(sizeof(wchar_t)); + + WString x; + x.Cat(48); + x.Cat(48000); + x.Cat(70000); + + std::wstring w = x; + + DDUMP(w.size()); + + WString y = w; + + ASSERT(x == y); + + DLOG("============= OK"); +} diff --git a/autotest/std_wstring/std_wstring.upp b/autotest/std_wstring/std_wstring.upp new file mode 100644 index 000000000..d8e70fde2 --- /dev/null +++ b/autotest/std_wstring/std_wstring.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + std_wstring.cpp; + +mainconfig + "" = ""; + diff --git a/examples/GetMemoryBlockSize/GetMemoryBlockSize.cpp b/examples/GetMemoryBlockSize/GetMemoryBlockSize.cpp new file mode 100644 index 000000000..9f3deb37b --- /dev/null +++ b/examples/GetMemoryBlockSize/GetMemoryBlockSize.cpp @@ -0,0 +1,17 @@ +#include + +using namespace Upp; + +// TEST IN RELEASE MODE! + +CONSOLE_APP_MAIN +{ + for(int q = 5; q < 500*1024*1024; q = q + 1 + q / 10) { + size_t sz = q; + void *ptr = MemoryAllocSz(sz); + DLOG("Requested " << q << ", allocated " << sz << ", GetMemoryBlockSize " << GetMemoryBlockSize(ptr)); + if(sz != GetMemoryBlockSize(ptr)) + Panic("FAILED!"); + MemoryFree(ptr); + } +} diff --git a/examples/GetMemoryBlockSize/GetMemoryBlockSize.upp b/examples/GetMemoryBlockSize/GetMemoryBlockSize.upp new file mode 100644 index 000000000..9001499b9 --- /dev/null +++ b/examples/GetMemoryBlockSize/GetMemoryBlockSize.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + GetMemoryBlockSize.cpp; + +mainconfig + "" = "DEBUGCODE"; + diff --git a/examples/MemorySize/MemorySize.cpp b/examples/MemorySize/MemorySize.cpp new file mode 100644 index 000000000..9f3deb37b --- /dev/null +++ b/examples/MemorySize/MemorySize.cpp @@ -0,0 +1,17 @@ +#include + +using namespace Upp; + +// TEST IN RELEASE MODE! + +CONSOLE_APP_MAIN +{ + for(int q = 5; q < 500*1024*1024; q = q + 1 + q / 10) { + size_t sz = q; + void *ptr = MemoryAllocSz(sz); + DLOG("Requested " << q << ", allocated " << sz << ", GetMemoryBlockSize " << GetMemoryBlockSize(ptr)); + if(sz != GetMemoryBlockSize(ptr)) + Panic("FAILED!"); + MemoryFree(ptr); + } +} diff --git a/examples/MemorySize/MemorySize.upp b/examples/MemorySize/MemorySize.upp new file mode 100644 index 000000000..c4a2da96c --- /dev/null +++ b/examples/MemorySize/MemorySize.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + MemorySize.cpp; + +mainconfig + "" = "DEBUGCODE"; + diff --git a/examples/WeirdBug/WeirdBug.cpp b/examples/WeirdBug/WeirdBug.cpp new file mode 100644 index 000000000..023ae5afa --- /dev/null +++ b/examples/WeirdBug/WeirdBug.cpp @@ -0,0 +1,13 @@ +#include + +using namespace Upp; + +Vector g_turbine_data; // one for turbine*scenario + +CONSOLE_APP_MAIN +{ + String data = LoadFile("D:/xxx/td.bin"); + RDUMP(data.GetCount()); + LoadFromString(g_turbine_data, data); + RDUMP(g_turbine_data); +} diff --git a/examples/WeirdBug/WeirdBug.upp b/examples/WeirdBug/WeirdBug.upp new file mode 100644 index 000000000..87e4f8712 --- /dev/null +++ b/examples/WeirdBug/WeirdBug.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + WeirdBug.cpp; + +mainconfig + "" = "DEBUGCODE"; + diff --git a/rainbow/WinAlt/DrawTextWinAlt.cpp b/rainbow/WinAlt/DrawTextWinAlt.cpp index 0e040b7e7..3a8ec6272 100644 --- a/rainbow/WinAlt/DrawTextWinAlt.cpp +++ b/rainbow/WinAlt/DrawTextWinAlt.cpp @@ -34,10 +34,11 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon double sina, cosa; Draw::SinCos(angle, sina, cosa); Size offset; - ::ExtTextOutW(handle, x + fround(ascent * sina), y + fround(ascent * cosa), 0, NULL, (const WCHAR *)text, n, dx); + ::ExtTextOutW(handle, x + fround(ascent * sina), y + fround(ascent * cosa), 0, NULL, + ToSystemCharsetW(text), n, dx); } else - ::ExtTextOutW(handle, x, y + ascent, 0, NULL, (const WCHAR *)text, + ::ExtTextOutW(handle, x, y + ascent, 0, NULL, ToSystemCharsetW(text), n, dx); ::SelectObject(handle, orgfont); } diff --git a/rainbow/WinAlt/TopWinAlt.cpp b/rainbow/WinAlt/TopWinAlt.cpp index 55426e7df..729c3f8e3 100644 --- a/rainbow/WinAlt/TopWinAlt.cpp +++ b/rainbow/WinAlt/TopWinAlt.cpp @@ -78,7 +78,7 @@ void TopWindow::SyncTitle0() #ifndef PLATFORM_WINCE if(hwnd) if(IsWindowUnicode(hwnd)) - ::SetWindowTextW(hwnd, (const WCHAR*)~title); + ::SetWindowTextW(hwnd, ToSystemCharsetW(title)); else #endif ::SetWindowText(hwnd, ToSystemCharset(title.ToString())); diff --git a/reference/OpenGL/OpenGL.upp b/reference/OpenGL/OpenGL.upp index 942c9e3b8..d28b6c5a8 100644 --- a/reference/OpenGL/OpenGL.upp +++ b/reference/OpenGL/OpenGL.upp @@ -2,7 +2,7 @@ description "GLCtrl widget example\377"; uses GLCtrl, - CodeEditor; + CtrlLib; file main.cpp; diff --git a/uppbox/FontMaps2/TypeReader.cpp b/uppbox/FontMaps2/TypeReader.cpp index 08136ad7f..18a18cde2 100644 --- a/uppbox/FontMaps2/TypeReader.cpp +++ b/uppbox/FontMaps2/TypeReader.cpp @@ -1,21 +1,31 @@ #include "TypeReader.h" #define LLOG(x) // LOG(x) -#define LDUMP(x) // LLOG(#x << " = " << x); +#define LDUMP(x) // LOG(#x << " = " << x); + +int FontTypeReader::Error() +{ + throw Fail(); return 0; +} + +int FontTypeReader::Error() +{ + throw Fail(); return 0; +} int FontTypeReader::Peek8(const char *s) { - return s + 1 < font.end() ? (byte)*s : Error(); + return s + 1 < data.end() ? (byte)*s : Error(); } int FontTypeReader::Peek16(const char *s) { - return s + 2 < font.end() ? Peek16be(s) : Error(); + return s + 2 < data.end() ? Peek16be(s) : Error(); } int FontTypeReader::Peek32(const char *s) { - return s + 4 < font.end() ? Peek32be(s) : Error(); + return s + 4 < data.end() ? Peek32be(s) : Error(); } int FontTypeReader::Peek8(const char *s, int i) @@ -54,45 +64,11 @@ int FontTypeReader::Read32(const char *&s) return q; } -const char *FontTypeReader::Seek(const char *tab, int& len) -{ - ASSERT(strlen(tab) == 4); - int q = table.Find(tab); - if(q < 0) - Error(); - len = table[q].length; - return ~font + table[q].offset; -} - -const char *FontTypeReader::Seek(const char *tab) -{ - int dummy; - return Seek(tab, dummy); -} - -bool FontTypeReader::Open(const String& fnt, bool symbol, bool justcheck) +bool FontTypeReader::Open(Font font, bool symbol, bool justcheck) { // DDUMP(fnt.GetCount()); try { int i; - table.Clear(); - font = fnt; - const char *s = fnt; - int q = Read32(s); - if(q != 0x74727565 && q != 0x00010000) - Error(); - int n = Read16(s); - s += 6; - while(n--) { -// DDUMP(String(s, 4)); - Table& t = table.Add(String(s, 4)); - s += 8; // skip checksum - t.offset = Read32(s); -// DDUMP(t.offset); - t.length = Read32(s); -// DDUMP(t.length); -// DLOG("----"); - } #if 0 for(i = 0; i < table.GetCount(); i++) LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length); @@ -124,35 +100,40 @@ bool FontTypeReader::Open(const String& fnt, bool symbol, bool justcheck) << ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size); #endif + data = font.GetData("OS/2"); + panose.Clear(); + if(data.GetCount() > 32 + 10) + panose = data.Mid(32, 10); + bool found = false; + data = font.GetData("cmap"); for(int pass = 0; pass < 2; pass++) { - const char *s = Seek("cmap"); - const char *p = s; + const char *p = data; // LOGHEXDUMP(p, 256); p += 2; - n = Read16(p); + int n = Read16(p); // DDUMP(n); while(n--) { int pid = Read16(p); int psid = Read16(p); int offset = Read32(p); - if(offset < 0 || offset > font.GetLength()) + if(offset < 0 || offset > data.GetCount()) Error(); - int format = Peek16(s + offset); + int format = Peek16(~data + offset); LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format); //Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol... if(symbol) { - if(pid == 1 && psid == 0 && Peek16(s + offset) == 0) { + if(pid == 1 && psid == 0 && Peek16(~data + offset) == 0) { LLOG("Reading symbol table"); - p = s + offset + 6; + p = ~data + offset + 6; for(int i = 0; i < 256; i++); //SetGlyph(i, (byte)p[i]); goto done; } } else - if(pid == 3 && psid == 10 && format == 12 && pass == 0) { - const char *p = s + offset; + if((pid == 3 && psid == 10) || (pid == 0 && psid == 4) && format == 12 && pass == 0) { + const char *p = ~data + offset; int ngroups = Peek32(p + 12); p += 16; // pointer to groups table for(int i = 0; i < ngroups; i++) { @@ -163,8 +144,8 @@ bool FontTypeReader::Open(const String& fnt, bool symbol, bool justcheck) goto done; } else - if(pid == 3 && psid == 1 && format == 4 && pass == 1) { - const char *p = s + offset; + if((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4 && pass == 1) { + const char *p = ~data + offset; int n = Peek16(p + 6) >> 1; LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n); const char *seg_end = p + 14; @@ -199,35 +180,38 @@ bool FontTypeReader::Open(const String& fnt, bool symbol, bool justcheck) } } } - done: - - int len; - const char *strings = Seek("name", len); - s = strings + 2; - int count = Read16(s); - strings += (word)Read16(s); - for(int i = 0; i < count; i++) { - int platform = Read16(s); - s += 4; - if(Read16(s) == 6) { - int len = Read16(s); - int offset = Read16(s); - if(platform == 1) - ps_name = String(strings + offset, len); - else { - s = strings + offset; - len >>= 1; - while(len--) - ps_name.Cat(Read16(s)); + done:; + #if 0 + String names = font.GetData("name"); + if(names.GetCount()) { + const char *strings = names; + const char *s = strings + 2; + int count = Read16(s); + strings += (word)Read16(s); + for(int i = 0; i < count; i++) { + int platform = Read16(s); + s += 4; + if(Read16(s) == 6) { + int len = Read16(s); + int offset = Read16(s); + if(platform == 1) + ps_name = String(strings + offset, len); + else { + s = strings + offset; + len >>= 1; + while(len--) + ps_name.Cat(Read16(s)); + } + break; } - break; + s += 4; } - s += 4; } DDUMP(ps_name); + #endif } catch(Fail) { - DLOG("ERROR"); + LLOG("ERROR"); return false; } diff --git a/uppbox/FontMaps2/TypeReader.h b/uppbox/FontMaps2/TypeReader.h index b153cebf0..52d2ec541 100644 --- a/uppbox/FontMaps2/TypeReader.h +++ b/uppbox/FontMaps2/TypeReader.h @@ -6,7 +6,7 @@ using namespace Upp; class FontTypeReader { - String font; + String data; struct Table : Moveable { int offset; @@ -15,7 +15,7 @@ class FontTypeReader { VectorMap table; struct Fail {}; - static int Error() { throw Fail(); return 0; } + static int Error(); int Peek8(const char *s); int Peek16(const char *s); @@ -27,17 +27,14 @@ class FontTypeReader { int Read16(const char *&s); int Read32(const char *&s); - const char *Seek(const char *tab, int& len); - const char *Seek(const char *tab); -// void Seek(const char *tab, TTFStreamIn& s); - String GetTable(const char *tab); - public: String ps_name; Array> ranges; + + String panose; - bool Open(const String& fnt, bool symbol = false, bool justcheck = false); + bool Open(Font font, bool symbol = false, bool justcheck = false); }; #endif diff --git a/uppbox/FontMaps2/main.cpp b/uppbox/FontMaps2/main.cpp index ee8890956..978841ed3 100644 --- a/uppbox/FontMaps2/main.cpp +++ b/uppbox/FontMaps2/main.cpp @@ -8,6 +8,8 @@ using namespace Upp; #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p')) +#ifdef PLATFORM_WIN32 + namespace Upp { HFONT GetWin32Font(Font fnt, int angle); }; @@ -34,20 +36,70 @@ String GetFontDataSys(Font font, dword table) return r; } +#endif + +String ReadFontTable(Stream& in, const char *table, int fonti = 0) +{ + in.Seek(0); + int q = in.Get32be(); + if(q == 0x74746366) { // true type collection + in.Get32(); // skip major/minor version + int nfonts = in.Get32be(); + if(fonti >= nfonts) + return Null; + in.SeekCur(fonti * 4); + int offset = in.Get32be(); + if(offset < 0 || offset >= in.GetSize()) + return Null; + in.Seek(offset); + q = in.Get32be(); + } + if(q != 0x74727565 && q != 0x00010000) + return Null; + int n = in.Get16be(); + in.Get32(); + in.Get16(); + while(n--) { + if(in.IsError() || in.IsEof()) return Null; + String tab = in.Get(4); + in.Get32(); + int offset = in.Get32be(); + int length = in.Get32be(); + if(tab == table) { + if(offset < 0 || length < 0 || offset + length > in.GetSize()) + return Null; + in.Seek(offset); + return in.Get(length); + } + } + return Null; +} + GUI_APP_MAIN { +// FileIn in("C:/Windows/Fonts/arial.ttf"); +/* + FileIn in("D:\\xxx\\msyh.ttc"); + DDUMPHEX(ReadFontTable(in, "cmap", 0)); + DDUMPHEX(ReadFontTable(in, "cmap", 1)); + DDUMPHEX(ReadFontTable(in, "cmap", 2)); + return; +*/ #if 0 -// Font font(Font::FindFaceNameIndex("Microsoft JhengHei"), 20); - Font font = StdFont(); + Font font(Font::FindFaceNameIndex("Noto Serif CJK KR"), 20); + +// Font font = Roman(20); // SaveFile("d:/xxx/font.bin", GetFontDataSys(font, 0)); - String cmap = GetFontDataSys(font, CMAP); - LOGHEXDUMP(~cmap, 256); +// String cmap = GetFontDataSys(font, CMAP); +// LOGHEXDUMP(~cmap, 256); FontTypeReader r; // r.Open(Arial(20).GetData()); - r.Open(font.GetData()); + DDUMP(font.GetFaceName()); + r.Open(font); + DDUMPHEX(r.panose); return; @@ -55,34 +107,52 @@ GUI_APP_MAIN #endif Progress pi; pi.SetTotal(Font::GetFaceCount()); - for(int i = 0; i < Font::GetFaceCount(); i++) { + Vector name; + for(int i = 0; i < Font::GetFaceCount(); i++) + name.Add(Font::GetFaceName(i)); + for(int i : GetSortOrder(name)) { String f = Font::GetFaceName(i); pi.SetText(f); if(pi.StepCanceled()) break; Font fnt; fnt.FaceName(f); - DLOG("==========="); - DDUMP(f); FontTypeReader r; // r.Open(Arial(20).GetData()); - r.Open(fnt.GetData()); - Sort(r.ranges, [](Tuple a, Tuple b) { return a.a < b.a; }); - DDUMP(r.ranges); - while(r.ranges.GetCount() > 8) { - int mini = 0; - int mind = INT_MAX; - for(int i = 0; i < r.ranges.GetCount() - 1; i++) { - int d = r.ranges[i + 1].a - r.ranges[i].b; - if(d < mind) { - mind = d; - mini = i; + r.Open(fnt); + if(r.panose.GetCount() == 10) { + dword h[8] = {0}; + for(auto r : r.ranges) { + for(int c = r.a; c <= r.b; c++) { + c = max(c, 0); + if(c < 2048) + h[0] |= 0x80000000 >> (c >> 6); + else { + int bi = clamp(c - 2048, 0, 7*32*1024 - 1) >> 10; + ASSERT((bi >> 5) + 1 < 8); + h[(bi >> 5) + 1] |= 0x80000000 >> (bi & 31); + } } } - r.ranges[mini].b = r.ranges[mini + 1].b; - r.ranges.Remove(mini + 1); + String l; + l << "{ " << AsCString(f); + l << ", { "; + bool first = true; + for(int h : r.panose) { + if(first) + first = false; + else + l << ","; + l << h; + } + l << " }, { "; + for(int i = 0; i < 8; i++) { + if(i) l << ","; + l << Format("0x%08x", (int)h[i]); + } + l << " } },"; + LOG(l); } - DDUMP(r.ranges); } // r.Open(Font(Font::FindFaceNameIndex("Segoe UI Emoji"), 20).GetData()); diff --git a/uppsrc/CodeEditor/FindReplace.cpp b/uppsrc/CodeEditor/FindReplace.cpp index c59f3b81f..3ae8ef322 100644 --- a/uppsrc/CodeEditor/FindReplace.cpp +++ b/uppsrc/CodeEditor/FindReplace.cpp @@ -218,8 +218,8 @@ bool CodeEditor::RegExpFind(int64 pos, bool block) for(int i = 0; i < regex.GetCount(); i++) SetFound(i, WILDANY, regex.GetString(i).ToWString()); int off = regex.GetOffset(); - int len = utf8len(~ln + off, regex.GetLength()); - pos = GetPos64(line, utf8len(~ln, off) + (int)pos); + int len = Utf32Len(~ln + off, regex.GetLength()); + pos = GetPos64(line, Utf32Len(~ln, off) + (int)pos); foundtext = GetW(pos, len); if(!block) { foundsel = true; diff --git a/uppsrc/Core/App.cpp b/uppsrc/Core/App.cpp index 9383eaee5..37bd0299f 100644 --- a/uppsrc/Core/App.cpp +++ b/uppsrc/Core/App.cpp @@ -59,7 +59,7 @@ String GetHomeDirectory() { String GetEnv(const char *id) { - return WString(_wgetenv(WString(id))).ToString(); + return WString(_wgetenv(ToSystemCharsetW(id))).ToString(); } String GetExeFilePath() @@ -500,27 +500,27 @@ void AppInitEnvironment__() int nArgs; LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs); if(szArglist) { - strcpy(Argv0__, WString(szArglist[0]).ToString()); + strcpy(Argv0__, FromSystemCharsetW(szArglist[0])); for(int i = 1; i < nArgs; i++) - coreCmdLine__().Add(szArglist[i]); + coreCmdLine__().Add(FromSystemCharsetW(szArglist[i]).ToWString()); LocalFree(szArglist); } - wchar *env = GetEnvironmentStringsW(); - for(wchar *ptr = env; *ptr; ptr++) + WCHAR *env = GetEnvironmentStringsW(); + for(WCHAR *ptr = env; *ptr; ptr++) { - const wchar *b = ptr; + const WCHAR *b = ptr; if(*ptr) ptr++; while(*ptr && *ptr != '=') ptr++; - WString varname(b, ptr); + WString varname = ToUtf32(b, int(ptr - b)); if(*ptr) ptr++; b = ptr; while(*ptr) ptr++; - EnvMap().GetAdd(ToUpper(varname)) = WString(b, ptr); + EnvMap().GetAdd(ToUpper(varname)) = ToUtf32(b, int(ptr - b)); } FreeEnvironmentStringsW(env); @@ -556,16 +556,16 @@ void LaunchWebBrowser(const String& url) #if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE) static auxthread_t auxthread__ sShellExecuteOpen(void *str) { - ShellExecuteW(NULL, L"open", (wchar *)str, NULL, L".", SW_SHOWDEFAULT); + ShellExecuteW(NULL, L"open", (WCHAR *)str, NULL, L".", SW_SHOWDEFAULT); free(str); return 0; } void LaunchWebBrowser(const String& url) { - WString wurl = ToSystemCharsetW(url); + Vector wurl = ToSystemCharsetW(url); if ((int64)(ShellExecuteW(NULL, L"open", wurl, NULL, L".", SW_SHOWDEFAULT)) <= 32) { - int l = sizeof(wchar) * wurl.GetLength() + 1; + int l = sizeof(wchar) * wurl.GetCount() + 1; char *curl = (char *)malloc(l); memcpy(curl, wurl, l); StartAuxThread(sShellExecuteOpen, curl); @@ -619,27 +619,29 @@ String LoadDataFile(const char *filename) String GetComputerName() { - char temp[256]; - *temp = 0; #if defined(PLATFORM_WIN32) + WCHAR temp[256]; + *temp = 0; dword w = 255; - ::GetComputerNameA(temp, &w); + ::GetComputerNameW(temp, &w); #else + char temp[256]; gethostname(temp, sizeof(temp)); #endif - return FromSystemCharset(temp); + return temp; } String GetUserName() { - char temp[256]; - *temp = 0; #if defined(PLATFORM_WIN32) + WCHAR temp[256]; + *temp = 0; dword w = 255; - ::GetUserNameA(temp, &w); - return FromSystemCharset(temp); + ::GetUserNameW(temp, &w); + return temp; #else - return Nvl(GetEnv("USER"), "boot"); + char temp[256]; + return Nvl(GetEnv("USER"), "root"); #endif } @@ -652,7 +654,7 @@ String GetDesktopManager() if(GetEnv("GNOME_DESKTOP_SESSION_ID").GetCount()) return "gnome"; if(GetEnv("KDE_FULL_SESSION").GetCount() || GetEnv("KDEDIR").GetCount()) - return "kde"; + return "kde"; return GetEnv("DESKTOP_SESSION"); #endif } @@ -661,9 +663,9 @@ String GetDesktopManager() String GetShellFolder(int clsid) { - wchar path[MAX_PATH]; + WCHAR path[MAX_PATH]; if(SHGetFolderPathW(NULL, clsid, NULL, /*SHGFP_TYPE_CURRENT*/0, path) == S_OK) - return FromUnicodeBuffer(path); + return FromSystemCharsetW(path); return Null; } @@ -691,7 +693,7 @@ String GetDownloadFolder() if(SHGetKnownFolderPath) { PWSTR path = NULL; if(SHGetKnownFolderPath(&MY_FOLDERID_Downloads, 0, NULL, &path) == S_OK && path) { - String s = FromUnicodeBuffer(path, wstrlen(path)); + String s = FromSystemCharsetW(path); CoTaskMemFree(path); return s; } diff --git a/uppsrc/Core/Bom.cpp b/uppsrc/Core/Bom.cpp index ef5abb71b..25384f187 100644 --- a/uppsrc/Core/Bom.cpp +++ b/uppsrc/Core/Bom.cpp @@ -35,7 +35,7 @@ static void sLoadBom(Stream& in, String *t, WString *wt, byte def_charset) byte *h = (byte *)&header; if(h[0] == 0xef && h[1] == 0xbb && c == 0xbf) { if(wt) - *wt = FromUtf8(LoadStream(in)); + *wt = ToUtf32(LoadStream(in)); else *t = ToCharset(CHARSET_DEFAULT, LoadStream(in), CHARSET_UTF8); return; diff --git a/uppsrc/Core/CharSet.cpp b/uppsrc/Core/CharSet.cpp index a6839e385..2d1ab8502 100644 --- a/uppsrc/Core/CharSet.cpp +++ b/uppsrc/Core/CharSet.cpp @@ -1998,12 +1998,6 @@ int ToAscii(int c, byte charset) return cs.FromUnicode(ToAscii(cs.ToUnicode(c))); } -word UnicodeCombine(word chr, word combine) -{ - dword h[2] = { chr, combine }; - return (word)UnicodeCompose(h, 2); -} - void ToUpper(char *t, const char *s, int len, byte charset) { charset = ResolveCharset(charset); @@ -2050,7 +2044,7 @@ WString ToUnicode(const char *src, int l, byte charset) { charset = ResolveCharset(charset); if(charset == CHARSET_UTF8) - return FromUtf8(src, l); + return ToUtf32(src, l); WStringBuffer result(l); ToUnicode(result, src, l, charset); return WString(result); @@ -2073,7 +2067,7 @@ String FromUnicodeBuffer(const wchar *src, int len, byte charset, int defchar) String FromUnicodeBuffer(const wchar *src) { - return FromUnicodeBuffer(src, wstrlen(src)); + return FromUnicodeBuffer(src, strlen__(src)); } String FromUnicode(const WString& src, byte charset, int defchar) @@ -2089,7 +2083,7 @@ String ToCharset(byte charset, const String& src, byte scharset, int def) return src; int slen = src.GetLength(); if(scharset == CHARSET_UTF8) - return FromUnicode(FromUtf8(src, slen), charset, def); + return FromUnicode(ToUtf32(src, slen), charset, def); if(charset == CHARSET_UTF8) return ToUtf8(ToUnicode(src, scharset)); StringBuffer result(slen); @@ -2161,7 +2155,7 @@ String ToUpper(const char *s, byte charset) { charset = ResolveCharset(charset); if(charset == CHARSET_UTF8) - return ToUtf8(ToUpper(FromUtf8(s))); + return ToUtf8(ToUpper(ToUtf32(s))); int l = (int)strlen(s); StringBuffer r(l); ToUpper(r, s, l, charset); @@ -2172,7 +2166,7 @@ String ToLower(const char *s, byte charset) { charset = ResolveCharset(charset); if(charset == CHARSET_UTF8) - return ToUtf8(ToLower(FromUtf8(s))); + return ToUtf8(ToLower(ToUtf32(s))); int l = (int)strlen(s); StringBuffer r(l); ToLower(r, s, l, charset); @@ -2183,7 +2177,7 @@ String ToAscii(const char *s, byte charset) { charset = ResolveCharset(charset); if(charset == CHARSET_UTF8) - return ToUtf8(ToAscii(FromUtf8(s))); + return ToUtf8(ToAscii(ToUtf32(s))); int l = (int)strlen(s); StringBuffer r(l); ToAscii(r, s, l, charset); @@ -2194,7 +2188,7 @@ String ToUpper(const String& s, byte charset) { charset = ResolveCharset(charset); if(charset == CHARSET_UTF8) - return ToUtf8(ToUpper(FromUtf8(s))); + return ToUtf8(ToUpper(ToUtf32(s))); int l = s.GetLength(); StringBuffer r(l); ToUpper(r, s, l, charset); @@ -2205,7 +2199,7 @@ String ToLower(const String& s, byte charset) { charset = ResolveCharset(charset); if(charset == CHARSET_UTF8) - return ToUtf8(ToLower(FromUtf8(s))); + return ToUtf8(ToLower(ToUtf32(s))); int l = s.GetLength(); StringBuffer r(l); ToLower(r, s, l, charset); diff --git a/uppsrc/Core/CharSet.h b/uppsrc/Core/CharSet.h index e8d19a28b..f3d953cd1 100644 --- a/uppsrc/Core/CharSet.h +++ b/uppsrc/Core/CharSet.h @@ -8,6 +8,7 @@ enum { #undef CHRSET_ #define CHARSET_TOASCII 253 +#define CHARSET_UTF32 254 // auxilary #define CHARSET_UTF8 255 #define CHARSET_UNICODE 255 @@ -23,86 +24,83 @@ enum { #include "Utf.hpp" -int strlen32(const dword *s); +inline bool IsUtf8Lead(int c) { return (c & 0xc0) != 0x80; } -inline bool IsUtf8Lead(int c) -{ - return (c & 0xc0) != 0x80; -} +wchar ReadSurrogatePair(const char16 *s, const char16 *lim); -dword FetchUtf8(const char *&s, const char *lim, bool& ok); -inline dword FetchUtf8(const char *&s, const char *lim) { bool ok; return FetchUtf8(s, lim, ok); } +wchar FetchUtf8(const char *&s, const char *lim, bool& ok); +inline wchar FetchUtf8(const char *&s, const char *lim) { bool ok; return FetchUtf8(s, lim, ok); } + +dword FetchUtf8(const char *&s, bool& ok); +inline wchar FetchUtf8(const char *&s) { bool ok; return FetchUtf8(s, ok); } bool CheckUtf8(const char *s, int len); -inline bool CheckUtf8(const char *s) { return CheckUtf8(s, (int)strlen(s)); } +inline bool CheckUtf8(const char *s) { return CheckUtf8(s, (int)strlen8(s)); } inline bool CheckUtf8(const String& s) { return CheckUtf8(~s, s.GetCount()); } -int Utf8Len(const dword *s, int len); -inline int Utf8Len(const dword *s) { return Utf8Len(s, strlen32(s)); } -inline int Utf8Len(const Vector& s) { return Utf8Len(s, s.GetCount()); } -inline int Utf8Len(dword code) { return Utf8Len(&code, 1); } - int Utf8Len(const wchar *s, int len); -inline int Utf8Len(const wchar *s) { return Utf8Len(s, wstrlen(s)); } +inline int Utf8Len(const wchar *s) { return Utf8Len(s, strlen32(s)); } +inline int Utf8Len(wchar code) { return Utf8Len(&code, 1); } inline int Utf8Len(const WString& s) { return Utf8Len(~s, s.GetCount()); } -void ToUtf8(char *t, const dword *s, int len); -String ToUtf8(const dword *s, int len); -inline String ToUtf8(const dword *s) { return ToUtf8(s, strlen32(s)); } -inline String ToUtf8(const Vector& s) { return ToUtf8(s, s.GetCount()); } -inline String ToUtf8(dword code) { return ToUtf8(&code, 1); } +int Utf8Len(const char16 *s, int len); +inline int Utf8Len(const char16 *s) { return Utf8Len(s, strlen16(s)); } +inline int Utf8Len(const Vector& s) { return Utf8Len(s, s.GetCount()); } void ToUtf8(char *t, const wchar *s, int len); String ToUtf8(const wchar *s, int len); -inline String ToUtf8(const wchar *s) { return ToUtf8(s, wstrlen(s)); } +inline String ToUtf8(const wchar *s) { return ToUtf8(s, strlen32(s)); } +inline String ToUtf8(wchar code) { return ToUtf8(&code, 1); } inline String ToUtf8(const WString& s) { return ToUtf8(~s, s.GetCount()); } -int Utf16Len(const dword *s, int len); -inline int Utf16Len(const dword *s) { return Utf16Len(s, strlen32(s)); } -inline int Utf16Len(const Vector& s) { return Utf16Len(s, s.GetCount()); } -inline int Utf16Len(dword code) { return Utf16Len(&code, 1); } +void ToUtf8(char *t, const char16 *s, int len); +String ToUtf8(const char16 *s, int len); +inline String ToUtf8(const char16 *s) { return ToUtf8(s, strlen16(s)); } +inline String ToUtf8(const Vector& s) { return ToUtf8(s, s.GetCount()); } + +int Utf16Len(const wchar *s, int len); +inline int Utf16Len(const wchar *s) { return Utf16Len(s, strlen32(s)); } +inline int Utf16Len(const WString& s) { return Utf16Len(s, s.GetCount()); } +inline int Utf16Len(wchar code) { return Utf16Len(&code, 1); } int Utf16Len(const char *s, int len); -inline int Utf16Len(const char *s) { return Utf16Len(s, (int)strlen(s)); } +inline int Utf16Len(const char *s) { return Utf16Len(s, (int)strlen8(s)); } inline int Utf16Len(const String& s) { return Utf16Len(~s, s.GetCount()); } -void ToUtf16(wchar *t, const dword *s, int len); -WString ToUtf16(const dword *s, int len); -inline WString ToUtf16(const dword *s) { return ToUtf16(s, strlen32(s)); } -inline WString ToUtf16(const Vector& s) { return ToUtf16(s, s.GetCount()); } -inline WString ToUtf16(dword code) { return ToUtf16(&code, 1); } +int ToUtf16(char16 *t, const wchar *s, int len); +Vector ToUtf16(const wchar *s, int len); +inline Vector ToUtf16(const wchar *s) { return ToUtf16(s, strlen32(s)); } +inline Vector ToUtf16(const WString& s) { return ToUtf16(s, s.GetCount()); } +inline Vector ToUtf16(wchar code) { return ToUtf16(&code, 1); } -void ToUtf16(wchar *t, const char *s, int len); -WString ToUtf16(const char *s, int len); -inline WString ToUtf16(const char *s) { return ToUtf16(s, (int)strlen(s)); } -inline WString ToUtf16(const String& s) { return ToUtf16(~s, s.GetCount()); } +int ToUtf16(char16 *t, const char *s, int len); +Vector ToUtf16(const char *s, int len); +inline Vector ToUtf16(const char *s) { return ToUtf16(s, (int)strlen8(s)); } +inline Vector ToUtf16(const String& s) { return ToUtf16(~s, s.GetCount()); } -int Utf32Len(const wchar *s, int len); -inline int Utf32Len(const wchar *s) { return Utf32Len(s, wstrlen(s)); } -inline int Utf32Len(const WString& s) { return Utf32Len(~s, s.GetCount()); } +int Utf32Len(const char16 *s, int len); +inline int Utf32Len(const char16 *s) { return Utf32Len(s, strlen16(s)); } +inline int Utf32Len(const Vector& s) { return Utf32Len(s, s.GetCount()); } int Utf32Len(const char *s, int len); -inline int Utf32Len(const char *s) { return Utf32Len(s, (int)strlen(s)); } +inline int Utf32Len(const char *s) { return Utf32Len(s, (int)strlen8(s)); } inline int Utf32Len(const String& s) { return Utf32Len(~s, s.GetCount()); } -dword ReadSurrogatePair(const wchar *s, const wchar *lim); +void ToUtf32(wchar *t, const char16 *s, int len); +WString ToUtf32(const char16 *s, int len); +inline WString ToUtf32(const char16 *s) { return ToUtf32(s, strlen16(s)); } +inline WString ToUtf32(const Vector& s) { return ToUtf32(s, s.GetCount()); } -void ToUtf32(dword *t, const wchar *s, int len); -Vector ToUtf32(const wchar *s, int len); -inline Vector ToUtf32(const wchar *s) { return ToUtf32(s, wstrlen(s)); } -inline Vector ToUtf32(const WString& s) { return ToUtf32(~s, s.GetCount()); } - -void ToUtf32(dword *t, const char *s, int len); -Vector ToUtf32(const char *s, int len); -inline Vector ToUtf32(const char *s) { return ToUtf32(s, (int)strlen(s)); } -inline Vector ToUtf32(const String& s) { return ToUtf32(~s, s.GetCount()); } +void ToUtf32(wchar *t, const char *s, int len); +WString ToUtf32(const char *s, int len); +inline WString ToUtf32(const char *s) { return ToUtf32(s, (int)strlen8(s)); } +inline WString ToUtf32(const String& s) { return ToUtf32(~s, s.GetCount()); } enum { MAX_DECOMPOSED = 18 }; -int UnicodeDecompose(dword codepoint, dword t[MAX_DECOMPOSED], bool only_canonical = false); -Vector UnicodeDecompose(dword codepoint, bool only_canonical = false); -dword UnicodeCompose(const dword *t, int count); -inline dword UnicodeCompose(const Vector& t) { return UnicodeCompose(t, t.GetCount()); } +int UnicodeDecompose(wchar codepoint, wchar t[MAX_DECOMPOSED], bool only_canonical = false); +WString UnicodeDecompose(wchar codepoint, bool only_canonical = false); +wchar UnicodeCompose(const WString& t); void SetDefaultCharset(byte charset); byte GetDefaultCharset(); @@ -127,62 +125,62 @@ extern byte unicode_fast_info__[2048]; extern byte unicode_fast_upper_ascii__[]; extern byte unicode_fast_lower_ascii__[]; -dword ToUpperRest_(dword c); -dword ToLowerRest_(dword c); -char ToAsciiRest_(dword c); -bool IsRTL_(dword c); -bool IsMark_(dword c); -bool IsLetter_(dword c); -bool IsUpper_(dword c); -bool IsLower_(dword c); +wchar ToUpperRest_(wchar c); +wchar ToLowerRest_(wchar c); +char ToAsciiRest_(wchar c); +bool IsRTL_(wchar c); +bool IsMark_(wchar c); +bool IsLetter_(wchar c); +bool IsUpper_(wchar c); +bool IsLower_(wchar c); -inline dword ToUpper(dword c) { return c < 2048 ? unicode_fast_upper__[c] : ToUpperRest_(c); } -inline dword ToLower(dword c) { return c < 2048 ? unicode_fast_lower__[c] : ToLowerRest_(c); } -inline char ToAscii(dword c) { return c < 2048 ? unicode_fast_ascii__[c] : ToAsciiRest_(c); } -inline char ToUpperAscii(dword c){ return c < 2048 ? unicode_fast_upper_ascii__[c] : (char)ToUpper(ToAsciiRest_(c)); } -inline char ToLowerAscii(dword c){ return c < 2048 ? unicode_fast_lower_ascii__[c] : (char)ToLower(ToAsciiRest_(c)); } -inline bool IsLower(dword c) { return c < 2048 ? unicode_fast_info__[c] & 1 : IsLower_(c); } -inline bool IsUpper(dword c) { return c < 2048 ? unicode_fast_info__[c] & 2 : IsUpper_(c); } -inline bool IsLetter(dword c) { return c < 2048 ? unicode_fast_info__[c] & 4 : IsLetter_(c); } +inline wchar ToUpper(wchar c) { return c < 2048 ? unicode_fast_upper__[c] : ToUpperRest_(c); } +inline wchar ToLower(wchar c) { return c < 2048 ? unicode_fast_lower__[c] : ToLowerRest_(c); } +inline char ToAscii(wchar c) { return c < 2048 ? unicode_fast_ascii__[c] : ToAsciiRest_(c); } +inline char ToUpperAscii(wchar c){ return c < 2048 ? unicode_fast_upper_ascii__[c] : (char)ToUpper(ToAsciiRest_(c)); } +inline char ToLowerAscii(wchar c){ return c < 2048 ? unicode_fast_lower_ascii__[c] : (char)ToLower(ToAsciiRest_(c)); } +inline bool IsLower(wchar c) { return c < 2048 ? unicode_fast_info__[c] & 1 : IsLower_(c); } +inline bool IsUpper(wchar c) { return c < 2048 ? unicode_fast_info__[c] & 2 : IsUpper_(c); } +inline bool IsLetter(wchar c) { return c < 2048 ? unicode_fast_info__[c] & 4 : IsLetter_(c); } -inline bool IsRTL(dword c) { return (dword)c >= 1470 && IsRTL_(c); } -inline bool IsMark(dword c) { return c < 0x300 ? false : c <= 0x36f ? true : IsMark_(c); } +inline bool IsRTL(wchar c) { return (wchar)c >= 1470 && IsRTL_(c); } +inline bool IsMark(wchar c) { return c < 0x300 ? false : c <= 0x36f ? true : IsMark_(c); } -inline bool IsLetter(int c) { return IsLetter((dword) c); } -inline bool IsUpper(int c) { return IsUpper((dword) c); } -inline bool IsLower(int c) { return IsLower((dword) c); } -inline int ToUpper(int c) { return ToUpper((dword) c); } -inline int ToLower(int c) { return ToLower((dword) c); } -inline char ToAscii(int c) { return ToAscii((dword) c); } -inline char ToUpperAscii(int c) { return ToUpperAscii((dword) c); } -inline char ToLowerAscii(int c) { return ToUpperAscii((dword) c); } +inline bool IsLetter(int c) { return IsLetter((wchar) c); } +inline bool IsUpper(int c) { return IsUpper((wchar) c); } +inline bool IsLower(int c) { return IsLower((wchar) c); } +inline int ToUpper(int c) { return ToUpper((wchar) c); } +inline int ToLower(int c) { return ToLower((wchar) c); } +inline char ToAscii(int c) { return ToAscii((wchar) c); } +inline char ToUpperAscii(int c) { return ToUpperAscii((wchar) c); } +inline char ToLowerAscii(int c) { return ToUpperAscii((wchar) c); } -inline bool IsLetter(char c) { return IsLetter((dword)(byte) c); } -inline bool IsUpper(char c) { return IsUpper((dword)(byte) c); } -inline bool IsLower(char c) { return IsLower((dword)(byte) c); } -inline dword ToUpper(char c) { return ToUpper((dword)(byte) c); } -inline dword ToLower(char c) { return ToLower((dword)(byte) c); } -inline char ToAscii(char c) { return ToAscii((dword)(byte) c); } -inline char ToUpperAscii(char c) { return ToUpperAscii((dword)(byte) c); } -inline char ToLowerAscii(char c) { return ToLowerAscii((dword)(byte) c); } +inline bool IsLetter(char c) { return IsLetter((wchar)(byte) c); } +inline bool IsUpper(char c) { return IsUpper((wchar)(byte) c); } +inline bool IsLower(char c) { return IsLower((wchar)(byte) c); } +inline wchar ToUpper(char c) { return ToUpper((wchar)(byte) c); } +inline wchar ToLower(char c) { return ToLower((wchar)(byte) c); } +inline char ToAscii(char c) { return ToAscii((wchar)(byte) c); } +inline char ToUpperAscii(char c) { return ToUpperAscii((wchar)(byte) c); } +inline char ToLowerAscii(char c) { return ToLowerAscii((wchar)(byte) c); } -inline bool IsLetter(signed char c) { return IsLetter((dword)(byte) c); } -inline bool IsUpper(signed char c) { return IsUpper((dword)(byte) c); } -inline bool IsLower(signed char c) { return IsLower((dword)(byte) c); } -inline dword ToUpper(signed char c) { return ToUpper((dword)(byte) c); } -inline dword ToLower(signed char c) { return ToLower((dword)(byte) c); } -inline char ToAscii(signed char c) { return ToAscii((dword)(byte) c); } -inline char ToUpperAscii(signed char c) { return ToUpperAscii((dword)(byte) c); } -inline char ToLowerAscii(signed char c) { return ToLowerAscii((dword)(byte) c); } +inline bool IsLetter(signed char c) { return IsLetter((wchar)(byte) c); } +inline bool IsUpper(signed char c) { return IsUpper((wchar)(byte) c); } +inline bool IsLower(signed char c) { return IsLower((wchar)(byte) c); } +inline wchar ToUpper(signed char c) { return ToUpper((wchar)(byte) c); } +inline wchar ToLower(signed char c) { return ToLower((wchar)(byte) c); } +inline char ToAscii(signed char c) { return ToAscii((wchar)(byte) c); } +inline char ToUpperAscii(signed char c) { return ToUpperAscii((wchar)(byte) c); } +inline char ToLowerAscii(signed char c) { return ToLowerAscii((wchar)(byte) c); } -inline bool IsLetter(wchar c) { return IsLetter((dword) c); } -inline bool IsUpper(wchar c) { return IsUpper((dword) c); } -inline bool IsLower(wchar c) { return IsLower((dword) c); } -inline dword ToUpper(wchar c) { return ToUpper((dword) c); } -inline dword ToLower(wchar c) { return ToLower((dword) c); } -inline char ToAscii(wchar c) { return ToAscii((dword) c); } -inline char ToUpperAscii(wchar c) { return ToUpperAscii((dword) c); } -inline char ToLowerAscii(wchar c) { return ToLowerAscii((dword) c); } +inline bool IsLetter(char16 c) { return IsLetter((wchar) c); } +inline bool IsUpper(char16 c) { return IsUpper((wchar) c); } +inline bool IsLower(char16 c) { return IsLower((wchar) c); } +inline wchar ToUpper(char16 c) { return ToUpper((wchar) c); } +inline wchar ToLower(char16 c) { return ToLower((wchar) c); } +inline char ToAscii(char16 c) { return ToAscii((wchar) c); } +inline char ToUpperAscii(char16 c) { return ToUpperAscii((wchar) c); } +inline char ToLowerAscii(char16 c) { return ToLowerAscii((wchar) c); } inline bool IsDigit(int c) { return c >= '0' && c <= '9'; } inline bool IsAlpha(int c) { return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; } @@ -198,13 +196,13 @@ String Utf8ToAscii(const String& src); String Utf8ToUpperAscii(const String& src); String Utf8ToLowerAscii(const String& src); -void ToUpper(wchar *t, const wchar *s, int len); -void ToLower(wchar *t, const wchar *s, int len); -void ToAscii(wchar *t, const wchar *s, int len); +void ToUpper(char16 *t, const char16 *s, int len); +void ToLower(char16 *t, const char16 *s, int len); +void ToAscii(char16 *t, const char16 *s, int len); -void ToUpper(wchar *s, int len); -void ToLower(wchar *s, int len); -void ToAscii(wchar *s, int len); +void ToUpper(char16 *s, int len); +void ToLower(char16 *s, int len); +void ToAscii(char16 *s, int len); bool IsLetter(int c, byte charset); bool IsUpper(int c, byte charset); @@ -253,32 +251,11 @@ bool SaveFileBOMUtf8(const char *path, const String& data); bool Utf8BOM(Stream& in); - -// Deprecated - -word UnicodeCombine(word chr, word combine); - -inline bool IsCJKIdeograph(int c) { return c >= 0x2e80 && c <= 0xdfaf || c >= 0xf900 && c <= 0xfaff; } - -int ToUnicode(int chr, byte charset); -int FromUnicode(wchar wchr, byte charset, int defchar = DEFAULTCHAR); - -void ToUnicode(wchar *ws, const char *s, int n, byte charset); -void FromUnicode(char *s, const wchar *ws, int n, byte charset, int defchar = DEFAULTCHAR); - WString ToUnicode(const String& src, byte charset); WString ToUnicode(const char *src, int n, byte charset); String FromUnicodeBuffer(const wchar *src, int len, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR); String FromUnicodeBuffer(const wchar *src); String FromUnicode(const WString& src, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR); -inline WString FromUtf8(const char *s, int len) { return ToUtf16(s, len); } -inline WString FromUtf8(const char *s) { return ToUtf16(s); } -inline WString FromUtf8(const String& s) { return ToUtf16(s); } - -inline bool utf8check(const char *s, int len) { return CheckUtf8(s, len); } - -inline int utf8len(const char *s, int len) { return Utf16Len(s, len); } -inline int utf8len(const char *s) { return Utf16Len(s); } -inline int lenAsUtf8(const wchar *s, int len) { return Utf8Len(s, len); } -inline int lenAsUtf8(const wchar *s) { return Utf8Len(s); } +int ToUnicode(int chr, byte charset); +int FromUnicode(wchar wchr, byte charset, int defchar = DEFAULTCHAR); diff --git a/uppsrc/Core/Core.h b/uppsrc/Core/Core.h index 5965f7955..0c3c34d2c 100644 --- a/uppsrc/Core/Core.h +++ b/uppsrc/Core/Core.h @@ -1,7 +1,7 @@ #ifndef CORE_H #define CORE_H -#define UPP_VERSION 0x20200200 +#define UPP_VERSION 0x20210900 #ifndef flagMT #define flagMT // MT is now always on @@ -63,6 +63,11 @@ #ifdef CPU_X86 #include + +#ifdef PLATFORM_WIN32 +#include +#endif + #endif #if defined(PLATFORM_POSIX) @@ -306,7 +311,6 @@ class JsonIO; #include "String.h" #include "TimeDate.h" -#include "Path.h" #include "Stream.h" #include "Diag.h" @@ -324,6 +328,8 @@ class JsonIO; #include "CharSet.h" +#include "Path.h" + #include "SplitMerge.h" #include "Other.h" diff --git a/uppsrc/Core/Cpu.cpp b/uppsrc/Core/Cpu.cpp index 99707a2ed..a5c785a9c 100644 --- a/uppsrc/Core/Cpu.cpp +++ b/uppsrc/Core/Cpu.cpp @@ -1,12 +1,8 @@ #include "Core.h" -#ifdef CPU_X86 -#ifdef COMPILER_MSC -#include -#else +#if !(defined(CPU_X86) && defined(COMPILER_MSC)) #include #endif -#endif #ifdef PLATFORM_FREEBSD #include diff --git a/uppsrc/Core/CvFlt.cpp b/uppsrc/Core/CvFlt.cpp index b69feec44..ee5a9adcf 100644 --- a/uppsrc/Core/CvFlt.cpp +++ b/uppsrc/Core/CvFlt.cpp @@ -167,7 +167,7 @@ int FormatDoubleDigits(const sF128& w, char *digits, int precision) } }; - auto D1 = [&](dword u) { *digits++ = u + '0'; }; + auto D1 = [&](dword u) { *digits++ = char(u + '0'); }; auto D2 = [&](dword u) { memcpy(digits, s100 + 2 * u, 2); digits += 2; }; auto D3 = [&](dword u) { int q = (5243 * u) >> 19; D1(q); D2(u - 100 * q); }; // bit faster than / % here @@ -182,24 +182,24 @@ int FormatDoubleDigits(const sF128& w, char *digits, int precision) auto U16 = [&] { u1 = u / 10000000000000000; u = u % 10000000000000000; }; switch(precision) { - case 1: FP(10); D1(u); break; - case 2: FP(100); D2(u); break; - case 3: FP(1000); D3(u); break; - case 4: FP(10000); D4(u); break; - case 5: FP(100000); D5(u); break; - case 6: FP(1000000); D6(u); break; - case 7: FP(10000000); D7(u); break; - case 8: FP(100000000); D8(u); break; - case 9: FP(1000000000); U8(); D1(u1); D8(u); break; - case 10: FP(10000000000); U8(); D2(u1); D8(u); break; - case 11: FP(100000000000); U8(); D3(u1); D8(u); break; - case 12: FP(1000000000000); U8(); D4(u1); D8(u); break; - case 13: FP(10000000000000); U8(); D5(u1); D8(u); break; - case 14: FP(100000000000000); U8(); D6(u1); D8(u); break; - case 15: FP(1000000000000000); U8(); D7(u1); D8(u); break; - case 16: FP(10000000000000000); U8(); D8(u1); D8(u); break; - case 17: FP(100000000000000000); U16(); D1(u1); U8(); D8(u1); D8(u); break; - case 18: FP(1000000000000000000u); U16(); D2(u1); U8(); D8(u1); D8(u); break; + case 1: FP(10); D1((dword)u); break; + case 2: FP(100); D2((dword)u); break; + case 3: FP(1000); D3((dword)u); break; + case 4: FP(10000); D4((dword)u); break; + case 5: FP(100000); D5((dword)u); break; + case 6: FP(1000000); D6((dword)u); break; + case 7: FP(10000000); D7((dword)u); break; + case 8: FP(100000000); D8((dword)u); break; + case 9: FP(1000000000); U8(); D1((dword)u1); D8((dword)u); break; + case 10: FP(10000000000); U8(); D2((dword)u1); D8((dword)u); break; + case 11: FP(100000000000); U8(); D3((dword)u1); D8((dword)u); break; + case 12: FP(1000000000000); U8(); D4((dword)u1); D8((dword)u); break; + case 13: FP(10000000000000); U8(); D5((dword)u1); D8((dword)u); break; + case 14: FP(100000000000000); U8(); D6((dword)u1); D8((dword)u); break; + case 15: FP(1000000000000000); U8(); D7((dword)u1); D8((dword)u); break; + case 16: FP(10000000000000000); U8(); D8((dword)u1); D8((dword)u); break; + case 17: FP(100000000000000000); U16(); D1((dword)u1); U8(); D8((dword)u1); D8((dword)u); break; + case 18: FP(1000000000000000000u); U16(); D2((dword)u1); U8(); D8((dword)u1); D8((dword)u); break; } return -e10; } diff --git a/uppsrc/Core/Defs.h b/uppsrc/Core/Defs.h index 6c05e0551..b5ef1149d 100644 --- a/uppsrc/Core/Defs.h +++ b/uppsrc/Core/Defs.h @@ -145,14 +145,16 @@ typedef short unsigned uint16; typedef unsigned long dword; typedef long int32; typedef unsigned long uint32; -typedef WCHAR wchar; +typedef WCHAR char16; + #else typedef unsigned int dword; typedef int int32; typedef unsigned int uint32; -typedef word wchar; +typedef word char16; #endif +typedef uint32 wchar; #ifdef COMPILER_MSC typedef __int64 int64; diff --git a/uppsrc/Core/FileMapping.cpp b/uppsrc/Core/FileMapping.cpp index 53941a2d5..05f2d9090 100644 --- a/uppsrc/Core/FileMapping.cpp +++ b/uppsrc/Core/FileMapping.cpp @@ -47,7 +47,7 @@ bool FileMapping::Open(const char *file, bool delete_share) write = false; #ifdef PLATFORM_WIN32 hfile = CreateFileW(ToSystemCharsetW(file), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | (delete_share && IsWinNT() ? FILE_SHARE_DELETE : 0), + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hfile == INVALID_HANDLE_VALUE) return false; diff --git a/uppsrc/Core/Format.cpp b/uppsrc/Core/Format.cpp index e9e0c2e29..420f90573 100644 --- a/uppsrc/Core/Format.cpp +++ b/uppsrc/Core/Format.cpp @@ -559,7 +559,7 @@ String DoubleFormatter(const Formatting& f) dword n; bool overflow = false; s = ScanUint(n, s, overflow); - if(overflow || !s || n > (wd ? 1000 : 100)) + if(overflow || !s || n > (wd ? 1000u : 100u)) return Null; (wd ? width : precision) = n; } diff --git a/uppsrc/Core/Heap.h b/uppsrc/Core/Heap.h index c3d343a9e..e1554b627 100644 --- a/uppsrc/Core/Heap.h +++ b/uppsrc/Core/Heap.h @@ -23,9 +23,6 @@ void *MemoryAlloc(size_t size); void MemoryFree(void *ptr); void *MemoryAlloc32(); void MemoryFree32(void *ptr); -void *MemoryAlloc48(); -void MemoryFree48(void *ptr); -void MemoryFreeThread(); void MemoryCheck(); void MemoryDumpLarge(); void MemoryDumpHuge(); diff --git a/uppsrc/Core/HeapImp.h b/uppsrc/Core/HeapImp.h index dcb103e22..12128ae7a 100644 --- a/uppsrc/Core/HeapImp.h +++ b/uppsrc/Core/HeapImp.h @@ -215,11 +215,11 @@ template bool BlkHeap::TryRealloc(void *ptr, size_t count, size_t& n) { ASSERT(count); - + BlkHeader *h = (BlkHeader *)ptr; if(h->size == 0) return false; - + word sz = h->GetSize(); if(sz != count) { if(!JoinNext(h, (word)count) && count > sz) @@ -271,7 +271,7 @@ struct Heap : BlkHeap { REMOTE_OUT_SZ = 2000, // maximum size of remote frees to be buffered to flush at once }; - + // allocator options: static word HPAGE; // size of master page, in 4KB units static int max_free_hpages; // maximum free master pages kept in reserve (if more, they are returned to the system) @@ -294,7 +294,7 @@ struct Heap : BlkHeap { static_assert(__countof(sz) == 23, "NKLASS mismatch"); return sz[k]; } - + struct FreeLink { FreeLink *next; }; @@ -316,16 +316,16 @@ struct Heap : BlkHeap { byte *End() { return (byte *)this + 4096; } int Count() { return (int)(uintptr_t)(End() - Begin()) / Ksz(klass); } }; - + struct LargeHeapDetail { BlkHeader_ freelist[25][1]; void LinkFree(BlkHeader_ *h); }; - + struct LargeHeap : BlkHeap {}; - + typedef LargeHeap::BlkHeader LBlkHeader; - + struct DLink : BlkPrefix { // Large Page header / big block header DLink *next; DLink *prev; @@ -339,7 +339,7 @@ struct Heap : BlkHeap { void LinkSelf() { Dbl_Self(this); } void Unlink() { Dbl_Unlink(this); } void Link(DLink *lnk) { Dbl_LinkAfter(this, lnk); } - + LargeHeap::BlkHeader *GetFirst() { return (LargeHeap::BlkHeader *)((byte *)this + LOFFSET); } // pointer to data area }; @@ -349,7 +349,7 @@ struct Heap : BlkHeap { static_assert(sizeof(BlkPrefix) == 16, "Wrong sizeof(BlkPrefix)"); static_assert(sizeof(DLink) == 64, "Wrong sizeof(DLink)"); - + static StaticMutex mutex; Page work[NKLASS][1]; // circular list of pages that contain some empty blocks @@ -363,7 +363,7 @@ struct Heap : BlkHeap { LargeHeap lheap; DLink large[1]; // all large 64KB chunks that belong to this heap int free_lpages; // empty large pages (in reserve) - + void *out[REMOTE_OUT_SZ / 8 + 1]; void **out_ptr; int out_size; @@ -377,9 +377,9 @@ struct Heap : BlkHeap { void *page; HugePage *next; }; - + static HugePage *huge_pages; - + static DLink big[1]; // List of all big blocks static Heap aux; // Single global auxiliary heap to store orphans and global list of free pages @@ -410,11 +410,11 @@ struct Heap : BlkHeap { void Init(); - static int CheckFree(FreeLink *l, int k); + static int CheckFree(FreeLink *l, int k, bool page = true); void Check(); static void DblCheck(Page *p); static void AssertLeaks(bool b); - + static bool IsSmall(void *ptr) { return (((dword)(uintptr_t)ptr) & 16) == 0; } static Page *GetPage(void *ptr) { return (Page *)((uintptr_t)ptr & ~(uintptr_t)4095); } @@ -546,4 +546,4 @@ void Heap::LargeFreeRemote() } LargeFreeRemoteRaw(list); } -} +} \ No newline at end of file diff --git a/uppsrc/Core/Lang.h b/uppsrc/Core/Lang.h index 673fffe6e..dcd91e3c0 100644 --- a/uppsrc/Core/Lang.h +++ b/uppsrc/Core/Lang.h @@ -68,9 +68,9 @@ public: WString GetIndexLetter(const wchar *text) const { return (*getindexletter)(text, language); } int Compare(const wchar *a, int alen, const wchar *b, int blen) const { return (*compare)(a, alen, b, blen, language); } - int Compare(const wchar *a, const wchar *b) const { return Compare(a, wstrlen(a), b, wstrlen(b)); } + int Compare(const wchar *a, const wchar *b) const { return Compare(a, strlen__(a), b, strlen__(b)); } int Compare(WString a, WString b) const { return Compare(a, a.GetLength(), b, b.GetLength()); } - int Compare(const char *a, const char *b) const { return Compare(ToUnicode(a, CHARSET_DEFAULT), ToUnicode(b, CHARSET_DEFAULT)); } + int Compare(const char *a, const char *b) const { return Compare(ToUtf32(a), ToUtf32(b)); } int Compare(String a, String b) const { return Compare(a.ToWString(), b.ToWString()); } bool operator()(const wchar *a, const wchar *b) const { return Compare(a, b) < 0; } diff --git a/uppsrc/Core/LangInfo.cpp b/uppsrc/Core/LangInfo.cpp index 35e668ebc..2cd362f57 100644 --- a/uppsrc/Core/LangInfo.cpp +++ b/uppsrc/Core/LangInfo.cpp @@ -193,14 +193,14 @@ int CSCZLanguageCompare(const wchar *a, int a_length, const wchar *b, int b_leng String GetLocaleInfoA(LCID lcid, LCTYPE lctype) { - wchar cbuf[1000]; + WCHAR cbuf[1000]; ::GetLocaleInfoW(lcid, lctype, cbuf, __countof(cbuf)); - return FromSystemCharsetW(cbuf); + return cbuf; } WString GetLocaleInfoW(LCID lcid, LCTYPE lctype) { - wchar wbuf[1000]; + WCHAR wbuf[1000]; Zero(wbuf); if(::GetLocaleInfoW(lcid, lctype, (WCHAR *)wbuf, __countof(wbuf))) return wbuf; diff --git a/uppsrc/Core/LocalProcess.cpp b/uppsrc/Core/LocalProcess.cpp index 95c53b622..c3839de92 100644 --- a/uppsrc/Core/LocalProcess.cpp +++ b/uppsrc/Core/LocalProcess.cpp @@ -68,14 +68,11 @@ static void sNoBlock(int fd) #ifdef PLATFORM_WIN32 bool Win32CreateProcess(const char *command, const char *envptr, STARTUPINFOW& si, PROCESS_INFORMATION& pi, const char *cd) { // provides conversion of charset for cmdline and envptr - WString wcmd(command); - int n = wcmd.GetCount() + 1; - WString wcd(cd); - Buffer cmd(n); - memcpy(cmd, wcmd, n * sizeof(wchar)); + Vector cmd = ToSystemCharsetW(command); + cmd.Add(0); #if 0 // unicode environment not necessary for now wchar wenvptr = NULL; - Buffer env(n); + Buffer env(n); if(envptr) { int len = 0; while(envptr[len] || envptr[len + 1]) @@ -85,7 +82,8 @@ bool Win32CreateProcess(const char *command, const char *envptr, STARTUPINFOW& s memcpy(env, wenv, (len + 2) * sizeof(wchar)); } #endif - return CreateProcessW(NULL, cmd, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, (void *)envptr, cd ? ~wcd : NULL, &si, &pi); + return CreateProcessW(NULL, cmd, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, (void *)envptr, + cd ? ToSystemCharsetW(cd).begin() : NULL, &si, &pi); } #endif diff --git a/uppsrc/Core/Mem.h b/uppsrc/Core/Mem.h index 5db192468..16b488073 100644 --- a/uppsrc/Core/Mem.h +++ b/uppsrc/Core/Mem.h @@ -641,4 +641,22 @@ int inline_memcmp_aligned(const char *a, const char *b, size_t count) } #endif +template +bool memeq_t(const T *p, const T *q, size_t count) +{ + if((sizeof(T) & 15) == 0) + return memeq128(p, q, count * (sizeof(T) >> 4)); + else + if((sizeof(T) & 7) == 0) + return memeq64(p, q, count * (sizeof(T) >> 3)); + else + if((sizeof(T) & 3) == 0) + return memeq32(p, q, count * (sizeof(T) >> 2)); + else + if((sizeof(T) & 1) == 0) + return memeq16(p, q, count * (sizeof(T) >> 1)); + else + return memeq8(p, q, count * sizeof(T)); +} + hash_t memhash(const void *ptr, size_t count); diff --git a/uppsrc/Core/NetNode.cpp b/uppsrc/Core/NetNode.cpp index 9aa47ab26..9532aa977 100644 --- a/uppsrc/Core/NetNode.cpp +++ b/uppsrc/Core/NetNode.cpp @@ -12,10 +12,10 @@ NetNode::NetNode() NetNode& NetNode::operator=(const NetNode& s) { net = s.net; - local = s.local; - remote = s.remote; - comment = s.comment; - provider = s.provider; + local = clone(s.local); + remote = clone(s.remote); + comment = clone(s.comment); + provider = clone(s.provider); name = s.name; path = s.path; SetPtrs(); @@ -30,25 +30,23 @@ String DosInitCaps(const char *name) return InitCaps(name); } -void NetNode::SetPtr(String& s, char *& ptr) -{ - if(ptr) ptr = (char *)~s; -} - void NetNode::SetPtrs() { + auto SetPtr = [](Vector& s, char16 *& ptr) { if(ptr) ptr = s; }; SetPtr(local, net.lpLocalName); SetPtr(remote, net.lpRemoteName); SetPtr(comment, net.lpComment); SetPtr(provider, net.lpProvider); } +/* void NetNode::Serialize(Stream& s) { s % net.dwScope % net.dwType % net.dwDisplayType % net.dwUsage; s % local % remote % comment % provider % name % path; SetPtrs(); } +*/ Array NetNode::Enum() const { @@ -78,34 +76,35 @@ Array NetNode::Enum0(HANDLE hEnum) { Array r; DWORD cEntries = (DWORD)-1, cbBuffer = 0x4000; - Buffer lpnr(cbBuffer); - while(::WNetEnumResource(hEnum, &cEntries, lpnr, &cbBuffer) == 0) { + Buffer lpnr(cbBuffer); + while(::WNetEnumResourceW(hEnum, &cEntries, lpnr, &cbBuffer) == 0) { for(int i = 0; i < (int)cEntries; i++) { - NETRESOURCE& sn = lpnr[i]; - const char *s = sn.lpRemoteName; + NETRESOURCEW& sn = lpnr[i]; + const WCHAR *s = sn.lpRemoteName; NetNode& nn = r.Add(); - NETRESOURCE& n = nn.net; + NETRESOURCEW& n = nn.net; n = sn; - nn.local = n.lpLocalName; - nn.remote = n.lpRemoteName; - nn.comment = n.lpComment; - nn.provider = n.lpProvider; + auto get = [](const char16 *s) { Vector x; while(s && *s) x.Add(*s++); x.Add(0); return x; }; + nn.local = get(n.lpLocalName); + nn.remote = get(n.lpRemoteName); + nn.comment = get(n.lpComment); + nn.provider = get(n.lpProvider); nn.SetPtrs(); if(s) { if(s[0] == '\\' && s[1] == '\\') - nn.name = FromSystemCharset(DosInitCaps(GetFileName(s))); + nn.name = DosInitCaps(GetFileName(FromSystemCharsetW(s))); else - nn.name = FromSystemCharset(s); + nn.name = FromSystemCharsetW(s); } if(n.lpComment && *n.lpComment) { if(nn.name.GetCount()) - nn.name = String().Cat() << FromSystemCharset(n.lpComment) + nn.name = String().Cat() << FromSystemCharsetW(n.lpComment) << " (" << nn.name << ")"; else - nn.name = FromSystemCharset(n.lpComment); + nn.name = FromSystemCharsetW(n.lpComment); } if(!(n.dwUsage & RESOURCEUSAGE_CONTAINER)) - nn.path = FromSystemCharset(n.lpRemoteName); + nn.path = FromSystemCharsetW(n.lpRemoteName); } } ::WNetCloseEnum(hEnum); diff --git a/uppsrc/Core/Ops.h b/uppsrc/Core/Ops.h index a993a3260..f7b3c99c5 100644 --- a/uppsrc/Core/Ops.h +++ b/uppsrc/Core/Ops.h @@ -233,8 +233,6 @@ byte addc64(uint64& result, const uint64& value, byte carry) { #elif defined(COMPILER_MSC) && defined(CPU_64) -#include - inline uint64 mul64(uint64 a, uint64 b, uint64& hi) { diff --git a/uppsrc/Core/Path.cpp b/uppsrc/Core/Path.cpp index 17904ae71..c098b2006 100644 --- a/uppsrc/Core/Path.cpp +++ b/uppsrc/Core/Path.cpp @@ -187,7 +187,7 @@ bool PathIsEqual(const char *p1, const char *p2) #ifndef PLATFORM_WINCE String GetCurrentDirectory() { #if defined(PLATFORM_WIN32) - wchar h[MAX_PATH]; + WCHAR h[MAX_PATH]; GetCurrentDirectoryW(MAX_PATH, h); return FromSystemCharsetW(h); #elif defined(PLATFORM_POSIX) @@ -211,7 +211,7 @@ bool SetCurrentDirectory(const char *path) String GetTempPath() { - wchar h[MAX_PATH]; + WCHAR h[MAX_PATH]; GetTempPathW(MAX_PATH, h); return FromSystemCharsetW(h); } @@ -253,7 +253,7 @@ String ToUnixName(const char* fn, const char* stop = NULL) { String GetFullPath(const char *file) { #ifdef PLATFORM_WIN32 String ufn = FromUnixName(file); - wchar h[MAX_PATH]; + WCHAR h[MAX_PATH]; GetFullPathNameW(ToSystemCharsetW(ufn), MAX_PATH, h, 0); return FromSystemCharsetW(h); #else @@ -364,10 +364,10 @@ static bool sGetSymLinkPath0(const char *linkpath, String *path) { bool ret = false; HRESULT hres; - IShellLink* psl; + IShellLinkW* psl; IPersistFile* ppf; CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (PVOID *) &psl); if(SUCCEEDED(hres)) { hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf); @@ -375,9 +375,9 @@ static bool sGetSymLinkPath0(const char *linkpath, String *path) hres = ppf->Load(ToSystemCharsetW(linkpath), STGM_READ); if(SUCCEEDED(hres)) { if(path) { - char fileW[_MAX_PATH] = {0}; + WCHAR fileW[_MAX_PATH] = {0}; psl->GetPath(fileW, _MAX_PATH, NULL, 0); - *path = FromSystemCharset(fileW); + *path = fileW; } else ret = true; @@ -950,20 +950,20 @@ Array FileSystemInfo::Find(String mask, int max_count, f.filename = "\\"; f.root_style = ROOT_FIXED; #elif defined(PLATFORM_WIN32) - char drive[4] = "?:\\"; + WCHAR drive[4] = L"?:\\"; for(int c = 'A'; c <= 'Z'; c++) { *drive = c; - int n = GetDriveType(drive); + int n = GetDriveTypeW(drive); if(n == DRIVE_NO_ROOT_DIR) continue; FileInfo& f = fi.Add(); f.filename = drive; - char name[256], system[256]; + WCHAR name[256], system[256]; DWORD d; if(c != 'A' && c != 'B' && n != DRIVE_UNKNOWN) { - bool b = GetVolumeInformation(drive, name, 256, &d, &d, &d, system, 256); + bool b = GetVolumeInformationW(drive, name, 256, &d, &d, &d, system, 256); if(b) { - if(*name) f.root_desc << " " << FromSystemCharset(name); + if(*name) f.root_desc << " " << FromSystemCharsetW(name); } else if(n == DRIVE_REMOVABLE || n == DRIVE_CDROM) { if(unmounted) { diff --git a/uppsrc/Core/Path.h b/uppsrc/Core/Path.h index 8f8922c82..50c608282 100644 --- a/uppsrc/Core/Path.h +++ b/uppsrc/Core/Path.h @@ -315,15 +315,14 @@ FileSystemInfo& StdFileSystemInfo(); #ifdef PLATFORM_WIN32 class NetNode : Moveable { - NETRESOURCE net; - String local, remote, comment, provider; + NETRESOURCEW net; + Vector local, remote, comment, provider; - String name; - String path; + String name; + String path; static void Copy(String& t, char *s); static Array Enum0(HANDLE hEnum); - static void SetPtr(String& s, char *& ptr); void SetPtrs(); @@ -334,14 +333,12 @@ public: String GetName() const { return name; } String GetPath() const { return path; } int GetDisplayType() const; - String GetRemote() const { return remote; } - String GetLocal() const { return local; } - String GetProvider() const { return provider; } - String GetComment() const { return comment; } + String GetRemote() const { return ToUtf8(remote); } + String GetLocal() const { return ToUtf8(local); } + String GetProvider() const { return ToUtf8(provider); } + String GetComment() const { return ToUtf8(comment); } Array Enum() const; - void Serialize(Stream& s); - static Array EnumRoot(); static Array EnumRemembered(); diff --git a/uppsrc/Core/SSL/InitExit.cpp b/uppsrc/Core/SSL/InitExit.cpp index 8ea5227f8..8923c0413 100644 --- a/uppsrc/Core/SSL/InitExit.cpp +++ b/uppsrc/Core/SSL/InitExit.cpp @@ -6,28 +6,25 @@ namespace Upp { static int64 UPP_SSL_alloc = 0; -static void *SslAlloc0(size_t size) -{ - LLOG("Alloc " << size); - size_t alloc = size + sizeof(int64); - int64 *aptr = (int64 *)MemoryAllocSz(alloc); - *aptr++ = (int64)alloc; - UPP_SSL_alloc += alloc; - LLOG("UPP_SSL_MALLOC(" << (int64)size << ", alloc " << alloc << ") -> " << FormatIntHex(aptr) << ", total = " << UPP_SSL_alloc); - return aptr; -} - #if OPENSSL_VERSION_NUMBER >= 0x10100000L -static void *SslAlloc(size_t size, const char *, int) +static void *SslAlloc(size_t size, const char *file, int line) #else static void *SslAlloc(size_t size) #endif { - return SslAlloc0(size); + size_t alloc = size + sizeof(int64); + int64 *aptr = (int64 *)MemoryAllocSz(alloc); + *aptr++ = (int64)alloc; + UPP_SSL_alloc += alloc; + LLOG("UPP_SSL_MALLOC(" << (int64)size << ", size " << size + << ", " << file << " " << line + << ") -> " << aptr << ", MemorySize: " << GetMemoryBlockSize(aptr) + << ", total = " << UPP_SSL_alloc << ", thread: " << Thread::GetCurrentId()); + return aptr; } #if OPENSSL_VERSION_NUMBER >= 0x10100000L -static void SslFree(void *ptr, const char *, int) +static void SslFree(void *ptr, const char *file, int line) #else static void SslFree(void *ptr) #endif @@ -36,35 +33,46 @@ static void SslFree(void *ptr) return; int64 *aptr = (int64 *)ptr - 1; UPP_SSL_alloc -= *aptr; - LLOG("UPP_SSL_FREE(" << ptr << ", alloc " << *aptr << "), total = " << UPP_SSL_alloc); + LLOG("UPP_SSL_FREE(" << ptr << ", size " << *aptr + << ", " << file << " " << line + << "), MemorySize: " << GetMemoryBlockSize(aptr) << ", total = " << UPP_SSL_alloc << ", thread: " << Thread::GetCurrentId()); + if(*aptr != GetMemoryBlockSize(aptr)) + Panic("SslFree corrupted"); MemoryFree(aptr); } #if OPENSSL_VERSION_NUMBER >= 0x10100000L -static void *SslRealloc(void *ptr, size_t size, const char *, int) +static void *SslRealloc(void *ptr, size_t size, const char *file, int line) #else static void *SslRealloc(void *ptr, size_t size) #endif { LLOG("SslRealloc " << ptr << ", " << size); - if(!ptr) - return SslAlloc0(size); + if(!ptr) { + LLOG("UPP_SSL_REALLOC by Alloc:"); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return SslAlloc(size, file, line); +#else + return SslAlloc(size); +#endif + } int64 *aptr = (int64 *)ptr - 1; - if((int64)(size + sizeof(int64)) <= *aptr) { - LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << *aptr << ") -> keep same block"); + if((int64)(size + sizeof(int64)) <= *aptr) { // TODO: Do we really want this? + LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << *aptr << ") -> keep same block" << ", thread: " << Thread::GetCurrentId()); return ptr; } size_t newalloc = size + sizeof(int64); int64 *newaptr = (int64 *)MemoryAllocSz(newalloc); if(!newaptr) { - LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << newalloc << ") -> fail"); + LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << newalloc << ") -> fail" << ", thread: " << Thread::GetCurrentId()); return NULL; } *newaptr++ = newalloc; memcpy(newaptr, ptr, min((int)(*aptr - sizeof(int64)), (int)size)); UPP_SSL_alloc += newalloc - *aptr; - LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << newalloc << ") -> " - << FormatIntHex(newaptr) << ", total = " << UPP_SSL_alloc); + LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << newalloc + << ", " << file << " " << line + << ") -> " << newaptr << ", total = " << UPP_SSL_alloc << ", thread: " << Thread::GetCurrentId()); MemoryFree(aptr); return newaptr; } @@ -74,7 +82,7 @@ void TcpSocketInit(); INITIALIZER(SSL) { MemoryIgnoreLeaksBlock __; - LLOG("SSL init"); + LLOG("SslInit"); TcpSocketInit(); CRYPTO_set_mem_functions(SslAlloc, SslRealloc, SslFree); SSL_library_init(); diff --git a/uppsrc/Core/Speller.cpp b/uppsrc/Core/Speller.cpp index 09d8a58c5..2efb96ca5 100644 --- a/uppsrc/Core/Speller.cpp +++ b/uppsrc/Core/Speller.cpp @@ -167,7 +167,7 @@ Speller *sGetSpeller(int lang) while(!user.IsEof()) { String s = user.GetLine(); if(!s.IsEmpty()) - f.user.Add(FromUtf8(s)); + f.user.Add(ToUtf32(s)); } if(in.Get() != 255) f.SetOld(LoadFile(path)); diff --git a/uppsrc/Core/SplitMerge.cpp b/uppsrc/Core/SplitMerge.cpp index 7f201381f..ec830d545 100644 --- a/uppsrc/Core/SplitMerge.cpp +++ b/uppsrc/Core/SplitMerge.cpp @@ -138,7 +138,7 @@ Vector Split(int maxcount, const wchar *s, const wchar *text, bool igno { SplitDelimWText delim; delim.ds = text; - delim.l = wstrlen(text); + delim.l = strlen__(text); return delim.l ? SplitGeneric(maxcount, delim, s, ignoreempty) : Vector(); } diff --git a/uppsrc/Core/StrUtil.cpp b/uppsrc/Core/StrUtil.cpp index 6951fd669..283102d15 100644 --- a/uppsrc/Core/StrUtil.cpp +++ b/uppsrc/Core/StrUtil.cpp @@ -2,11 +2,20 @@ namespace Upp { -int wstrlen(const wchar *s) +int strlen16(const char16 *s) { - const wchar *q = s; - while(*q) q++; - return (int)(q - s); + if(!s) return 0; + const char16 *s0 = s; + while(*s) s++; + return int(s - s0); +} + +int strlen32(const wchar *s) +{ + if(!s) return 0; + const wchar *s0 = s; + while(*s) s++; + return int(s - s0); } unsigned ctoi(int c) @@ -32,7 +41,7 @@ int CharFilterAscii128(int c) int CharFilterUnicode(int c) { - return c >= 32 && c < 65536 ? c : 0; + return c >= 32 && c < 0x10FFFF ? c : 0; } int CharFilterDigit(int c) diff --git a/uppsrc/Core/Stream.cpp b/uppsrc/Core/Stream.cpp index 92e9df196..716fe5f15 100644 --- a/uppsrc/Core/Stream.cpp +++ b/uppsrc/Core/Stream.cpp @@ -629,36 +629,29 @@ Stream& Stream::operator/(String& s) { return *this; } -Stream& Stream::operator%(WString& s) { +Stream& Stream::operator%(WString& s) +{ // we do not support BE here anymore if(IsError()) return *this; if(IsLoading()) { - dword len; - Pack(len); - if(len < 256 * 1024) { - WStringBuffer sb(len); - SerializeRaw((byte*)~sb, len * sizeof(wchar)); - s = sb; - } - else { - String h = GetAll(len * sizeof(wchar)); - if(h.IsVoid()) - LoadError(); - else { - WStringBuffer sb(len); - memcpy8(~sb, ~h, len * sizeof(wchar)); - s = sb; - } - } + dword len = Get(); + if(len == 0xff) + len = Get32le(); + String h = GetAll(len * sizeof(char16)); + if(h.IsVoid()) + LoadError(); + else + s = ToUtf32((const char16 *)~h, len); } else { - dword len = s.GetLength(); + Vector x = ToUtf16(s); + dword len = x.GetCount(); if(len < 0xff) Put(len); else { Put(0xff); Put32le(len); } - SerializeRaw((byte*)~s, len * sizeof(wchar)); + SerializeRaw((byte*)x.begin(), len * sizeof(char16)); } return *this; } @@ -667,7 +660,7 @@ Stream& Stream::operator/(WString& s) { if(IsError()) return *this; String h = ToUtf8(s); *this / h; - s = FromUtf8(h); + s = ToUtf32(h); return *this; } @@ -1082,32 +1075,28 @@ Stream& NilStream() return Single(); } -#ifdef PLATFORM_WIN32 -bool IsCoutUTF8; -#endif - -void CoutUTF8() -{ -#ifdef PLATFORM_WIN32 - IsCoutUTF8 = true; - SetConsoleOutputCP(65001); -#endif -} - #ifndef PLATFORM_WINCE class CoutStream : public Stream { +#ifdef PLATFORM_WIN32 String buffer; + void Flush() { + ONCELOCK { + SetConsoleOutputCP(65001); // set console to UTF8 mode + } + static HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + dword dummy; + WriteFile(h, ~buffer, buffer.GetCount(), &dummy, NULL); + buffer.Clear(); + } +#endif + + void Put0(int w) { #ifdef PLATFORM_WIN32 buffer.Cat(w); - if(CheckUtf8(buffer)) { // TODO: Use W api - String ws = ToSystemCharset(buffer, GetConsoleOutputCP()); - static HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); - dword dummy; - WriteFile(h, ~ws, ws.GetCount(), &dummy, NULL); - buffer.Clear(); - } + if(CheckUtf8(buffer) || buffer.GetCount() > 8) + Flush(); #else putchar(w); #endif diff --git a/uppsrc/Core/Stream.h b/uppsrc/Core/Stream.h index 2a00b971f..9c171a1ba 100644 --- a/uppsrc/Core/Stream.h +++ b/uppsrc/Core/Stream.h @@ -178,10 +178,6 @@ public: void PutLine(const char *s); void PutLine(const String& s); - void PutW(const wchar *s, int count) { Put(s, count * 2); } - dword GetW(wchar *s, int count) { return Get(s, count * 2) / 2; } - bool GetAllW(wchar *s, int count) { return GetAll(s, count * 2); } - void Put(Stream& s, int64 size = INT64_MAX, dword click = 4096); // Stream as serialization streamer @@ -253,6 +249,9 @@ public: void PutIL(int c) { Put32le(c); } void PutMW(int c) { Put16be(c); } void PutML(int c) { Put32be(c); } + void PutW(const char16 *s, int count) { Put(s, count * 2); } + dword GetW(char16 *s, int count) { return Get(s, count * 2) / 2; } + bool GetAllW(char16 *s, int count) { return GetAll(s, count * 2); } #endif private: // No copy Stream(const Stream& s); diff --git a/uppsrc/Core/String.cpp b/uppsrc/Core/String.cpp index eb71cc6ed..8013d7872 100644 --- a/uppsrc/Core/String.cpp +++ b/uppsrc/Core/String.cpp @@ -216,9 +216,12 @@ WString String::ToWString() const int String::GetCharCount() const { - return GetDefaultCharset() == CHARSET_UTF8 ? utf8len(Begin(), GetCount()) : GetCount(); + return GetDefaultCharset() == CHARSET_UTF8 ? Utf32Len(Begin(), GetCount()) : GetCount(); } +String::String(char16 *s) : String(ToUtf8(s)) {} +String::String(wchar *s) : String(ToUtf8(s)) {} + String::String(StringBuffer& b) { Zero(); @@ -354,26 +357,14 @@ struct StringICompare__ StringICompare__(int e) : encoding(e) {} }; -int CompareNoCase(const String& a, const String& b, byte encoding) +int CompareNoCase(const String& a, const String& b) { - if(encoding == CHARSET_DEFAULT) encoding = GetDefaultCharset(); - if(encoding == CHARSET_UTF8) return CompareNoCase(FromUtf8(a), FromUtf8(b)); -#ifdef DEPRECATED - return IterCompare(a.Begin(), a.End(), b.Begin(), b.End(), StringICompare__(encoding)); -#else - return CompareRanges(a, b, StringICompare__(encoding)); -#endif + return CompareNoCase(ToUtf32(a), ToUtf32(b)); } -int CompareNoCase(const String& a, const char *b, byte encoding) +int CompareNoCase(const String& a, const char *b) { - if(encoding == CHARSET_DEFAULT) encoding = GetDefaultCharset(); - if(encoding == CHARSET_UTF8) return CompareNoCase(FromUtf8(a), FromUtf8(b, (int)strlen(b))); -#ifdef DEPRECATED - return IterCompare(a.Begin(), a.End(), b, b + strlen(b), StringICompare__(encoding)); -#else - return CompareRanges(a, SubRange(b, b + strlen(b)), StringICompare__(encoding)); -#endif + return CompareNoCase(ToUtf32(a), ToUtf32(b, (int)strlen(b))); } } diff --git a/uppsrc/Core/String.h b/uppsrc/Core/String.h index dc8d6af8e..9a59c7369 100644 --- a/uppsrc/Core/String.h +++ b/uppsrc/Core/String.h @@ -1,6 +1,8 @@ class Nuller; -int wstrlen(const wchar *s); +inline int strlen8(const char *s) { return s ? (int)strlen(s) : 0; } +int strlen16(const char16 *s); +int strlen32(const wchar *s); #ifdef PLATFORM_POSIX inline int stricmp(const char *a, const char *b) { return strcasecmp(a, b); } @@ -12,12 +14,11 @@ inline int stricmp(const char *a, const char *b) { return _stricmp(a, b) inline int strnicmp(const char *a, const char *b, int n) { return _strnicmp(a, b, n); } #endif -force_inline int strlen__(const char *s) { return s ? (int)strlen(s) : 0; } - -inline int strlen__(const wchar *s) { return s ? (int)wstrlen(s) : 0; } +force_inline int strlen__(const char *s) { return strlen8(s); } +inline int strlen__(const wchar *s) { return strlen32(s); } inline int cmpval__(char x) { return (byte)x; } -inline int cmpval__(wchar x) { return (word)x; } +inline int cmpval__(wchar x) { return x; } int find(const char *text, int len, const char *needle, int nlen, int from); int find(const wchar *text, int len, const wchar *needle, int nlen, int from); @@ -391,6 +392,10 @@ public: String(int chr, int count) { String0::Zero(); Cat(chr, count); } String(StringBuffer& b); + + String(char16 *s); + String(wchar *s); + WString ToWString() const; const String& ToString() const { return *this; } @@ -618,12 +623,12 @@ inline String AsString(const String& s) { return s; } template<> inline hash_t GetHashValue(const String& s) { return s.GetHashValue(); } -int CompareNoCase(const String& a, const String& b, byte encoding = 0); -int CompareNoCase(const String& a, const char *b, byte encoding = 0); +int CompareNoCase(const String& a, const String& b); +int CompareNoCase(const String& a, const char *b); inline -int CompareNoCase(const char *a, const String& b, byte encoding = 0) { - return -CompareNoCase(b, a, encoding); +int CompareNoCase(const char *a, const String& b) { + return -CompareNoCase(b, a); } String TrimLeft(const String& s); @@ -774,8 +779,8 @@ public: int GetAlloc() const { return alloc; } hash_t GetHashValue() const { return memhash(ptr, length * sizeof(wchar)); } - bool IsEqual(const WString0& s) const { return s.length == length && memeq16(ptr, s.ptr, length); } - bool IsEqual(const wchar *s) const { int l = wstrlen(s); return l == GetCount() && memeq16(begin(), s, l); } + bool IsEqual(const WString0& s) const { return s.length == length && memeq_t(ptr, s.ptr, length); } + bool IsEqual(const wchar *s) const { int l = strlen__(s); return l == GetCount() && memeq_t(begin(), s, l); } int Compare(const WString0& s) const; void Remove(int pos, int count = 1); @@ -835,6 +840,8 @@ public: WString(const char *s, int n); WString(const char *s, const char *lim); + WString(const char16 *s); + static WString GetVoid(); bool IsVoid() const { return alloc < 0; } @@ -845,13 +852,13 @@ public: #ifndef _HAVE_NO_STDWSTRING WString(const std::wstring& s); - operator std::wstring() const; - std::wstring ToStd() const { return std::wstring(Begin(), End()); } + operator std::wstring() const { return ToStd(); } + std::wstring ToStd() const; #endif }; #ifndef _HAVE_NO_STDWSTRING -inline std::wstring to_string(const WString& s) { return std::wstring(s.Begin(), s.End()); } +inline std::wstring to_string(const WString& s) { return s.ToStd(); } #endif class WStringBuffer : NoCopy { @@ -885,7 +892,7 @@ public: void SetCount(int l) { SetLength(l); } int GetLength() const { return (int)(pend - pbegin); } int GetCount() const { return GetLength(); } - void Strlen() { SetLength(wstrlen(pbegin)); } + void Strlen() { SetLength(strlen__(pbegin)); } void Clear() { Free(); Zero(); } void Reserve(int r) { int l = GetLength(); SetLength(l + r); SetLength(l); } @@ -893,7 +900,7 @@ public: void Cat(int c, int count); void Cat(const wchar *s, int l); void Cat(const wchar *s, const wchar *e) { Cat(s, int(e - s)); } - void Cat(const wchar *s) { Cat(s, wstrlen(s)); } + void Cat(const wchar *s) { Cat(s, strlen__(s)); } void Cat(const WString& s) { Cat(s, s.GetLength()); } void Cat(const char *s) { Cat(WString(s)); } diff --git a/uppsrc/Core/StringFind.cpp b/uppsrc/Core/StringFind.cpp index ef5f25abf..d717259f4 100644 --- a/uppsrc/Core/StringFind.cpp +++ b/uppsrc/Core/StringFind.cpp @@ -123,8 +123,8 @@ int find(const char *text, int len, const char *needle, int nlen, int from) int find(const wchar *text, int len, const wchar *needle, int nlen, int from) { - int q = t_find<2>((const char *)text, 2 * len, (const char *)needle, 2 * nlen, 2 * from); - return q < 0 ? q : q / 2; + int q = t_find((const char *)text, sizeof(wchar) * len, (const char *)needle, sizeof(wchar) * nlen, sizeof(wchar) * from); + return q < 0 ? q : q / sizeof(wchar); } #else diff --git a/uppsrc/Core/UnicodeInfo.cpp b/uppsrc/Core/UnicodeInfo.cpp index bafeb392a..9cb32af78 100644 --- a/uppsrc/Core/UnicodeInfo.cpp +++ b/uppsrc/Core/UnicodeInfo.cpp @@ -76,12 +76,12 @@ struct UnicodeInfo { } }; - Index composed; - Index decomposed; // using String as the vessel for dwords + Index composed; + Index decomposed; int canonical_count; - Index lower; - Index upper; + Index lower; + Index upper; CharBits rtl; CharBits letter; CharBits islower; @@ -130,8 +130,8 @@ UnicodeInfo::UnicodeInfo() count += data[1]; for(int i = 0; i < count; i++) { composed.Add(data[i + 2]); - String h; - auto put = [&](dword c) { if(c) h.Cat((char *)&c, 4); }; + WString h; + auto put = [&](dword c) { if(c) h.Cat(c); }; put(data[i + count + 2]); put(data[i + 2 * count + 2]); put(data[i + 3 * count + 2]); @@ -143,11 +143,11 @@ UnicodeInfo::UnicodeInfo() int offset = 4 * count + 2; while(data[offset]) { - dword code = data[offset++]; + wchar code = data[offset++]; int ii = composed.Find(code); - String h = decomposed[ii]; + WString h = decomposed[ii]; while(data[offset]) - h.Cat((char *)&data[offset++], 4); + h.Cat(data[offset++]); decomposed.Set(ii, h); offset++; } @@ -169,54 +169,54 @@ UnicodeInfo::UnicodeInfo() Load(data, ismark, offset); } -static int sUnicodeDecompose(dword codepoint, dword *t, Vector *r, bool only_canonical) +static int sUnicodeDecompose(wchar codepoint, wchar *t, WString *r, bool only_canonical) { // TODO: Add hangul support const UnicodeInfo& f = Single(); int q = f.composed.Find(codepoint); if(q >= 0 && (!only_canonical || q < f.canonical_count)) { - String s = f.decomposed[q]; + const WString& s = f.decomposed[q]; if(r) - r->SetCount(s.GetCount() >> 2); - int i; - for(i = 0; 4 * i < s.GetCount(); i++) - (r ? (*r)[i] : t[i]) = ((const dword *)~s)[i]; - return i; + *r = s; + if(t) + memcpy(t, s, sizeof(wchar) * s.GetCount()); + return s.GetCount(); } return 0; } -int UnicodeDecompose(dword codepoint, dword t[MAX_DECOMPOSED], bool only_canonical) +int UnicodeDecompose(wchar codepoint, wchar t[MAX_DECOMPOSED], bool only_canonical) { return sUnicodeDecompose(codepoint, t, NULL, only_canonical); } -Vector UnicodeDecompose(dword codepoint, bool only_canonical) +WString UnicodeDecompose(wchar codepoint, bool only_canonical) { - Vector r; + WString r; sUnicodeDecompose(codepoint, NULL, &r, only_canonical); return r; } -dword UnicodeCompose(const dword *t, int count) +wchar UnicodeCompose(const WString& s) { + int count = s.GetCount(); if(count < 1 || count > 3) return 0; if(count == 1) - return t[0]; - String s((byte *)t, sizeof(dword) * count); + return *s; + const UnicodeInfo& f = Single(); int q = f.decomposed.Find(s); return q >= 0 && q < f.canonical_count ? f.composed[q] : 0; } -dword ToUpperRest_(dword c) +wchar ToUpperRest_(wchar c) { const UnicodeInfo& f = Single(); int q = f.lower.Find(c); return q >= 0 ? f.upper[q] : c; } -dword ToLowerRest_(dword c) +wchar ToLowerRest_(wchar c) { if(c == 0x1e9e) // Capital sharp S -> small sharp S (but not reverse direction) return 0xdf; @@ -233,7 +233,7 @@ dword ToLowerRest_(dword c) return q >= 0 ? f.lower[q] : c; } -char ToAsciiRest_(dword c) +char ToAsciiRest_(wchar c) { const UnicodeInfo& f = Single(); int q = f.composed.Find(c); @@ -243,27 +243,27 @@ char ToAsciiRest_(dword c) return ch >= ' ' && ch < 128 ? ch : ' '; } -bool IsRTL_(dword c) +bool IsRTL_(wchar c) { return Single().rtl.Get(c); } -bool IsLetter_(dword c) +bool IsLetter_(wchar c) { return Single().letter.Get(c); } -bool IsLower_(dword c) +bool IsLower_(wchar c) { return c != (dword)ToUpper((int)c) || Single().islower.Get(c); } -bool IsUpper_(dword c) +bool IsUpper_(wchar c) { return c != (dword)ToLower((int)c) || Single().isupper.Get(c); } -bool IsMark_(dword c) +bool IsMark_(wchar c) { return Single().ismark.Get(c); } diff --git a/uppsrc/Core/Utf.cpp b/uppsrc/Core/Utf.cpp index 3acf1bd32..4844c6c8c 100644 --- a/uppsrc/Core/Utf.cpp +++ b/uppsrc/Core/Utf.cpp @@ -2,138 +2,142 @@ namespace Upp { -int strlen32(const dword *s) -{ - const dword *s0 = s; - while(*s) s++; - return int(s - s0); -} - bool CheckUtf8(const char *s, int len) { - return FromUtf8_([](const byte *, dword){}, s, len); -} - -int Utf8Len(const dword *s, int len) -{ - int rlen = 0; - for(const dword *lim = s + len; s < lim; s++) - ToUtf8_([&](char) { rlen++; }, *s); - return rlen; -} - -void ToUtf8(char *t, const dword *s, int len) -{ - for(const dword *lim = s + len; s < lim; s++) - ToUtf8_([&](char c) { *t++ = c; }, *s); -} - -String ToUtf8(const dword *s, int len) -{ - String r; - for(const dword *lim = s + len; s < lim; s++) - ToUtf8_([&](char c) { r.Cat(c); }, *s); - return r; + return FromUtf8_([](wchar) {}, s, len); } int Utf8Len(const wchar *s, int len) { int rlen = 0; - FromUtf16_([&](const wchar *, dword code) { ToUtf8_([&](char c) { rlen++; }, code); }, s, len); + for(const wchar *lim = s + len; s < lim; s++) + ToUtf8_([&](char) { rlen++; }, *s); return rlen; } void ToUtf8(char *t, const wchar *s, int len) { - FromUtf16_([&](const wchar *, dword code) { ToUtf8_([&](char c) { *t++ = c; }, code); }, s, len); + for(const wchar *lim = s + len; s < lim; s++) + ToUtf8_([&](char c) { *t++ = c; }, *s); } String ToUtf8(const wchar *s, int len) { - StringBuffer r; - r.Reserve(len); - FromUtf16_([&](const wchar *, dword code) { ToUtf8_([&](char c) { r.Cat(c); }, code); }, s, len); - return String(r); + String r; + for(const wchar *lim = s + len; s < lim; s++) + ToUtf8_([&](char c) { r.Cat(c); }, *s); + return r; } -int Utf16Len(const dword *s, int len) +int Utf8Len(const char16 *s, int len) { int rlen = 0; - for(const dword *lim = s + len; s < lim; s++) - ToUtf16_([&](wchar) { rlen++; }, *s); + FromUtf16_([&](wchar code) { ToUtf8_([&](char c) { rlen++; }, code); }, s, len); return rlen; } -void ToUtf16(wchar *t, const dword *s, int len) +void ToUtf8(char *t, const char16 *s, int len) { - for(const dword *lim = s + len; s < lim; s++) - ToUtf16_([&](wchar c) { *t++ = c; }, *s); + FromUtf16_([&](wchar code) { ToUtf8_([&](char c) { *t++ = c; }, code); }, s, len); } -WString ToUtf16(const dword *s, int len) +String ToUtf8(const char16 *s, int len) { - WStringBuffer r; + StringBuffer r; r.Reserve(len); - for(const dword *lim = s + len; s < lim; s++) - ToUtf16_([&](wchar c) { r.Cat(c); }, *s); - return WString(r); + FromUtf16_([&](wchar code) { ToUtf8_([&](char c) { r.Cat(c); }, code); }, s, len); + return String(r); +} + +int Utf16Len(const wchar *s, int len) +{ + int rlen = 0; + for(const wchar *lim = s + len; s < lim; s++) + ToUtf16_([&](char16) { rlen++; }, *s); + return rlen; +} + +int ToUtf16(char16 *t, const wchar *s, int len) +{ + char16 *t0 = t; + for(const wchar *lim = s + len; s < lim; s++) + ToUtf16_([&](char16 c) { *t++ = c; }, *s); + return int(t - t0); +} + +Vector ToUtf16(const wchar *s, int len) +{ + Vector r; + r.Reserve(len); + for(const wchar *lim = s + len; s < lim; s++) + ToUtf16_([&](char16 c) { r.Add(c); }, *s); + return r; } int Utf16Len(const char *s, int len) { int rlen = 0; - FromUtf8_([&](const byte *, dword code) { ToUtf16_([&](wchar c) { rlen++; }, code); }, s, len); + FromUtf8_([&](wchar code) { + ToUtf16_([&](char16) { rlen++; }, code); + }, s, len); return rlen; } -void ToUtf16(wchar *t, const char *s, int len) +int ToUtf16(char16 *t, const char *s, int len) { - FromUtf8_([&](const byte *, dword code) { ToUtf16_([&](wchar c) { *t++ = c; }, code); }, s, len); + char16 *t0 = t; + FromUtf8_([&](wchar code) { + ToUtf16_([&](char16 c) { *t++ = c; }, code); + }, s, len); + return int(t - t0); } -WString ToUtf16(const char *s, int len) +Vector ToUtf16(const char *s, int len) { - WStringBuffer r; - FromUtf8_([&](const byte *, dword code) { ToUtf16_([&](wchar c) { r.Cat(c); }, code); }, s, len); - return WString(r); + Vector r; + FromUtf8_([&](wchar code) { + ToUtf16_([&](char16 c) { r.Add(c); } , code); + }, s, len); + return r; } int Utf32Len(const char *s, int len) { int rlen = 0; - FromUtf8_([&](const byte *, dword) { rlen++; }, s, len); + FromUtf8_([&](wchar) { rlen++; }, s, len); return rlen; } -void ToUtf32(dword *t, const char *s, int len) +void ToUtf32(wchar *t, const char *s, int len) { - FromUtf8_([&](const byte *, dword c) { *t++ = c; }, s, len); + FromUtf8_([&](wchar c) { *t++ = c; }, s, len); } -Vector ToUtf32(const char *s, int len) +WString ToUtf32(const char *s, int len) { - Vector r; - FromUtf8_([&](const byte *, dword c) { r.Add(c); }, s, len); - return r; + WStringBuffer r; + FromUtf8_([&](wchar c) { r.Cat(c); }, s, len); + return WString(r); } -int Utf32Len(const wchar *s, int len) +int Utf32Len(const char16 *s, int len) { int rlen = 0; - FromUtf16_([&](const wchar *, dword) { rlen++; }, s, len); + FromUtf16_([&](wchar) { rlen++; }, s, len); return rlen; } -void ToUtf32(dword *t, const wchar *s, int len) +void ToUtf32(wchar *t, const char16 *s, int len) { - FromUtf16_([&](const wchar *, dword c) { *t++ = c; }, s, len); + FromUtf16_([&](wchar c) { *t++ = c; }, s, len); } -Vector ToUtf32(const wchar *s, int len) +WString ToUtf32(const char16 *s, int len) { - Vector r; - FromUtf16_([&](const wchar *, dword c) { r.Add(c); }, s, len); - return r; + WStringBuffer r; + r.Reserve(len); + FromUtf16_([&](wchar c) { r.Cat(c); }, s, len); + return WString(r); } String Utf8ToAscii(const String& src) @@ -176,4 +180,4 @@ String Utf8ToLowerAscii(const String& src) return String(r); } -}; +}; \ No newline at end of file diff --git a/uppsrc/Core/Utf.hpp b/uppsrc/Core/Utf.hpp index 19b8dc319..099fceabd 100644 --- a/uppsrc/Core/Utf.hpp +++ b/uppsrc/Core/Utf.hpp @@ -1,5 +1,5 @@ template -force_inline bool ToUtf8_(Target t, dword codepoint) +force_inline bool ToUtf8_(Target t, wchar codepoint) { if(codepoint < 0x80) t((char)codepoint); @@ -29,7 +29,7 @@ force_inline bool ToUtf8_(Target t, dword codepoint) return true; } -force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok) +force_inline dword FetchUtf8(const char *&_s, bool nolim, const char *_lim, bool& ok) { const byte *s = (const byte *)_s; const byte *lim = (const byte *)_lim; @@ -41,14 +41,14 @@ force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok) else if(code >= 0xC2) { dword c; - if(code < 0xE0 && s + 1 < lim && + if(code < 0xE0 && (nolim || s + 1 < lim) && s[1] >= 0x80 && s[1] < 0xc0 && (c = ((code - 0xC0) << 6) + s[1] - 0x80) >= 0x80 && c < 0x800) { _s += 2; return c; } else - if(code < 0xF0 && s + 2 < lim && + if(code < 0xF0 && (nolim || s + 2 < lim) && s[1] >= 0x80 && s[1] < 0xc0 && s[2] >= 0x80 && s[2] < 0xc0 && (c = ((code - 0xE0) << 12) + ((s[1] - 0x80) << 6) + s[2] - 0x80) >= 0x800 && !(c >= 0xEE00 && c <= 0xEEFF)) { @@ -56,7 +56,7 @@ force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok) return c; } else - if(code < 0xF8 && s + 3 < lim && + if(code < 0xF8 && (nolim || s + 3 < lim) && s[1] >= 0x80 && s[1] < 0xc0 && s[2] >= 0x80 && s[2] < 0xc0 && s[3] >= 0x80 && s[3] < 0xc0 && (c = ((code - 0xF0) << 18) + ((s[1] - 0x80) << 12) + ((s[2] - 0x80) << 6) + s[3] - 0x80) >= 0x10000 && c < 0x110000) { @@ -69,13 +69,23 @@ force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok) return 0xEE00 + code; // ERROR ESCAPE } +force_inline dword FetchUtf8(const char *&s, const char *lim, bool& ok) +{ + return FetchUtf8(s, false, lim, ok); +} + +force_inline dword FetchUtf8(const char *&s, bool& ok) +{ + return FetchUtf8(s, true, NULL, ok); +} + template force_inline bool FromUtf8_(Target t, const char *s, size_t len) { bool ok = true; const char *lim = s + len; while(s < lim) - t((const byte *)s, FetchUtf8(s, lim, ok)); + t(FetchUtf8(s, lim, ok)); return ok; } @@ -83,36 +93,36 @@ template force_inline bool ToUtf16_(Target t, size_t codepoint) { if(codepoint < 0x10000) - t((wchar)codepoint); + t((char16)codepoint); else if(codepoint < 0x110000) { codepoint -= 0x10000; - t(wchar(0xD800 + (0x3ff & (codepoint >> 10)))); - t(wchar(0xDC00 + (0x3ff & codepoint))); + t(char16(0xD800 + (0x3ff & (codepoint >> 10)))); + t(char16(0xDC00 + (0x3ff & codepoint))); } else return false; return true; } -force_inline dword ReadSurrogatePair(const wchar *s, const wchar *lim) +force_inline wchar ReadSurrogatePair(const char16 *s, const char16 *lim) { return (*s & 0XFC00) == 0xD800 && s + 1 < lim && (s[1] & 0xFC00) == 0xDC00 ? - ((dword(s[0] & 0x3ff) << 10) | (s[1] & 0x3ff)) + 0x10000 : 0; + ((wchar(s[0] & 0x3ff) << 10) | (s[1] & 0x3ff)) + 0x10000 : 0; } template -force_inline void FromUtf16_(Target t, const wchar *s, size_t len) +force_inline void FromUtf16_(Target t, const char16 *s, size_t len) { - const wchar *lim = s + len; + const char16 *lim = s + len; while(s < lim) { - dword c = ReadSurrogatePair(s, lim); + wchar c = ReadSurrogatePair(s, lim); if(c) { - t(s, c); + t(c); s += 2; } else { - t(s, *s); + t(*s); s++; } } diff --git a/uppsrc/Core/Util.cpp b/uppsrc/Core/Util.cpp index 555badfeb..8a27d9f24 100644 --- a/uppsrc/Core/Util.cpp +++ b/uppsrc/Core/Util.cpp @@ -577,25 +577,13 @@ int ChNoInvalid(int c) return c == DEFAULTCHAR ? '_' : c; } -#ifdef PLATFORM_WINCE -WString ToSystemCharset(const String& src) -{ - return src.ToWString(); -} - -String FromSystemCharset(const WString& src) -{ - return src.ToString(); -} -#else - #ifdef PLATFORM_WIN32 String ToSystemCharset(const String& src, int cp) { - WString s = src.ToWString(); - int l = s.GetLength() * 5; + Vector s = ToUtf16(src); + int l = s.GetCount() * 8; StringBuffer b(l); - int q = WideCharToMultiByte(cp, 0, (const WCHAR *)~s, s.GetLength(), b, l, NULL, NULL); + int q = WideCharToMultiByte(cp, 0, s, s.GetCount(), b, l, NULL, NULL); if(q <= 0) return src; b.SetCount(q); @@ -609,12 +597,11 @@ String ToSystemCharset(const String& src) String FromWin32Charset(const String& src, int cp) { - WStringBuffer b(src.GetLength()); - int q = MultiByteToWideChar(cp, MB_PRECOMPOSED, ~src, src.GetLength(), (WCHAR*)~b, src.GetLength()); + Buffer b(src.GetLength()); + int q = MultiByteToWideChar(cp, MB_PRECOMPOSED, ~src, src.GetLength(), b, src.GetLength()); if(q <= 0) return src; - b.SetCount(q); - return WString(b).ToString(); + return ToUtf8(b, q); } String FromOEMCharset(const String& src) @@ -627,16 +614,6 @@ String FromSystemCharset(const String& src) return FromWin32Charset(src, CP_ACP); } -WString ToSystemCharsetW(const char *src) -{ - return String(src).ToWString(); -} - -String FromSystemCharsetW(const wchar *src) -{ - return WString(src).ToString(); -} - #else String ToSystemCharset(const String& src) { @@ -649,8 +626,39 @@ String FromSystemCharset(const String& src) return IsMainRunning() ? Filter(ToCharset(CHARSET_DEFAULT, src, GetLNGCharset(GetSystemLNG())), ChNoInvalid) : src; } #endif -#endif +Vector ToSystemCharsetW(const WString& src) +{ + Vector h = ToUtf16(src); + h.Add(0); + return h; +} + +Vector ToSystemCharsetW(const String& src) +{ + Vector h = ToUtf16(src); + h.Add(0); + return h; +} + +Vector ToSystemCharsetW(const wchar *src) +{ + Vector h = ToUtf16(src); + h.Add(0); + return h; +} + +Vector ToSystemCharsetW(const char *src) +{ + Vector h = ToUtf16(src); + h.Add(0); + return h; +} + +String FromSystemCharsetW(const char16 *src) +{ + return ToUtf8(src); +} static StaticMutex sGCfgLock; diff --git a/uppsrc/Core/Util.h b/uppsrc/Core/Util.h index 6884128a3..c2b8b71a2 100644 --- a/uppsrc/Core/Util.h +++ b/uppsrc/Core/Util.h @@ -158,17 +158,17 @@ String HexDecode(const char *s, const char *lim); inline String HexDecode(const char *s, int len) { return HexDecode(s, s + len); } inline String HexDecode(const String& s) { return HexDecode(~s, s.GetCount()); } -#ifdef PLATFORM_WINCE -WString ToSystemCharset(const String& src); -String FromSystemCharset(const WString& src); -#else String ToSystemCharset(const String& src, int cp); String ToSystemCharset(const String& src); String FromWin32Charset(const String& src, int cp); String FromSystemCharset(const String& src); -WString ToSystemCharsetW(const char *src); -String FromSystemCharsetW(const wchar *src); -#endif + +Vector ToSystemCharsetW(const WString& src); +Vector ToSystemCharsetW(const String& src); +Vector ToSystemCharsetW(const wchar *src); +Vector ToSystemCharsetW(const char *src); + +String FromSystemCharsetW(const char16 *src); #ifdef PLATFORM_WIN32 String FromOEMCharset(const String& src); diff --git a/uppsrc/Core/ValueUtil.cpp b/uppsrc/Core/ValueUtil.cpp index 5a3984aeb..8d2ef2285 100644 --- a/uppsrc/Core/ValueUtil.cpp +++ b/uppsrc/Core/ValueUtil.cpp @@ -289,21 +289,13 @@ bool ValueMap::Data::IsNull() const { } void ValueMap::Data::Serialize(Stream& s) { -#if !defined(_MSC_VER) || _MSC_VER > 1310 s % key % value; -#else - throw 0; -#endif } void ValueMap::Data::Xmlize(XmlIO& xio) { -#if !defined(_MSC_VER) || _MSC_VER > 1310 Upp::Xmlize(xio, key); Upp::Xmlize(xio, value); -#else - throw 0; -#endif } void ValueMap::Data::Jsonize(JsonIO& jio) diff --git a/uppsrc/Core/WString.cpp b/uppsrc/Core/WString.cpp index 71f539610..f9d6dade7 100644 --- a/uppsrc/Core/WString.cpp +++ b/uppsrc/Core/WString.cpp @@ -6,13 +6,13 @@ wchar *WString0::Alloc(int& count) { if(count <= SMALL) { count = SMALL; - wchar *p = (wchar *)MemoryAlloc48(); + wchar *p = (wchar *)MemoryAlloc((SMALL + 1) * sizeof(wchar)); return p; } size_t sz = sizeof(Atomic) + ((size_t)count + 1) * sizeof(wchar); Atomic *rc = (Atomic *)MemoryAllocSz(sz); if(count != INT_MAX) - count = int(((sz - sizeof(Atomic)) >> 1) - 1); + count = int(((sz - sizeof(Atomic)) / sizeof(wchar)) - 1); *rc = 1; return (wchar *)(rc + 1); } @@ -26,7 +26,7 @@ void WString0::Free() MemoryFree(&rc); } else - MemoryFree48(ptr); + MemoryFree(ptr); } } @@ -94,15 +94,8 @@ void WString0::Set0(const WString0& src) AtomicInc(Rc()); } else { - ptr = (wchar *)MemoryAlloc48(); - qword *t = (qword *)ptr; - qword *s = (qword *)src.ptr; - t[0] = s[0]; - t[1] = s[1]; - t[2] = s[2]; - t[3] = s[3]; - t[4] = s[4]; - t[5] = s[5]; + ptr = (wchar *)MemoryAlloc((SMALL + 1) * sizeof(wchar)); + memcpy(ptr, src.ptr, sizeof(wchar) * (SMALL + 1)); } Dsyn(); } @@ -224,6 +217,11 @@ WString::WString(const char *s) { *this = ToUnicode(s, s ? (int)strlen(s) : 0, CHARSET_DEFAULT); } +WString::WString(const char16 *s) { + Zero(); + *this = ToUtf32(s); +} + WString::WString(const char *s, int n) { Zero(); *this = ToUnicode(s, n, CHARSET_DEFAULT); @@ -249,30 +247,26 @@ WString WString::GetVoid() } #ifndef _HAVE_NO_STDWSTRING +static_assert(sizeof(wchar_t) == 4 || sizeof(wchar_t) == 2, "Invalid wchar_t size"); + WString::WString(const std::wstring& s) { - if(sizeof(std::wstring::value_type) == sizeof(wchar)) { - WString0::Set0((wchar *)s.c_str(), (int)s.length()); - } - else { - WString0::Zero(); - std::wstring::const_iterator i = s.begin(); - while(i < s.end()) - Cat(*i++); - } + WString0::Zero(); + if(sizeof(wchar_t) == 4) + *this = WString((const wchar *)s.c_str(), (int)s.size()); + if(sizeof(wchar_t) == 2) + *this = ToUtf32((char16 *)s.c_str(), (int)s.size()); } -WString::operator std::wstring() const +std::wstring WString::ToStd() const { - if(sizeof(std::wstring::value_type) == sizeof(wchar)) - return std::wstring((std::wstring::value_type *)Begin(), - (std::wstring::value_type *)End()); - else { - std::wstring r; - const wchar *s = Begin(); - while(s < End()) - r += *s++; - return r; + if(sizeof(wchar_t) == 4) { + const wchar *s = begin(); + return std::wstring((const wchar_t *)begin(), GetCount()); + } + if(sizeof(wchar_t) == 2) { + Vector h = ToUtf16(*this); + return std::wstring((const wchar_t *)h.begin(), h.GetCount()); } } #endif @@ -286,14 +280,14 @@ void WStringBuffer::Zero() wchar *WStringBuffer::Alloc(int count, int& alloc) { if(count <= 23) { - wchar *s = (wchar *)MemoryAlloc48(); + wchar *s = (wchar *)MemoryAlloc(24 * sizeof(wchar)); alloc = WString0::SMALL; return s; } else { size_t sz = sizeof(Atomic) + ((size_t)count + 1) * sizeof(wchar); Atomic *rc = (Atomic *)MemoryAlloc(sz); - alloc = (int)min((size_t)INT_MAX, ((sz - sizeof(Atomic)) >> 1) - 1); + alloc = (int)min((size_t)INT_MAX, ((sz - sizeof(Atomic)) / sizeof(wchar)) - 1); ASSERT(alloc >= 0); *rc = 1; return (wchar *)(rc + 1); @@ -304,7 +298,7 @@ void WStringBuffer::Free() { int all = (int)(limit - pbegin); if(all == WString0::SMALL) - MemoryFree48(pbegin); + MemoryFree(pbegin); if(all > WString0::SMALL) MemoryFree((Atomic *)pbegin - 1); } @@ -357,7 +351,7 @@ void WStringBuffer::Cat(int c, int l) { if(pend + l > limit) Expand(max(GetLength(), l) + GetLength(), NULL, l); - memset16(pend, c, l); + memset32(pend, c, l); pend += l; } @@ -408,9 +402,9 @@ int CompareNoCase(const WString& a, const WString& b) int CompareNoCase(const WString& a, const wchar *b) { #ifdef DEPRECATED - return IterCompare(a.Begin(), a.End(), b, b + wstrlen(b), WStringICompare__()); + return IterCompare(a.Begin(), a.End(), b, b + strlen__(b), WStringICompare__()); #else - return CompareRanges(a, SubRange(b, b + wstrlen(b)), WStringICompare__()); + return CompareRanges(a, SubRange(b, b + strlen__(b)), WStringICompare__()); #endif } diff --git a/uppsrc/Core/Win32Util.cpp b/uppsrc/Core/Win32Util.cpp index b2aeebc62..57fc986a5 100644 --- a/uppsrc/Core/Win32Util.cpp +++ b/uppsrc/Core/Win32Util.cpp @@ -158,14 +158,14 @@ void DeleteWinReg(const String& key, HKEY base, dword wow) { } String GetSystemDirectory() { - char temp[MAX_PATH]; + WCHAR temp[MAX_PATH]; *temp = 0; - ::GetSystemDirectory(temp, sizeof(temp)); - return FromSystemCharset(temp); + ::GetSystemDirectoryW(temp, sizeof(temp)); + return FromSystemCharsetW(temp); } String GetWindowsDirectory() { - wchar temp[MAX_PATH]; + WCHAR temp[MAX_PATH]; *temp = 0; GetWindowsDirectoryW(temp, sizeof(temp)); return FromSystemCharsetW(temp); @@ -179,7 +179,7 @@ void *GetDllFn(const char *dll, const char *fn) } String GetModuleFileName(HINSTANCE instance) { - wchar h[_MAX_PATH]; + WCHAR h[_MAX_PATH]; GetModuleFileNameW(instance, h, _MAX_PATH); return FromSystemCharsetW(h); } diff --git a/uppsrc/Core/Xmlize.cpp b/uppsrc/Core/Xmlize.cpp index 7d038a60c..d5e2c67fe 100644 --- a/uppsrc/Core/Xmlize.cpp +++ b/uppsrc/Core/Xmlize.cpp @@ -31,12 +31,12 @@ void Xmlize(XmlIO& xml, WString& var) h = ToUtf8(var); Xmlize(xml, h); if(xml.IsLoading()) - var = FromUtf8(h); + var = ToUtf32(h); } template<> void XmlAttrLoad(WString& var, const String& text) { - var = FromUtf8(text); + var = ToUtf32(text); } template<> String XmlAttrStore(const WString& var) diff --git a/uppsrc/Core/config.h b/uppsrc/Core/config.h index 2267fa730..3a4f44deb 100644 --- a/uppsrc/Core/config.h +++ b/uppsrc/Core/config.h @@ -185,4 +185,6 @@ #define CPP_11 #endif +#define WCHAR32 1 // this version of U++ has 32 bit wchar + #endif diff --git a/uppsrc/Core/heap.cpp b/uppsrc/Core/heap.cpp index b0bd6252a..24787e07d 100644 --- a/uppsrc/Core/heap.cpp +++ b/uppsrc/Core/heap.cpp @@ -125,11 +125,37 @@ void Heap::DblCheck(Page *p) while(p != l); } -int Heap::CheckFree(FreeLink *l, int k) +int Heap::CheckFree(FreeLink *l, int k, bool pg) { + char h[200]; int n = 0; + + Page *page = GetPage(l); + + if(l && page->klass != k) { + sprintf(h, "Invalid freelist block at 0x%p sz: %d (klass mismatch)", l, Ksz(k)); + Panic(h); + } + while(l) { + if(l->next) { + Page *lp = GetPage(l->next); + if(pg && lp != page) { + sprintf(h, "Invalid freelist block at 0x%p sz: %d (out of page) (-> 0x%p)", l, Ksz(k), l->next); + Panic(h); + } + if((4096 - ((uintptr_t)(l->next) & (uintptr_t)4095)) % Ksz(k) != 0) { + sprintf(h, "Invalid freelist block at 0x%p sz: %d (invalid address)", l, Ksz(k)); + Panic(h); + } + if(lp->klass != k) { + sprintf(h, "Invalid freelist block at 0x%p sz: %d (next klass mismatch)", l, Ksz(k)); + Panic(h); + } + } + DbgFreeCheckK(l, k); + l = l->next; n++; } @@ -167,7 +193,7 @@ void Heap::Check() { break; p = p->next; } - CheckFree(cache[i], i); + CheckFree(cache[i], i, false); } DLink *l = large->next; diff --git a/uppsrc/Core/heapdbg.cpp b/uppsrc/Core/heapdbg.cpp index a89be21b7..6b14d2073 100644 --- a/uppsrc/Core/heapdbg.cpp +++ b/uppsrc/Core/heapdbg.cpp @@ -174,8 +174,6 @@ size_t GetMemoryBlockSize(void *ptr) void *MemoryAlloc32() { return MemoryAlloc(32); } void MemoryFree32(void *ptr) { return MemoryFree(ptr); } -void *MemoryAlloc48() { return MemoryAlloc(48); } -void MemoryFree48(void *ptr) { return MemoryFree(ptr); } void MemoryCheckDebug() { diff --git a/uppsrc/Core/lheap.cpp b/uppsrc/Core/lheap.cpp index 8a5264533..8894ed008 100644 --- a/uppsrc/Core/lheap.cpp +++ b/uppsrc/Core/lheap.cpp @@ -203,7 +203,7 @@ bool Heap::TryRealloc(void *ptr, size_t& newsize) return true; } } - + Mutex::Lock __(mutex); if(h->heap == NULL) { // this is big block LTIMING("Big realloc"); @@ -211,7 +211,7 @@ bool Heap::TryRealloc(void *ptr, size_t& newsize) DLink *d = (DLink *)h - 1; size_t count = (newsize + sizeof(DLink) + sizeof(BlkPrefix) + 4095) >> 12; - + if(HugeTryRealloc(d, count)) { big_size -= d->size; d->size = newsize = (count << 12) - sizeof(DLink) - sizeof(BlkPrefix); @@ -220,21 +220,23 @@ bool Heap::TryRealloc(void *ptr, size_t& newsize) } } + // TODO: When small block fits, we could still return true + return false; } size_t Heap::LGetBlockSize(void *ptr) { - LBlkHeader *h = (LBlkHeader *)ptr - 1; + BlkPrefix *h = (BlkPrefix *)ptr - 1; if(h->heap == NULL) { // huge block Mutex::Lock __(mutex); - DLink *h = (DLink *)ptr - 1; - return h->size; + DLink *hh = (DLink *)h - 1; + return hh->size; } - - return h->GetSize(); + + return ((int)h->GetSize() * LUNIT) - sizeof(BlkPrefix); } #endif -} +} \ No newline at end of file diff --git a/uppsrc/Core/sheap.cpp b/uppsrc/Core/sheap.cpp index dd67b46e8..454da0f49 100644 --- a/uppsrc/Core/sheap.cpp +++ b/uppsrc/Core/sheap.cpp @@ -388,6 +388,8 @@ struct HeapMutexLock { ~HeapMutexLock() { LeaveHeapMutex(); } }; +void MemoryFreeThread(); + struct HeapExitThreadGuard { void Used() {} ~HeapExitThreadGuard() { MemoryFreeThread(); } @@ -608,31 +610,6 @@ void MemoryFree32_i(void *ptr) void MemoryFree32(void *ptr) { MemoryFree32_i(ptr); } -void *MemoryAlloc48() -{ - LTIMING("MemoryAlloc48"); - Heap *heap = heap_tls__; - if(heap) - return LogAlloc(heap->Alloc48(), 48); - else { - HeapMutexLock __; - return LogAlloc(MakeHeap()->Alloc48(), 48); - } -} - -void MemoryFree48(void *ptr) -{ - LTIMING("MemoryFree48"); - LogFree(ptr); - Heap *heap = heap_tls__; - if(heap) - heap->Free48(ptr); - else { - HeapMutexLock __; - MakeHeap()->Free48(ptr); - } -} - #endif void MemoryFreeThread() diff --git a/uppsrc/Core/src.tpp/Heap_en-us.tpp b/uppsrc/Core/src.tpp/Heap_en-us.tpp index 0cd439ae9..efb4c5ced 100644 --- a/uppsrc/Core/src.tpp/Heap_en-us.tpp +++ b/uppsrc/Core/src.tpp/Heap_en-us.tpp @@ -58,18 +58,6 @@ This has the same functionality as MemoryFree([%-*@3 ptr]), but is slightly faster.&] [s3;%% &] [s4; &] -[s5;:Upp`:`:MemoryAlloc48`(`): [@(0.0.255) void]_`*[* MemoryAlloc48]()&] -[s2;%% Allocates memory block of exactly 48 bytes. This has the same -functionality as MemoryAlloc(32), but is slightly faster.&] -[s3; &] -[s4; &] -[s5;:Upp`:`:MemoryFree48`(void`*`): [@(0.0.255) void]_[* MemoryFree48]([@(0.0.255) void]_`* -[*@3 ptr])&] -[s2;%% Frees a memory block previously allocated by MemoryAlloc48. -This has the same functionality as MemoryFree([%-*@3 ptr]), but -is slightly faster.&] -[s3;%% &] -[s4; &] [s5;:Upp`:`:MemoryTryRealloc`(void`*`,size`_t`&`): [@(0.0.255) bool]_[* MemoryTryRealloc]( [@(0.0.255) void]_`*[*@3 ptr], [_^size`_t^ size`_t][@(0.0.255) `&]_[*@3 newsize])&] [s2;%% Attempts to change the size of block at [%-*@3 ptr] to something diff --git a/uppsrc/Core/src.tpp/StreamFn_en-us.tpp b/uppsrc/Core/src.tpp/StreamFn_en-us.tpp index ffd56d5f4..97d2edce4 100644 --- a/uppsrc/Core/src.tpp/StreamFn_en-us.tpp +++ b/uppsrc/Core/src.tpp/StreamFn_en-us.tpp @@ -1,5 +1,4 @@ topic "Stream utilities"; -[2 $$0,0#00000000000000000000000000000000:Default] [i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] [l288;2 $$2,0#27521748481378242620020725143825:desc] [0 $$3,0#96390100711032703541132217272105:end] @@ -9,6 +8,7 @@ topic "Stream utilities"; [l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param] [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [b42;2 $$9,9#13035079074754324216151401829390:normal] +[2 $$0,0#00000000000000000000000000000000:Default] [{_} [ {{10000@(113.42.0) [s0;%% [*@2;4 Stream helpers]]}}&] [s0;%% &] @@ -40,16 +40,9 @@ stream. Returns the actual number of bytes copied. With default [%-*@3 count] value it copies all data from [%-*@3 src] until EOF.&] [s3; &] [s4; &] -[s5;:CoutUTF8`(`): [@(0.0.255) void]_[* CoutUTF8]()&] -[s2;%% In Win32, setups console output for UTF8. NOP in POSIX.&] -[s3; &] -[s4; &] [s5;:Cout`(`): [_^Stream^ Stream][@(0.0.255) `&]_[* Cout]()&] [s2;%% Returns special output stream representing console output. -Data written to this stream are displayed as characters in console. -In Win32, encoding is converted to default console encoding, -or is not convereted at all if CoutUTF8 was called.&] -[s7;%% [*/ Return value]-|Console stream.&] +Data written to this stream are displayed as characters in console.&] [s3; &] [s4; &] [s5;:Cerr`(`): [_^Stream^ Stream][@(0.0.255) `&]_[* Cerr]()&] diff --git a/uppsrc/Core/src.tpp/Stream_en-us.tpp b/uppsrc/Core/src.tpp/Stream_en-us.tpp index 0876db3ae..ea2a36be6 100644 --- a/uppsrc/Core/src.tpp/Stream_en-us.tpp +++ b/uppsrc/Core/src.tpp/Stream_en-us.tpp @@ -704,37 +704,6 @@ as 0 is considered as NULL pointer too...&] [s7; [%-*C@3 count]-|Repeat count.&] [s3; &] [s4;%- &] -[s5;:Stream`:`:PutW`(const wchar`*`,int`):%- [@(0.0.255) void]_[* PutW]([@(0.0.255) const]_ -[_^topic`:`/`/Core`/src`/PrimitiveDataTypes`$en`-us`#Upp`:`:wchar`:`:typedef^ wchar -]_`*[*@3 s], [@(0.0.255) int]_[*@3 count])&] -[s2; Writes a specified number of wchars (16`-bit character values) -to the stream in platform specific format (little`-endian or -big`-endian).&] -[s7; [%-*C@3 s]-|String to write.&] -[s7; [%-*C@3 count]-|Length of string.&] -[s3; &] -[s4;%- &] -[s5;:Stream`:`:GetW`(wchar`*`,int`):%- [_^topic`:`/`/Core`/src`/PrimitiveDataTypes`$en`-us`#Upp`:`:dword`:`:typedef^ d -word]_[* GetW]([_^topic`:`/`/Core`/src`/PrimitiveDataTypes`$en`-us`#Upp`:`:wchar`:`:typedef^ w -char]_`*[*@3 s], [@(0.0.255) int]_[*@3 count])&] -[s2; Reads a specified number of wchars (16`-bit character values) -from the stream in platform specific format.&] -[s7; [%-*C@3 s]-|Pointer to buffer to receive wchars.&] -[s7; [%-*C@3 count]-|Number of wchars.&] -[s7; [*/ Return value]-|Number of wchars actually read.&] -[s3; &] -[s4;%- &] -[s5;:Stream`:`:GetAllW`(wchar`*`,int`):%- [@(0.0.255) bool]_[* GetAllW]([_^topic`:`/`/Core`/src`/PrimitiveDataTypes`$en`-us`#Upp`:`:wchar`:`:typedef^ w -char]_`*[*@3 s], [@(0.0.255) int]_[*@3 count])&] -[s2; Reads a specified number of wchars (16`-bit character values) -from the stream in platform specific format. If there is not -enough data in the stream, LoadError is invoked (that in turn -might throw an exception).&] -[s7; [%-*C@3 s]-|&] -[s7; [%-*C@3 count]-|&] -[s7; [*/ Return value]-|&] -[s3; &] -[s4;%- &] [s5;:Stream`:`:PutCrLf`(`):%- [@(0.0.255) void]_[* PutCrLf]()&] [s2; Writes CR`-LF pair to the stream. &] [s3; &] diff --git a/uppsrc/Core/src.tpp/String_en-us.tpp b/uppsrc/Core/src.tpp/String_en-us.tpp index 27d18d1bf..f4a8bd64f 100644 --- a/uppsrc/Core/src.tpp/String_en-us.tpp +++ b/uppsrc/Core/src.tpp/String_en-us.tpp @@ -109,7 +109,8 @@ td`::string][@(0.0.255) `&]_[*@3 s])&] st]&] [s2; Returns a number of characters contained in String. This is equal GetCount() if default charset is not UTF`-8, but different -for UTF`-8. It is faster equivalent of ToWString().GetCount().&] +for UTF`-8 where it returns a number of unicode codepoints. It +is faster equivalent of ToWString().GetCount().&] [s3;%- &] [s4;%- &] [s5;:String`:`:ToWString`(`)const:%- [_^WString^ WString]_[* ToWString]()_[@(0.0.255) const diff --git a/uppsrc/CppBase/ppfile.cpp b/uppsrc/CppBase/ppfile.cpp index e2723bbb8..9f10b0f7b 100644 --- a/uppsrc/CppBase/ppfile.cpp +++ b/uppsrc/CppBase/ppfile.cpp @@ -411,12 +411,17 @@ void InvalidateFileTimeCache(const String& path) Time GetFileTimeCached(const String& p) { LTIMING("GetFileTimeCached"); - Mutex::Lock __(s_PathFileTimeMutex); - int q = s_PathFileTime.Find(p); - if(q >= 0) - return s_PathFileTime[q]; + { + Mutex::Lock __(s_PathFileTimeMutex); + int q = s_PathFileTime.Find(p); + if(q >= 0) + return s_PathFileTime[q]; + } Time m = FileGetTime(p); - s_PathFileTime.Put(p, m); + { + Mutex::Lock __(s_PathFileTimeMutex); + s_PathFileTime.Put(p, m); + } return m; } diff --git a/uppsrc/CtrlCore/CocoClip.mm b/uppsrc/CtrlCore/CocoClip.mm index b853ddec9..a51893d0e 100644 --- a/uppsrc/CtrlCore/CocoClip.mm +++ b/uppsrc/CtrlCore/CocoClip.mm @@ -479,12 +479,7 @@ Image MakeDragImage(const Image& arrow, Image sample); Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) { -#ifdef PLATFORM_WIN32 - if(IsWin2K()) - return MakeDragImage(arrow, sample); - else -#endif - return arrow98; + return MakeDragImage(arrow, sample); } }; diff --git a/uppsrc/CtrlCore/CocoDnD.cpp b/uppsrc/CtrlCore/CocoDnD.cpp index 43ac54046..7f278e6e9 100644 --- a/uppsrc/CtrlCore/CocoDnD.cpp +++ b/uppsrc/CtrlCore/CocoDnD.cpp @@ -12,12 +12,7 @@ Image MakeDragImage(const Image& arrow, Image sample); Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) { -#ifdef PLATFORM_WIN32 - if(IsWin2K()) - return MakeDragImage(arrow, sample); - else -#endif - return arrow98; + return MakeDragImage(arrow, sample); } END_UPP_NAMESPACE diff --git a/uppsrc/CtrlCore/CocoDrawText.mm b/uppsrc/CtrlCore/CocoDrawText.mm index 2150ed73a..37ff39479 100644 --- a/uppsrc/CtrlCore/CocoDrawText.mm +++ b/uppsrc/CtrlCore/CocoDrawText.mm @@ -1,5 +1,7 @@ #include "CocoMM.h" +#include + #ifdef GUI_COCOA #define LLOG(x) @@ -15,9 +17,13 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon Set(ink); bool synth; - CFRef cgFont = CTFontCopyGraphicsFont(CT_Font(font, synth), NULL); - CGContextSetFont(cgHandle, cgFont); + CTFontRef ct_font = CT_Font(font, synth); + + static void (*CTFontDrawGlyphs)(CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef); + ONCELOCK { + *reinterpret_cast(&CTFontDrawGlyphs) = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs"); + } Point off = GetOffset(); CGAffineTransform tm = CGAffineTransformMakeTranslation(x + off.x, y + off.y); @@ -52,7 +58,16 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon } CGContextSetFontSize(cgHandle, font.GetHeight()); - CGContextShowGlyphsAtPositions(cgHandle, g, p, nn); } + + if(CTFontDrawGlyphs) + CTFontDrawGlyphs(ct_font, g, p, nn, cgHandle); + else { + CFRef cgFont = CTFontCopyGraphicsFont(ct_font, NULL); + CGContextSetFont(cgHandle, cgFont); + CGContextShowGlyphsAtPositions(cgHandle, g, p, nn); + } }; +} + #endif \ No newline at end of file diff --git a/uppsrc/CtrlCore/CtrlCore.h b/uppsrc/CtrlCore/CtrlCore.h index 1574ea86c..194317ac5 100644 --- a/uppsrc/CtrlCore/CtrlCore.h +++ b/uppsrc/CtrlCore/CtrlCore.h @@ -83,30 +83,31 @@ void SetSurface(Draw& w, const Rect& dest, const RGBA *pixels, Size srcsz, Point void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels); enum { - K_DELTA = 0x010000, + K_DELTA = 0x200000, + K_CHAR_LIM = 0x200000, // lower that this, key in Key is Unicode codepoint - K_ALT = 0x080000, - K_SHIFT = 0x040000, - K_CTRL = 0x020000, + K_ALT = 0x1000000, + K_SHIFT = 0x800000, + K_CTRL = 0x400000, +#ifdef PLATFORM_COCOA + K_OPTION = 0x2000000, +#endif - K_KEYUP = 0x100000, + K_KEYUP = 0x4000000, - K_MOUSEMIDDLE = 0x200000, - K_MOUSERIGHT = 0x400000, - K_MOUSELEFT = 0x800000, - K_MOUSEDOUBLE = 0x1000000, - K_MOUSETRIPLE = 0x2000000, + K_MOUSEMIDDLE = 0x2, + K_MOUSERIGHT = 0x4, + K_MOUSELEFT = 0x8, + K_MOUSEDOUBLE = 0x10, + K_MOUSETRIPLE = 0x20, K_SHIFT_CTRL = K_SHIFT|K_CTRL, -#ifdef PLATFORM_COCOA - K_OPTION = 0x4000000, -#endif - K_PEN = 0x8000000, + K_PEN = 0x80, IK_DBL_CLICK = 0x40000001, // this is just to get the info that the entry is equal to dbl-click to the menu - + K_MOUSE_FORWARD = 0x80000001, K_MOUSE_BACKWARD = 0x80000002, }; diff --git a/uppsrc/CtrlCore/CtrlKbd.cpp b/uppsrc/CtrlCore/CtrlKbd.cpp index c1bfa2076..2044c4721 100644 --- a/uppsrc/CtrlCore/CtrlKbd.cpp +++ b/uppsrc/CtrlCore/CtrlKbd.cpp @@ -68,7 +68,7 @@ bool Ctrl::DispatchKey(dword keycode, int count) String kl; dword k = keycode; const char *l = ""; - if(k < 65536) { + if(k < K_CHAR_LIM) { kl << "CHAR \'" << ToUtf8((wchar)keycode) << "\' (" << keycode << ')'; l = " "; } diff --git a/uppsrc/CtrlCore/CtrlMt.cpp b/uppsrc/CtrlCore/CtrlMt.cpp index 0b36432e9..3628b7e84 100644 --- a/uppsrc/CtrlCore/CtrlMt.cpp +++ b/uppsrc/CtrlCore/CtrlMt.cpp @@ -6,13 +6,24 @@ namespace Upp { static StaticMutex sGLock; +// #define DELAY_WATCH 1000 _DBG_ + static thread_local int sGLockLevel = 0; void EnterGuiMutex() { LLOG(">EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread()); - if(sGLockLevel++ == 0) + if(sGLockLevel++ == 0) { +#if DELAY_WATCH + for(int i = 0; i < DELAY_WATCH; i++) { + if(sGLock.TryEnter()) return; + Sleep(1); + } + Panic("Long timer procedure detected!"); +#else sGLock.Enter(); +#endif + } LLOG("EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread()); } diff --git a/uppsrc/CtrlCore/CtrlTimer.cpp b/uppsrc/CtrlCore/CtrlTimer.cpp index d97361647..32bd2e06b 100644 --- a/uppsrc/CtrlCore/CtrlTimer.cpp +++ b/uppsrc/CtrlCore/CtrlTimer.cpp @@ -4,6 +4,7 @@ namespace Upp { // #define LOG_QUEUE #define LLOG(x) // LOG(x) +// #define DELAY_WATCH 1000 _DBG_ int MemoryProbeInt; @@ -120,7 +121,14 @@ void Ctrl::TimerProc(dword time) else delete todo; sTimerLock.Leave(); + #if DELAY_WATCH + int tm = msecs(); + #endif cb(); + #if DELAY_WATCH + if(msecs() - tm > DELAY_WATCH) + Panic("Long timer procedure detected!"); + #endif sTimerLock.Enter(); } time = msecs(); diff --git a/uppsrc/CtrlCore/DrawTextWin32.cpp b/uppsrc/CtrlCore/DrawTextWin32.cpp index 85ffae095..8b2e902e6 100644 --- a/uppsrc/CtrlCore/DrawTextWin32.cpp +++ b/uppsrc/CtrlCore/DrawTextWin32.cpp @@ -21,14 +21,15 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon Mutex::Lock ___(sFontLock); // need this because of GetWin32Font HGDIOBJ orgfont = ::SelectObject(handle, GetWin32Font(font, angle)); int ascent = font.Info().GetAscent(); + Vector text16 = ToUtf16(text, n); if(angle) { double sina, cosa; Draw::SinCos(angle, sina, cosa); Size offset; - ::ExtTextOutW(handle, x + fround(ascent * sina), y + fround(ascent * cosa), 0, NULL, (const WCHAR *)text, n, dx); + ::ExtTextOutW(handle, x + fround(ascent * sina), y + fround(ascent * cosa), 0, NULL, text16.begin(), text16.GetCount(), dx); } else - ::ExtTextOutW(handle, x, y + ascent, 0, NULL, (const WCHAR *)text, n, dx); + ::ExtTextOutW(handle, x, y + ascent, 0, NULL, text16.begin(), text16.GetCount(), dx); ::SelectObject(handle, orgfont); } diff --git a/uppsrc/CtrlCore/DrawTextX11.cpp b/uppsrc/CtrlCore/DrawTextX11.cpp index cfba78501..951b4478b 100644 --- a/uppsrc/CtrlCore/DrawTextX11.cpp +++ b/uppsrc/CtrlCore/DrawTextX11.cpp @@ -135,7 +135,7 @@ GlyphInfo XftGetGlyphInfoSys(Font font, int chr) { wchar h = chr; XGlyphInfo info; - XftTextExtents16(Xdisplay, GetXftMetricFont(font, 0), &h, 1, &info); + XftTextExtents32(Xdisplay, GetXftMetricFont(font, 0), &h, 1, &info); GlyphInfo gi; gi.width = info.xOff; gi.lspc = -info.x; diff --git a/uppsrc/CtrlCore/DrawWin32.cpp b/uppsrc/CtrlCore/DrawWin32.cpp index 699c0e8ff..4ff32563e 100644 --- a/uppsrc/CtrlCore/DrawWin32.cpp +++ b/uppsrc/CtrlCore/DrawWin32.cpp @@ -464,12 +464,12 @@ PrintDraw::PrintDraw(HDC hdc, const char *docname) : SystemDraw(hdc) { GuiLock __; - DOCINFO di; + DOCINFOW di; memset(&di, 0, sizeof(di)); di.cbSize = sizeof(di); - String sys_docname = ToSystemCharset(docname); - di.lpszDocName = ~sys_docname; - if(::StartDoc(hdc, &di) <= 0) + Vector sys_docname = ToSystemCharsetW(docname); + di.lpszDocName = sys_docname; + if(::StartDocW(hdc, &di) <= 0) aborted = true; else InitPrinter(); diff --git a/uppsrc/CtrlCore/EncodeRTF.cpp b/uppsrc/CtrlCore/EncodeRTF.cpp index cf48424e5..3d036f7eb 100644 --- a/uppsrc/CtrlCore/EncodeRTF.cpp +++ b/uppsrc/CtrlCore/EncodeRTF.cpp @@ -223,8 +223,14 @@ void RTFEncoder::Command(const char *cmd, int param) void RTFEncoder::PutText(const wchar *text) { for(; *text; text++) - if((uint16)*text >= 128) - stream.Put(Format("\\u%d?", (int16)*text)); + if(*text >= 128) { + if(*text >= 65536) { + Vector h = ToUtf16(*text); + stream << "\\uc0 \\u" << (unsigned)h[0] << "\\uc1 \\u" << (unsigned)h[1]; + } + else + stream.Put(Format("\\u%d?", (int16)*text)); + } else { if(*text == '{' || *text == '}' || *text == '\\') stream.Put('\\'); diff --git a/uppsrc/CtrlCore/GtkClip.cpp b/uppsrc/CtrlCore/GtkClip.cpp index bce4744b4..4456d03d8 100644 --- a/uppsrc/CtrlCore/GtkClip.cpp +++ b/uppsrc/CtrlCore/GtkClip.cpp @@ -240,7 +240,7 @@ WString GetWString(PasteClip& clip) { GuiLock __; if(clip.IsAvailable("text")) - return FromUtf8(clip.Get("text")); + return ToUtf32(clip.Get("text")); return Null; } @@ -286,7 +286,7 @@ String ReadClipboardText() WString ReadClipboardUnicodeText() { - return FromUtf8(Ctrl::gclipboard().Get("text")); + return ToUtf32(Ctrl::gclipboard().Get("text")); } bool IsClipboardAvailable(const char *id) diff --git a/uppsrc/CtrlCore/GtkEvent.cpp b/uppsrc/CtrlCore/GtkEvent.cpp index acb9e1f84..55b56d254 100644 --- a/uppsrc/CtrlCore/GtkEvent.cpp +++ b/uppsrc/CtrlCore/GtkEvent.cpp @@ -325,7 +325,7 @@ void Ctrl::AddEvent(gpointer user_data, int type, const Value& value, GdkEvent * void Ctrl::IMCommit(GtkIMContext *context, gchar *str, gpointer user_data) { GuiLock __; - AddEvent(user_data, EVENT_TEXT, FromUtf8(str), NULL); + AddEvent(user_data, EVENT_TEXT, ToUtf32(str), NULL); } bool Ctrl::ProcessInvalids() @@ -525,7 +525,7 @@ void Ctrl::Proc() case GDK_KEY_RELEASE: kv = CurrentEvent.value[0]; hw = CurrentEvent.value[1]; - if(kv >= 0 && kv < 65536) { + if(kv >= 0 && kv < K_CHAR_LIM) { LLOG("keyval " << FormatIntHex(kv) << ' ' << (char)kv); if(kv >= 'a' && kv <= 'z') kv = kv - 'a' + 'A'; diff --git a/uppsrc/CtrlCore/ImageWin32.cpp b/uppsrc/CtrlCore/ImageWin32.cpp index c05e49051..36b1100e7 100644 --- a/uppsrc/CtrlCore/ImageWin32.cpp +++ b/uppsrc/CtrlCore/ImageWin32.cpp @@ -329,7 +329,7 @@ void SystemDraw::SysDrawImageOp(int x, int y, const Image& img, const Rect& src, sz = Ctrl::GetVirtualScreenArea().GetSize(); m.img = IsPrinter() && GetDeviceCaps(GetHandle(), NUMCOLORS) == 2 ? Dither(img, 360) : img; // If printer does not support color, dither cache.Get(m).Paint(*this, x, y, src, color); - cache.Shrink(4 * sz.cx * sz.cy, IsWinNT() ? 1000 : 100); + cache.Shrink(4 * sz.cx * sz.cy, 1000); } void ImageDraw::Section::Init(int cx, int cy) @@ -567,12 +567,9 @@ HICON SystemDraw::IconWin32(const Image& img, bool cursor) Point p = img.GetHotSpot(); iconinfo.xHotspot = p.x; iconinfo.yHotspot = p.y; - static Size cursor_size(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); Size tsz = sz; - if(!IsWin2K() && cursor) - tsz = cursor_size; Size csz = Size(min(tsz.cx, sz.cx), min(tsz.cy, sz.cy)); - if(IsWinXP() && !ImageFallBack) { + if(!ImageFallBack) { RGBA *pixels; BitmapInfo32__ bi(tsz.cx, tsz.cy); HDC dcMem = ::CreateCompatibleDC(NULL); diff --git a/uppsrc/CtrlCore/ParseRTF.cpp b/uppsrc/CtrlCore/ParseRTF.cpp index c4208bcd6..dc3ddf85c 100644 --- a/uppsrc/CtrlCore/ParseRTF.cpp +++ b/uppsrc/CtrlCore/ParseRTF.cpp @@ -500,8 +500,19 @@ RTFParser::TOKEN RTFParser::Fetch() break; } } - if(c && !skip) + if(c && !skip) { text.Cat(c); + if(text.GetCount() >= 2) { + char16 h[2]; + h[0] = text[text.GetCount() - 2]; + h[1] = text[text.GetCount() - 1]; + wchar c = ReadSurrogatePair(h, h + 2); + if(c) { + text.TrimLast(2); + text.Cat(c); + } + } + } skip = nskip; } @@ -1080,7 +1091,7 @@ String RTFParser::ReadBinHex(char& odd) const byte v = ctoi(odd); String out; for(const wchar *s = text.Begin(); *s; s++) { - byte w = (*s >= '0' && *s <= '9' ? *s - '0' + byte w = (byte)(*s >= '0' && *s <= '9' ? *s - '0' : *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s >= 'a' && *s <= 'f' ? *s - 'a' + 10 : 255); diff --git a/uppsrc/CtrlCore/TopWin32.cpp b/uppsrc/CtrlCore/TopWin32.cpp index ac924b9b7..f69a24c79 100644 --- a/uppsrc/CtrlCore/TopWin32.cpp +++ b/uppsrc/CtrlCore/TopWin32.cpp @@ -75,12 +75,8 @@ void TopWindow::SyncTitle() GuiLock __; LLOG("TopWindow::SyncTitle0 " << UPP::Name(this)); HWND hwnd = GetHWND(); - if(hwnd) { - if(IsWindowUnicode(hwnd)) - ::SetWindowTextW(hwnd, (const WCHAR*)~title); - else - ::SetWindowText(hwnd, ToSystemCharset(title.ToString())); - } + if(hwnd) + ::SetWindowTextW(hwnd, ToSystemCharsetW(title)); } void TopWindow::DeleteIco() @@ -250,7 +246,7 @@ void TopWindow::Open(HWND hwnd) if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1)) DistributeAccessKeys(); USRLOG(" OPEN " << Desc(this)); - LLOG("TopWindow::Open, owner HWND = " << FormatIntHex((int)hwnd, 8) << ", Active = " << FormatIntHex((int)::GetActiveWindow(), 8)); + LLOG("TopWindow::Open, owner HWND = " << hwnd << ", Active = " << hwnd); IgnoreMouseUp(); SyncCaption(); LLOG("WindowStyles: " << WindowStyleAsString(style, exstyle)); diff --git a/uppsrc/CtrlCore/Win32Clip.cpp b/uppsrc/CtrlCore/Win32Clip.cpp index de303db5a..0189ded6e 100644 --- a/uppsrc/CtrlCore/Win32Clip.cpp +++ b/uppsrc/CtrlCore/Win32Clip.cpp @@ -55,7 +55,7 @@ bool DebugClipboard() void ClipboardLog(const char *txt) { - if(!DebugClipboard()) + if(!DebugClipboard()) return; FileAppend f(GetExeDirFile("clip.log")); f << GetSysTime() << ": " << txt << "\n"; @@ -232,7 +232,8 @@ void AppendClipboardText(const String& s) void AppendClipboardUnicodeText(const WString& s) { - AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); + Vector ws = ToUtf16(s); + AppendClipboard("wtext", (const byte *)ws.begin(), 2 * ws.GetCount()); } const char *ClipFmtsText() @@ -245,7 +246,7 @@ String GetString(PasteClip& clip) GuiLock __; if(clip.Accept("wtext")) { String s = ~clip; - return WString((const wchar *)~s, wstrlen((const wchar *)~s)).ToString(); + return ToUtf8((const char16 *)~s, strlen16((const char16 *)~s)); } if(clip.Accept("text")) return ~clip; @@ -257,7 +258,7 @@ WString GetWString(PasteClip& clip) GuiLock __; if(clip.Accept("wtext")) { String s = ~clip; - return WString((const wchar *)~s, wstrlen((const wchar *)~s)); + return ToUtf32((const char16 *)~s, strlen16((const char16 *)~s)); } if(clip.Accept("text")) return (~clip).ToWString(); @@ -326,7 +327,7 @@ String ReadClipboardText() WString ReadClipboardUnicodeText() { String s = ReadClipboard((const char *)CF_UNICODETEXT); - return WString((const wchar *)~s, wstrlen((const wchar *)~s)); + return ToUtf32((const char16 *)~s, strlen16((const char16 *)~s)); } bool IsClipboardAvailable(const char *id) @@ -475,7 +476,7 @@ Vector GetClipFiles(const String& data) const sDROPFILES *df = (const sDROPFILES *)~data; const char *s = ((const char *)df + df->offset); if(df->unicode) { - const wchar *ws = (wchar *)s; + const char16 *ws = (char16 *)s; while(*ws) { WString fn; while(*ws) diff --git a/uppsrc/CtrlCore/Win32DnD.cpp b/uppsrc/CtrlCore/Win32DnD.cpp index 66336477e..37a5749f5 100644 --- a/uppsrc/CtrlCore/Win32DnD.cpp +++ b/uppsrc/CtrlCore/Win32DnD.cpp @@ -484,10 +484,7 @@ Image MakeDragImage(const Image& arrow, Image sample); Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) { - if(IsWin2K()) - return MakeDragImage(arrow, sample); - else - return arrow98; + return MakeDragImage(arrow, sample); } int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions, diff --git a/uppsrc/CtrlCore/Win32Gui.h b/uppsrc/CtrlCore/Win32Gui.h index 6cf156c70..21e57eb9a 100644 --- a/uppsrc/CtrlCore/Win32Gui.h +++ b/uppsrc/CtrlCore/Win32Gui.h @@ -142,7 +142,7 @@ public: SystemDraw(HDC hdc); virtual ~SystemDraw(); - bool CanSetSurface() { return Pixels() && IsWinNT(); } + bool CanSetSurface() { return Pixels(); } }; #ifndef PLATFORM_WINCE diff --git a/uppsrc/CtrlCore/Win32Proc.cpp b/uppsrc/CtrlCore/Win32Proc.cpp index a7e946213..a18a72d83 100644 --- a/uppsrc/CtrlCore/Win32Proc.cpp +++ b/uppsrc/CtrlCore/Win32Proc.cpp @@ -366,8 +366,23 @@ LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { keycode = KEYtoK((dword)wParam) | K_KEYUP; else if(message == WM_CHAR && wParam != 127 && wParam > 32 || wParam == 32 && KEYtoK(VK_SPACE) == K_SPACE) { - if(IsWindowUnicode(hwnd)) // TRC 04/10/17: ActiveX Unicode patch + if(IsWindowUnicode(hwnd)) { // TRC 04/10/17: ActiveX Unicode patch + static WCHAR surr[2]; keycode = (dword)wParam; + if((keycode & 0XFC00) == 0xD800) { // covert UTF16 surrogate pair to UTF32 codepoint + surr[0] = (WCHAR)keycode; + return 0L; + } + if((keycode & 0xFC00) == 0xDC00) { + surr[1] = (WCHAR)keycode; + keycode = ReadSurrogatePair(surr, surr + 2); + surr[0] = 0; + if(!keycode) + return 0L; + } + else + surr[0] = 0; + } else { char b[20]; ::GetLocaleInfo(MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT), diff --git a/uppsrc/CtrlCore/Win32Wnd.cpp b/uppsrc/CtrlCore/Win32Wnd.cpp index 46b4fa1b1..894e4fd6c 100644 --- a/uppsrc/CtrlCore/Win32Wnd.cpp +++ b/uppsrc/CtrlCore/Win32Wnd.cpp @@ -5,7 +5,7 @@ namespace Upp { #define LLOG(x) // DLOG(x) -#define LOGTIMING 0 +// #define LOGTIMING 1 _DBG_ #ifdef _DEBUG #define LOGMESSAGES 0 @@ -23,8 +23,7 @@ hash_t GetHashValue(const HWND& h) bool Ctrl::GetMsg(MSG& msg) { if(!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false; - return IsWindowUnicode(msg.hwnd) ? PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE) - : PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + return PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE); } static bool sFinished; @@ -114,7 +113,7 @@ LRESULT CALLBACK Ctrl::OverwatchWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR } } if(ShutdownBlockReasonCreate) - ShutdownBlockReasonCreate(hwnd, ~WString(t_("waiting for user response"))); + ShutdownBlockReasonCreate(hwnd, ToSystemCharsetW(t_("waiting for user response"))); EndSession(); ELOGW("WM_QUERYENDSESSION 1"); OverwatchEndSession.Wait(); @@ -153,10 +152,7 @@ DWORD WINAPI Ctrl::Win32OverwatchThread(LPVOID) MSG Msg; while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); - if(IsWindowUnicode(Msg.hwnd)) - DispatchMessageW(&Msg); - else - DispatchMessage(&Msg); + DispatchMessageW(&Msg); } ELOGW("OverWatch 3"); return 0; @@ -239,18 +235,15 @@ void Ctrl::InitWin32(HINSTANCE hInstance) sMainThreadId = GetCurrentThreadId(); #define ILOG(x) // RLOG(x) Ctrl::hInstance = hInstance; - ILOG("RegisterClassW"); -#ifndef PLATFORM_WINCE - if(IsWinNT()) -#endif { + ILOG("RegisterClassW"); WNDCLASSW wc; Zero(wc); wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL; + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszClassName = L"UPP-CLASS-W"; RegisterClassW(&wc); wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; @@ -263,35 +256,37 @@ void Ctrl::InitWin32(HINSTANCE hInstance) wc.lpszClassName = L"UPP-CLASS-SB-DS-W"; RegisterClassW(&wc); } - - ILOG("RegisterClassA"); - WNDCLASS wc; - Zero(wc); - wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; - wc.hInstance = hInstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL; - wc.lpszClassName = L_("UPP-CLASS-A"); - RegisterClass(&wc); - if(IsWinXP()) { + { + ILOG("RegisterClassA"); + WNDCLASS wc; + Zero(wc); + wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL; + wc.lpszClassName = L_("UPP-CLASS-A"); + RegisterClass(&wc); wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; wc.lpszClassName = L_("UPP-CLASS-DS-A"); RegisterClass(&wc); - } - wc.style = CS_SAVEBITS|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; - wc.lpszClassName = L_("UPP-CLASS-SB-A"); - RegisterClass(&wc); - if(IsWinXP()) { + wc.style = CS_SAVEBITS|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpszClassName = L_("UPP-CLASS-SB-A"); + RegisterClass(&wc); wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS; wc.lpszClassName = L_("UPP-CLASS-SB-DS-A"); RegisterClass(&wc); } - wc.style = 0; - wc.lpszClassName = L_("UPP-TIMER"); - wc.hCursor = NULL; - wc.lpfnWndProc = &Ctrl::UtilityProc; - RegisterClass(&wc); + + WNDCLASS wca; + Zero(wca); + wca.hInstance = hInstance; + wca.hbrBackground = (HBRUSH)NULL; + wca.style = 0; + wca.lpszClassName = L_("UPP-TIMER"); + wca.hCursor = NULL; + wca.lpfnWndProc = &Ctrl::UtilityProc; + RegisterClass(&wca); ILOG("InitTimer"); InitTimer(); @@ -307,19 +302,10 @@ void Ctrl::InitWin32(HINSTANCE hInstance) OleInitialize(NULL); -/* TRC 05/11/14: moved to GuiSleep to avoid thread creation in OCX DllMain - DWORD dummy; - OverwatchThread = CreateThread(NULL, 0x100000, Win32OverwatchThread, NULL, 0, &dummy); - ExitLoopEvent().Wait(); -*/ - -// TRC 05/11/18: pSetLayeredWindowAttributes moved to GLOBAL_VAR (see below) to make OCX initialization simpler - Csizeinit(); #undef ILOG - if(IsWin7()) - GlobalBackPaint(); + GlobalBackPaint(); EnterGuiMutex(); } @@ -487,20 +473,12 @@ void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int sh top = new Top; ASSERT(!parent || IsWindow(parent)); style &= ~WS_VISIBLE; - if(!IsWinXP()) - dropshadow = false; - if(IsWinNT() && (!parent || IsWindowUnicode(parent))) - top->hwnd = CreateWindowExW(exstyle, - savebits ? dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W" - : dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W", - L"", style, 0, 0, 0, 0, - parent, NULL, hInstance, this); - else - top->hwnd = CreateWindowEx(exstyle, - savebits ? dropshadow ? "UPP-CLASS-SB-DS-A" : "UPP-CLASS-SB-A" - : dropshadow ? "UPP-CLASS-DS-A" : "UPP-CLASS-A", - "", style, 0, 0, 0, 0, - parent, NULL, hInstance, this); + dropshadow = false; + top->hwnd = CreateWindowEx(exstyle, + savebits ? dropshadow ? "UPP-CLASS-SB-DS-W" : "UPP-CLASS-SB-W" + : dropshadow ? "UPP-CLASS-DS-W" : "UPP-CLASS-W", + "", style, 0, 0, 0, 0, + parent, NULL, hInstance, this); inloop = false; @@ -636,9 +614,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP #if LOGMESSAGES bool logblk = false; if(message != WM_SETCURSOR && message != WM_CTLCOLORBTN && message != WM_TIMER && -#ifndef PLATFORM_WINCE message != WM_NCHITTEST && message != WM_ENTERIDLE && -#endif message != WM_CTLCOLORDLG && message != WM_CTLCOLOREDIT && message != WM_CTLCOLORLISTBOX && message != WM_CTLCOLORMSGBOX && message != WM_CTLCOLORSCROLLBAR && message != WM_CTLCOLORSTATIC && message != WM_CANCELMODE && @@ -655,7 +631,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP #endif LRESULT l = 0; if(w && (w->GetHWND() || w->isdhctrl)) { -#if defined(_DEBUG) && LOGTIMING +#if LOGTIMING int ticks = msecs(); String wname = w->Name(); #endif @@ -663,7 +639,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP l = w->WindowProc(message, wParam, lParam); if(pw) pw->SyncMoves(); -#if defined(_DEBUG) && LOGTIMING +#if LOGTIMING String msgname; for(WinMsg *m = sWinMsg; m->ID; m++) if(m->ID == message) { @@ -672,7 +648,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP } if(IsNull(msgname)) msgname = NFormat("0x%04x", (int)message); - LLOG(NFormat("T+%d %s 0x%08x 0x%08x -> %s", msecs(ticks), msgname, (int)wParam, (int)lParam, wname)); + RLOG(NFormat("T+%d %s 0x%08x 0x%08x -> %s", msecs(ticks), msgname, (int)wParam, (int)lParam, wname)); #endif } else @@ -755,10 +731,7 @@ void Ctrl::sProcessMSG(MSG& msg) DDUMP(cls); #endif - if(IsWindowUnicode(msg.hwnd)) - DispatchMessageW(&msg); - else - DispatchMessage(&msg); + DispatchMessageW(&msg); } bool Ctrl::IsWaitingEvent() @@ -1271,7 +1244,7 @@ Rect Ctrl::GetScreenClient(HWND hwnd) } Rect Ctrl::GetDefaultWindowRect() { - HWND hwnd = ::CreateWindow("UPP-CLASS-A", "", WS_OVERLAPPED, + HWND hwnd = ::CreateWindow("UPP-CLASS-W", "", WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); Rect sr; diff --git a/uppsrc/CtrlLib/AKeys.cpp b/uppsrc/CtrlLib/AKeys.cpp index c141b86d1..6ca52830e 100644 --- a/uppsrc/CtrlLib/AKeys.cpp +++ b/uppsrc/CtrlLib/AKeys.cpp @@ -71,7 +71,7 @@ struct KeyCtrl : Ctrl { virtual bool Key(dword _key, int) { if(_key == K_ENTER || _key == K_ESCAPE) return false; - if((_key & K_KEYUP) || _key < 65536 || _key == K_SHIFT_KEY || _key == K_ALT_KEY || _key == K_CTRL_KEY) + if((_key & K_KEYUP) || _key < K_CHAR_LIM || _key == K_SHIFT_KEY || _key == K_ALT_KEY || _key == K_CTRL_KEY) return true; if(_key == K_SPACE || _key == K_DELETE || _key == K_BACKSPACE) key = 0; diff --git a/uppsrc/CtrlLib/ChWin32.cpp b/uppsrc/CtrlLib/ChWin32.cpp index 55e515ef1..9ec57cf96 100644 --- a/uppsrc/CtrlLib/ChWin32.cpp +++ b/uppsrc/CtrlLib/ChWin32.cpp @@ -72,7 +72,7 @@ HANDLE XpWidget(int widget) { if(xp_widget_handle[widget] == NULL && XpTheme()) xp_widget_handle[widget] = XpTheme().OpenThemeData(NULL, - (WCHAR *)(const wchar *)WString(xp_widget_name[widget])); + ToSystemCharsetW(xp_widget_name[widget])); return xp_widget_handle[widget]; } @@ -308,11 +308,11 @@ void Win32Look(Value& ch, int widget, int part, int state = 1, bool contentm = f String XpThemeInfo(LPCWSTR pszPropertyName) { - wchar theme[512], colors[512], size[512]; + WCHAR theme[512], colors[512], size[512]; XpTheme().GetCurrentThemeName(theme, 512, colors, 512, size, 512); - wchar h[1024]; + WCHAR h[1024]; XpTheme().GetThemeDocumentationProperty(theme, pszPropertyName, h, 1000); - return FromUnicode(h); + return ToUtf8(h); } struct sysColor { @@ -394,8 +394,7 @@ void ChHostSkin() ChBaseSkin(); - GUI_GlobalStyle_Write(IsWinXP() && !ScreenInPaletteMode() && IsSysFlag(0x1022 /*SPI_GETFLATMENU*/) - ? GUISTYLE_XP : GUISTYLE_CLASSIC); + GUI_GlobalStyle_Write(GUISTYLE_XP); #ifndef PLATFORM_WINCE GUI_DragFullWindow_Write(IsSysFlag(SPI_GETDRAGFULLWINDOWS)); #endif diff --git a/uppsrc/CtrlLib/CtrlUtil.h b/uppsrc/CtrlLib/CtrlUtil.h index 4a663c1c1..9f1e005f1 100644 --- a/uppsrc/CtrlLib/CtrlUtil.h +++ b/uppsrc/CtrlLib/CtrlUtil.h @@ -210,40 +210,13 @@ public: #endif #ifdef GUI_WIN -#ifndef PLATFORM_WINCE class TrayIcon : private Ctrl { - struct NotifyIconOld { - dword sz; - HWND hwnd; - dword id; - dword flags; - dword message; - HICON icon; - char tip[64]; - }; - struct NotifyIconNew { - dword sz; - HWND hwnd; - dword id; - dword flags; - dword message; - HICON icon; - char tip[128]; - - dword state; - dword statemask; - char info[256]; - dword timeout; - char title[64]; - dword infoflags; - }; - - Image icon; - bool visible; - String tip; - NotifyIconNew nid; - HWND hwnd; + Image icon; + bool visible; + String tip; + NOTIFYICONDATAW nid; + HWND hwnd; void Notify(dword msg); void DoMenu(Bar& bar); @@ -348,7 +321,6 @@ public: typedef FileSelNative FileSelector; -#endif #endif #ifdef GUI_X11 diff --git a/uppsrc/CtrlLib/DocEdit.cpp b/uppsrc/CtrlLib/DocEdit.cpp index 2d595f9b2..fa371230a 100644 --- a/uppsrc/CtrlLib/DocEdit.cpp +++ b/uppsrc/CtrlLib/DocEdit.cpp @@ -438,10 +438,10 @@ bool DocEdit::Key(dword key, int cnt) default: if(filter && key >= 32 && key < 65535) key = (*filter)(key); - if(key >= ' ' && key < 65536 || key == '\n' || key == '\t' || key == K_SHIFT_SPACE) { + if(key >= ' ' && key < K_CHAR_LIM || key == '\n' || key == '\t' || key == K_SHIFT_SPACE) { if(key == K_TAB && !processtab) return false; - if(key >= 128 && key < 65536 && (charset != CHARSET_UNICODE && charset != CHARSET_UTF8_BOM) + if(key >= 128 && key < K_CHAR_LIM && (charset != CHARSET_UNICODE && charset != CHARSET_UTF8_BOM) && FromUnicode((wchar)key, charset) == DEFAULTCHAR) return true; RemoveSelection(); diff --git a/uppsrc/CtrlLib/DropList.cpp b/uppsrc/CtrlLib/DropList.cpp index b9e058d76..06943ad2c 100644 --- a/uppsrc/CtrlLib/DropList.cpp +++ b/uppsrc/CtrlLib/DropList.cpp @@ -54,7 +54,7 @@ bool DropList::Key(dword k, int) { Change(-1); break; default: - if(k >= 32 && k < 65536) { + if(k >= 32 && k < K_CHAR_LIM) { bool b = list.Key(k, 1); if(list.GetCursor() >= 0 && list.GetCursor() < key.GetCount() && key[list.GetCursor()] != value) Select(); diff --git a/uppsrc/CtrlLib/EditField.cpp b/uppsrc/CtrlLib/EditField.cpp index a9f1e5392..adb9ba553 100644 --- a/uppsrc/CtrlLib/EditField.cpp +++ b/uppsrc/CtrlLib/EditField.cpp @@ -944,7 +944,7 @@ bool EditField::Key(dword key, int rep) } return false; default: - if(key >= ' ' && key < 65536 || key == K_SHIFT_SPACE) { + if(key >= ' ' && key < K_CHAR_LIM || key == K_SHIFT_SPACE) { if(!RemoveSelection()) SaveUndo(); while(rep--) Insert(key == K_SHIFT_SPACE ? ' ' : key); diff --git a/uppsrc/CtrlLib/FileList.cpp b/uppsrc/CtrlLib/FileList.cpp index 87ca05947..d96739e3b 100644 --- a/uppsrc/CtrlLib/FileList.cpp +++ b/uppsrc/CtrlLib/FileList.cpp @@ -345,7 +345,7 @@ String FileList::GetCurrentName() const int FileList::Find(const char *s) { for(int i = 0; i < GetCount(); i++) - if(strcmp(Get(i).name, s) == 0) return i; + if(Get(i).name == s) return i; return -1; } diff --git a/uppsrc/CtrlLib/FileSel.cpp b/uppsrc/CtrlLib/FileSel.cpp index 485c14918..545e87cec 100644 --- a/uppsrc/CtrlLib/FileSel.cpp +++ b/uppsrc/CtrlLib/FileSel.cpp @@ -44,11 +44,11 @@ struct FileIconMaker : ImageMaker { } virtual Image Make() const { - SHFILEINFO info; + SHFILEINFOW info; AvoidPaintingCheck__(); - SHGetFileInfo(ToSystemCharset(file), dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL, - &info, sizeof(info), - SHGFI_ICON|(large ? SHGFI_LARGEICON : SHGFI_SMALLICON)|(exe ? 0 : SHGFI_USEFILEATTRIBUTES)); + SHGetFileInfoW(ToSystemCharsetW(file), dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL, + &info, sizeof(info), + SHGFI_ICON|(large ? SHGFI_LARGEICON : SHGFI_SMALLICON)|(exe ? 0 : SHGFI_USEFILEATTRIBUTES)); return ProcessSHIcon(info.hIcon); } }; @@ -587,14 +587,14 @@ bool Load(FileList& list, const String& dir, const char *patterns, bool dirs, #ifdef GUI_WIN static Mutex sExeMutex; -static wchar sExePath[1025]; +static WCHAR sExePath[1025]; static bool sExeRunning; static SHFILEINFOW sExeInfo; static auxthread_t auxthread__ sExeIconThread(void *) { SHFILEINFOW info; - wchar path[1025]; + WCHAR path[1025]; CoInitialize(NULL); sExeMutex.Enter(); wcscpy(path, sExePath); @@ -649,7 +649,7 @@ void LazyExeFileIcons::Do() sExeMutex.Enter(); bool running = sExeRunning; if(!running) { - done = path == sExePath; + done = path == ToUtf32(sExePath); memcpy(&info, &sExeInfo, sizeof(info)); *sExePath = '\0'; memset(&sExeInfo, 0, sizeof(sExeInfo)); @@ -2389,7 +2389,9 @@ FileSel::FileSel() places.NoWantFocus(); #ifdef PLATFORM_WIN32 - list.IconWidth(GetFileIcon(GetHomeDirectory(), true, false, false).GetSize().cx); + int icx = GetFileIcon(GetHomeDirectory(), true, false, false).GetSize().cx; + if(icx) + list.IconWidth(icx); #endif AddStandardPlaces(); diff --git a/uppsrc/CtrlLib/Help.cpp b/uppsrc/CtrlLib/Help.cpp index a19b55eec..67d6e128e 100644 --- a/uppsrc/CtrlLib/Help.cpp +++ b/uppsrc/CtrlLib/Help.cpp @@ -24,7 +24,7 @@ bool HelpWindow::GoTo0(const String& link) topic = t.link; if(~tree != topic) tree.FindSetCursor(topic); - Title(FromUtf8(t.title)); + Title(ToUtf32(t.title)); RichText txt = ParseQTF(t.text); FinishText(txt); view.Pick(pick(txt), zoom); diff --git a/uppsrc/CtrlLib/LineEdit.cpp b/uppsrc/CtrlLib/LineEdit.cpp index f707a05ec..b17f9d6b1 100644 --- a/uppsrc/CtrlLib/LineEdit.cpp +++ b/uppsrc/CtrlLib/LineEdit.cpp @@ -11,6 +11,7 @@ LineEdit::LineEdit() { showtabs = false; tabsize = 4; font = CourierZ(12); + SyncFont(); SetFrame(ViewFrame()); sb.NoBox(); AddFrame(sb); @@ -70,10 +71,20 @@ LineEdit& LineEdit::SetFont(Font f) { return *this; } +void LineEdit::SyncFont() +{ + fsz = GetFontSize(); +} + Size LineEdit::GetFontSize() const { return Size(font.GetMonoWidth(), font.GetCy()); } +bool LineEdit::IsDoubleChar(int ch) const +{ + return ch >= 2048 && (IsDoubleWidth(ch) || font.GetWidth(ch) > fsz.cx); +} + void LineEdit::SetRectSelection(int64 anchor, int64 cursor) { dorectsel = true; @@ -396,7 +407,6 @@ void LineEdit::Paint0(Draw& w) { if(rectsel) rect = GetRectSelection(); Size sz = GetSize(); - Size fsz = GetFontSize(); Point sc = sb; int ll = min(GetLineCount(), sz.cy / fsz.cy + sc.y + 1); int y = 0; @@ -480,7 +490,7 @@ void LineEdit::Paint0(Draw& w) { x = fsz.cx * gp; } else - if(IsDoubleWidth(chr)) { + if(IsDoubleChar(chr)) { x += 2 * fsz.cx; gp += 2; } @@ -508,7 +518,7 @@ void LineEdit::Paint0(Draw& w) { h.ink = color[INK_SELECTED]; } int x = gp * fsz.cx - scx; - bool cjk = IsDoubleWidth(h.chr); + bool cjk = IsDoubleChar(h.chr); int xx = x + (gp + 1 + cjk) * fsz.cx; if(h.chr == '\t') { int ngp = (gp + tabsize) / tabsize * tabsize; @@ -649,6 +659,7 @@ void LineEdit::RefreshChars(bool (*chars)(int c)) } void LineEdit::Layout() { + SyncFont(); Size sz = sb.GetReducedViewSize(); if(nohbar || isdrag) sz.cy = GetSize().cy; @@ -671,7 +682,7 @@ int64 LineEdit::GetGPos(int ln, int cl) const { if((byte)*s < 128) gl++; else { - WString txt = FromUtf8(s, int(e - s)); + WString txt = ToUtf32(s, int(e - s)); const wchar *b = txt; const wchar *e = txt.End(); const wchar *s = b; @@ -679,7 +690,7 @@ int64 LineEdit::GetGPos(int ln, int cl) const { if(*s == '\t') gl = (gl + tabsize) / tabsize * tabsize; else - gl += 1 + IsDoubleWidth(*s); + gl += 1 + IsDoubleChar(*s); if(cl < gl) break; s++; } @@ -704,7 +715,7 @@ Point LineEdit::GetColumnLine(int64 pos) const { if(*s == '\t') p.x = (p.x + tabsize) / tabsize * tabsize; else - p.x += 1 + IsDoubleWidth(*s); + p.x += 1 + IsDoubleChar(*s); s++; } return p; @@ -1007,11 +1018,11 @@ void LineEdit::MoveTextEnd(bool sel) { bool LineEdit::InsertChar(dword key, int count, bool canow) { if(key == K_TAB && !processtab) return false; - if(filter && key >= 32 && key < 65535) + if(filter && key >= 32 && key < K_CHAR_LIM) key = (*filter)(key); - if(!IsReadOnly() && (key >= 32 && key < 65536 || key == '\t' || key == '\n' || + if(!IsReadOnly() && (key >= 32 && key < K_CHAR_LIM || key == '\t' || key == '\n' || key == K_ENTER && processenter || key == K_SHIFT_SPACE)) { - if(key >= 128 && key < 65536 && (charset != CHARSET_UNICODE && charset != CHARSET_UTF8_BOM) + if(key >= 128 && key < K_CHAR_LIM && (charset != CHARSET_UNICODE && charset != CHARSET_UTF8_BOM) && FromUnicode((wchar)key, charset) == DEFAULTCHAR) return true; if(!RemoveSelection() && overwrite && key != '\n' && key != K_ENTER && canow) { @@ -1113,7 +1124,7 @@ void LineEdit::SetHBar() if(*s == '\t') pos = (pos + tabsize) / tabsize * tabsize; else - pos += 1 + IsDoubleWidth(*s); + pos += 1 + IsDoubleChar(*s); s++; } mpos = max(mpos, pos); diff --git a/uppsrc/CtrlLib/PopupTable.cpp b/uppsrc/CtrlLib/PopupTable.cpp index 578d63cca..4635f5124 100644 --- a/uppsrc/CtrlLib/PopupTable.cpp +++ b/uppsrc/CtrlLib/PopupTable.cpp @@ -68,6 +68,7 @@ bool PopUpTable::Key(dword key, int n) { } void PopUpTable::PopUp(Ctrl *owner, int x, int top, int bottom, int width) { + TimeStop tm; if(inpopup) return; inpopup++; diff --git a/uppsrc/CtrlLib/SuggestCtrl.cpp b/uppsrc/CtrlLib/SuggestCtrl.cpp index fab48acf3..45f4301f1 100644 --- a/uppsrc/CtrlLib/SuggestCtrl.cpp +++ b/uppsrc/CtrlLib/SuggestCtrl.cpp @@ -89,7 +89,7 @@ bool SuggestCtrl::Key(dword key, int count) if(cc) key = cc; if(EditString::Key(key, count)) { - if(key >= 32 && key < 65536 || key == K_BACKSPACE || key == K_CTRL_SPACE) { + if(key >= 32 && key < K_CHAR_LIM || key == K_BACKSPACE || key == K_CTRL_SPACE) { int h; WString x = CF(ReadLast(h)); list.Clear(); diff --git a/uppsrc/CtrlLib/Text.cpp b/uppsrc/CtrlLib/Text.cpp index d77517b7e..09cc0574b 100644 --- a/uppsrc/CtrlLib/Text.cpp +++ b/uppsrc/CtrlLib/Text.cpp @@ -257,13 +257,13 @@ int TextCtrl::LoadLines(Vector& ls, int n, int64& total, Stream& in, byte ch auto put_ln = [&]() -> bool { if(view_line_count) { (*view_line_count)++; - total += charset == CHARSET_UTF8 && (b8 & 0x80) ? utf8len(~ln, ln.GetCount()) + total += charset == CHARSET_UTF8 && (b8 & 0x80) ? Utf32Len(~ln, ln.GetCount()) : ln.GetCount(); } else { Ln& l = ls.Add(); if(charset == CHARSET_UTF8) { - l.len = (b8 & 0x80) ? utf8len(~ln, ln.GetCount()) : ln.GetCount(); + l.len = (b8 & 0x80) ? Utf32Len(~ln, ln.GetCount()) : ln.GetCount(); l.text = ln; } else { @@ -501,10 +501,24 @@ void TextCtrl::Save(Stream& s, byte charset, int line_endings) const { const wchar *e = txt.End(); if(be16) for(const wchar *w = txt; w != e; w++) - s.Put16be(*w); + if(*w < 0x10000) + s.Put16be((word)*w); + else { + char16 h[2]; + ToUtf16(h, w, 1); + s.Put16be(h[0]); + s.Put16be(h[1]); + } else for(const wchar *w = txt; w != e; w++) - s.Put16le(*w); + if(*w < 0x10000) + s.Put16le((word)*w); + else { + char16 h[2]; + ToUtf16(h, w, 1); + s.Put16le(h[0]); + s.Put16le(h[1]); + } } return; } @@ -593,7 +607,7 @@ String TextCtrl::GetEncodedLine(int i, byte charset) const { charset = ResolveCharset(charset); String h = GetUtf8Line(i); - return charset == CHARSET_UTF8 ? h : FromUnicode(FromUtf8(h), charset); + return charset == CHARSET_UTF8 ? h : FromUnicode(ToUtf32(h), charset); } int TextCtrl::GetLinePos64(int64& pos) const { @@ -717,7 +731,7 @@ String TextCtrl::Get(int64 pos, int size, byte charset) const if(pos == 0 && sz == n) r.Cat(s, n); else - r.Cat(FromUtf8(s, n).Mid((int)pos, sz).ToString()); + r.Cat(ToUtf32(s, n).Mid((int)pos, sz).ToString()); size -= sz; if(size == 0) break; #ifdef PLATFORM_WIN32 @@ -998,7 +1012,7 @@ void TextCtrl::Undo() { Remove0(u.pos, u.size); } else { - WString text = FromUtf8(u.GetText()); + WString text = ToUtf32(u.GetText()); r.size = Insert0(u.pos, text); nc += r.size; } @@ -1025,7 +1039,7 @@ void TextCtrl::Redo() { if(r.size) RemoveU(r.pos, r.size); else - nc += InsertU(r.pos, FromUtf8(r.GetText())); + nc += InsertU(r.pos, ToUtf32(r.GetText())); redo.DropTail(); IncDirty(); } diff --git a/uppsrc/CtrlLib/TextEdit.h b/uppsrc/CtrlLib/TextEdit.h index 81065aa56..df5298f63 100644 --- a/uppsrc/CtrlLib/TextEdit.h +++ b/uppsrc/CtrlLib/TextEdit.h @@ -189,7 +189,7 @@ public: int GetLine(int64 pos) const { return GetLinePos64(pos); } const String& GetUtf8Line(int i) const; - WString GetWLine(int i) const { return FromUtf8(GetUtf8Line(i)); } + WString GetWLine(int i) const { return ToUtf32(GetUtf8Line(i)); } String GetEncodedLine(int i, byte charset = CHARSET_DEFAULT) const; int GetLineLength(int i) const; @@ -336,6 +336,7 @@ protected: Font font; + Size fsz; CharFilter filter; int tabsize; int bordercolumn; @@ -368,6 +369,8 @@ protected: Rect DropCaret(); void RefreshDropCaret(); void DoPasteColumn() { PasteColumn(); } + void SyncFont(); + bool IsDoubleChar(int ch) const; struct RefreshDraw; friend class TextCtrl; diff --git a/uppsrc/CtrlLib/TrayIconWin32.cpp b/uppsrc/CtrlLib/TrayIconWin32.cpp index a7b288a24..192775c73 100644 --- a/uppsrc/CtrlLib/TrayIconWin32.cpp +++ b/uppsrc/CtrlLib/TrayIconWin32.cpp @@ -31,11 +31,11 @@ TrayIcon::TrayIcon() Create(NULL, WS_POPUP, 0, false, 0, 0); Ctrl::Hide(); Zero(nid); - nid.sz = IsWin2K() ? sizeof(NotifyIconNew) : sizeof(NotifyIconOld); - nid.message = UM_TASKBAR_; - nid.hwnd = GetHWND(); + nid.cbSize = sizeof(nid); + nid.uCallbackMessage = UM_TASKBAR_; + nid.hWnd = GetHWND(); static int id; - nid.id = ++id; + nid.uID = ++id; visible = false; Show(); } @@ -43,22 +43,29 @@ TrayIcon::TrayIcon() TrayIcon::~TrayIcon() { Hide(); - if(nid.icon) - DestroyIcon(nid.icon); + if(nid.hIcon) + DestroyIcon(nid.hIcon); +} + +void Wcpy(char16 *t, const String& s, int sz) +{ + Vector w = ToSystemCharsetW(s); + if(w.GetCount() > sz) { + w.SetCount(sz - 1); + w.Add(0); + } + memcpy(t, w, w.GetCount() * sizeof(char16)); } void TrayIcon::Notify(dword msg) { if(visible) { - nid.flags = NIF_ICON|NIF_MESSAGE|NIF_TIP; - if(nid.icon) - DestroyIcon(nid.icon); - nid.icon = SystemDraw::IconWin32(icon); - String stip = ToSystemCharset(tip); - int len = min(stip.GetLength(), 125); - memcpy(nid.tip, stip, len); - nid.tip[len] = 0; - BOOL Status = Shell_NotifyIcon(msg, (NOTIFYICONDATA *)&nid); + nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; + if(nid.hIcon) + DestroyIcon(nid.hIcon); + nid.hIcon = SystemDraw::IconWin32(icon); + Wcpy(nid.szTip, tip, 128); + BOOL Status = Shell_NotifyIconW(msg, &nid); // To prevent from Shell_NotifyIcon bugs... // discussed here : http://msdn.microsoft.com/en-us/library/bb762159(v=vs.85).aspx // and here : http://issuetracker.delphi-jedi.org/bug_view_advanced_page.php?bug_id=3747 @@ -71,7 +78,7 @@ void TrayIcon::Notify(dword msg) if(ErrorCode == ERROR_SUCCESS || ErrorCode == ERROR_TIMEOUT) { for(int retry = 0; retry < 60; retry++) { Sleep(50); - if(Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA *)&nid) == (msg != NIM_DELETE)) + if(Shell_NotifyIconW(NIM_MODIFY, &nid) == (msg != NIM_DELETE)) break; } } @@ -81,23 +88,12 @@ void TrayIcon::Notify(dword msg) void TrayIcon::Message(int type, const char *title, const char *text, int timeout) { - if(!IsWin2K()) - return; - nid.flags = 0x10; - *nid.info = *nid.title = 0; - if(text) { - String h = ToSystemCharset(text); - memcpy(nid.info, h, min(h.GetLength(), 255) + 1); - nid.info[255] = 0; - } - if(title) { - String h = ToSystemCharset(title); - memcpy(nid.title, h, min(h.GetLength(), 63) + 1); - nid.title[63] = 0; - } - nid.infoflags = type; - nid.timeout = minmax(timeout, 10, 30) * 1000; - Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA *)&nid); + nid.uFlags = 0x10; + Wcpy(nid.szInfo, text, 256); + Wcpy(nid.szInfoTitle, text, 64); + nid.dwInfoFlags = type; + nid.uTimeout = minmax(timeout, 10, 30) * 1000; + Shell_NotifyIconW(NIM_MODIFY, &nid); } void TrayIcon::Show(bool b) @@ -185,11 +181,11 @@ LRESULT TrayIcon::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) LeftUp(); return TRUE; case WM_LBUTTONDBLCLK: - ::SetForegroundWindow(nid.hwnd); + ::SetForegroundWindow(nid.hWnd); LeftDouble(); return TRUE; case WM_RBUTTONDOWN: - ::SetForegroundWindow(nid.hwnd); + ::SetForegroundWindow(nid.hWnd); MenuBar::Execute(NULL, THISBACK(DoMenu), GetMousePos()); return TRUE; case NIN_BALLOONSHOW_: diff --git a/uppsrc/CtrlLib/TreeCtrl.cpp b/uppsrc/CtrlLib/TreeCtrl.cpp index 9fd621201..dfd27cedc 100644 --- a/uppsrc/CtrlLib/TreeCtrl.cpp +++ b/uppsrc/CtrlLib/TreeCtrl.cpp @@ -1294,7 +1294,7 @@ bool TreeCtrl::Key(dword key, int) Open(cid); break; default: { - if(accel && key >= ' ' && key < 65536) { + if(accel && key >= ' ' && key < K_CHAR_LIM) { int ascii_line = -1; int upper_line = -1; int exact_line = -1; diff --git a/uppsrc/CtrlLib/Win32.cpp b/uppsrc/CtrlLib/Win32.cpp index f430aadf0..132afa560 100644 --- a/uppsrc/CtrlLib/Win32.cpp +++ b/uppsrc/CtrlLib/Win32.cpp @@ -26,8 +26,8 @@ FileSelNative::FileSelNative() { FileSelNative& FileSelNative::Type(const char *name, const char *ext) { FileType& t = type.Add(); - t.name = ToSystemCharset(name); - t.ext = ToSystemCharset(ext); + t.name = name; + t.ext = ext; return *this; } @@ -98,6 +98,12 @@ static UINT_PTR CALLBACK sCenterHook(HWND hdlg, UINT msg, WPARAM wParam, LPARAM #endif bool FileSelNative::Execute(bool open, const char *dlgtitle) { + Vector> s16; + auto W32 = [&](const String& s) -> char16* { + auto& h = s16.Add(); + h = ToSystemCharsetW(s); + return h; + }; String filter; for(int i = 0; i < type.GetCount(); i++) { filter.Cat(type[i].name); @@ -105,7 +111,7 @@ bool FileSelNative::Execute(bool open, const char *dlgtitle) { filter.Cat(type[i].ext); filter.Cat('\0'); } - OPENFILENAME ofn; + OPENFILENAMEW ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(OPENFILENAME); Ctrl *q = Ctrl::GetActiveWindow(); @@ -114,12 +120,12 @@ bool FileSelNative::Execute(bool open, const char *dlgtitle) { if(asking) ofn.Flags |= (open ? OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST : OFN_OVERWRITEPROMPT); if(!rdonly) ofn.Flags |= OFN_HIDEREADONLY; if(multi) ofn.Flags |= OFN_ALLOWMULTISELECT; - ofn.lpstrFilter = filter; + ofn.lpstrFilter = W32(filter); ofn.nFilterIndex = activetype; - ofn.lpstrInitialDir = activedir; + ofn.lpstrInitialDir = W32(activedir); ofn.lpfnHook = sCenterHook; int bufsize = ofn.nMaxFile = (multi ? 32000 : _MAX_PATH); - Buffer buffer(bufsize); + Buffer buffer(bufsize); *(ofn.lpstrFile = buffer) = 0; if(!filename.IsEmpty()) { @@ -127,16 +133,16 @@ bool FileSelNative::Execute(bool open, const char *dlgtitle) { for(int i = 0; i < filename.GetCount(); i++) { if(*ofn.lpstrInitialDir == 0 && FindFile().Search(AppendFileName(GetFileDirectory(filename[i]), "*"))) - ofn.lpstrInitialDir = GetFileDirectory(filename[i]); + ofn.lpstrInitialDir = W32(GetFileDirectory(filename[i])); if(!open || FileExists(filename[i])) { String fn = GetFileName(filename[i]); if(!IsNull(fn)) { if(multi && fn.Find(' ') >= 0) - out << '\"' << ToSystemCharset(fn) << '\"'; + out << W32(String() << '\"' << fn << '\"'); else - out << ToSystemCharset(fn); + out << W32(fn); out.Cat(0); } } @@ -145,44 +151,42 @@ bool FileSelNative::Execute(bool open, const char *dlgtitle) { memcpy(buffer, out, l + 1); } - String title; if(dlgtitle) - title = ToSystemCharset(dlgtitle); + ofn.lpstrTitle = W32(dlgtitle); else if(open) - title = ToSystemCharset(t_("Open..")); + ofn.lpstrTitle = W32(t_("Open..")); else - title = ToSystemCharset(t_("Save as")); - ofn.lpstrTitle = ~title; + ofn.lpstrTitle = W32(t_("Save as")); if(!defext.IsEmpty()) - ofn.lpstrDefExt = defext; - bool res = !!(open ? GetOpenFileName : GetSaveFileName)(&ofn); + ofn.lpstrDefExt = W32(defext); + bool res = !!(open ? GetOpenFileNameW : GetSaveFileNameW)(&ofn); if(!res && CommDlgExtendedError() == FNERR_INVALIDFILENAME) { *buffer = 0; - res = !!(open ? GetOpenFileName : GetSaveFileName)(&ofn); + res = !!(open ? GetOpenFileNameW : GetSaveFileNameW)(&ofn); } if(!res && CommDlgExtendedError() == FNERR_INVALIDFILENAME) { - ofn.lpstrInitialDir = ""; - res = !!(open ? GetOpenFileName : GetSaveFileName)(&ofn); + ofn.lpstrInitialDir = W32(""); + res = !!(open ? GetOpenFileNameW : GetSaveFileNameW)(&ofn); } if(!res) return false; filename.Clear(); activetype = ofn.nFilterIndex; if(multi) { - const char *s = ofn.lpstrFile; - activedir = s; - s += strlen(s); + const char16 *s = ofn.lpstrFile; + activedir = FromSystemCharsetW(s); + s += strlen16(s); if(s[1] == 0) - filename.Add() = FromSystemCharset(activedir); + filename.Add() = activedir; else do - filename.Add() = FromSystemCharset(AppendFileName(activedir, ++s)); - while((s += strlen(s))[1]); + filename.Add() = AppendFileName(activedir, FromSystemCharsetW(++s)); + while((s += strlen16(s))[1]); } else { - filename.Add(FromSystemCharset(ofn.lpstrFile)); + filename.Add(FromSystemCharsetW(ofn.lpstrFile)); activedir = GetFileDirectory(filename[0]); } readonly = ofn.Flags & OFN_READONLY ? TRUE : FALSE; diff --git a/uppsrc/Draw/Draw.h b/uppsrc/Draw/Draw.h index 2b9a56007..c9eb0e209 100644 --- a/uppsrc/Draw/Draw.h +++ b/uppsrc/Draw/Draw.h @@ -65,7 +65,7 @@ class Font : public ValueType >{ const CommonFontInfo& Fi() const; friend void sInitFonts(); - friend String GetFontDataSys(Font font); + friend String GetFontDataSys(Font font, const char *table, int offset, int size); public: enum { @@ -182,7 +182,7 @@ public: String GetTextFlags() const; void ParseTextFlags(const char *s); - String GetData() const; + String GetData(const char *table = NULL, int offset = 0, int size = INT_MAX) const; void Render(FontGlyphConsumer& sw, double x, double y, int ch) const; diff --git a/uppsrc/Draw/Draw.upp b/uppsrc/Draw/Draw.upp index 3d7bf124a..86b462e1c 100644 --- a/uppsrc/Draw/Draw.upp +++ b/uppsrc/Draw/Draw.upp @@ -8,7 +8,7 @@ acceptflags uses Core; -library(WIN32) "user32 gdi32"; +library(WIN32) "user32 gdi32 usp10"; link(OSX !X11) "-framework Foundation -framework Cocoa -framework Carbon"; @@ -20,6 +20,7 @@ file Draw.h options(BUILDER_OPTION) PCH, FontInt.h, Font.cpp, + Fonts.i, FontCR.cpp, FontWin32.cpp, FontFc.cpp, diff --git a/uppsrc/Draw/DrawText.cpp b/uppsrc/Draw/DrawText.cpp index 9c98a5382..99dca08ee 100644 --- a/uppsrc/Draw/DrawText.cpp +++ b/uppsrc/Draw/DrawText.cpp @@ -20,7 +20,7 @@ WString TextUnicode(const char *s, int n, byte cs, Font font) return WString(b); } #endif - return ToUnicode(s, n, cs); + return ToUtf32(s, n); } void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font, @@ -29,7 +29,7 @@ void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font, if(IsNull(ink)) return; ink = ResolveInk(ink); if(n < 0) - n = wstrlen(text); + n = strlen__(text); Std(font); double sina = 0; double cosa = 1; @@ -43,7 +43,7 @@ void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font, wchar chr = text[i]; GlyphInfo gi = GetGlyphInfo(font, chr); if(gi.IsNormal()) - if(angle) + if(angle || chr >= 0x10000) DrawTextOp(int(x + cosa * posx), int(y - sina * posx), angle, &chr, font, ink, 1, NULL); else { int c = 1; @@ -212,7 +212,7 @@ Size GetTextSize(const wchar *text, Font font, int n) { FontInfo fi = font.Info(); if(n < 0) - n = wstrlen(text); + n = strlen__(text); Size sz; sz.cx = 0; const wchar *wtext = (const wchar *)text; diff --git a/uppsrc/Draw/DrawTextUtil.cpp b/uppsrc/Draw/DrawTextUtil.cpp index 14de7eedf..a61161bda 100644 --- a/uppsrc/Draw/DrawTextUtil.cpp +++ b/uppsrc/Draw/DrawTextUtil.cpp @@ -5,7 +5,7 @@ namespace Upp { void DrawTextEllipsis(Draw& w, int x, int y, int cx, const wchar *text, const char *ellipsis, Font font, Color ink, int n) { - if(n < 0) n = wstrlen(text); + if(n < 0) n = strlen__(text); FontInfo f = font.Info(); const char *s; int dtl = 0; diff --git a/uppsrc/Draw/Drawing.cpp b/uppsrc/Draw/Drawing.cpp index c0f35bb0c..be677224a 100644 --- a/uppsrc/Draw/Drawing.cpp +++ b/uppsrc/Draw/Drawing.cpp @@ -250,17 +250,23 @@ void DrawingDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, C DrawingOp(DRAWING_DRAWARC) % const_cast(rc) % start % end % color % width; } +static_assert(sizeof(wchar) == 4, "sizeof wchar"); + void DrawingDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) { if(IsNull(ink)) return; if(n < 0) - n = wstrlen((const wchar *)text); + n = strlen__((const wchar *)text); if(n == 0) return; Stream& s = DrawingOp(DRAWING_DRAWTEXT); - byte cs = CHARSET_UNICODE; + byte cs = CHARSET_UTF32; s % x % y % angle % font % ink / n % cs; - s.PutW((wchar *)text, n); +#ifdef CPU_LE + s.Put(text, n * sizeof(wchar)); +#else + #error big endiand not supported +#endif bool dxb = dx; s % dxb; if(dx) { @@ -548,13 +554,18 @@ void Draw::DrawDrawingOp(const Rect& target, const Drawing& w) { FontInfo fi = font.Info(); font.Height(fi.GetHeight() - fi.GetInternal()); } - bool unicode = cs == CHARSET_UNICODE; WString text; - if(unicode) { + if(cs == CHARSET_UTF32) { Buffer txt(n); - ps.Stream::GetW(txt, n); + ps.Stream::Get(txt, n * sizeof(wchar)); text = WString(txt, n); } + else + if(cs == CHARSET_UNICODE) { // backward compatibility + Buffer txt(n); + ps.Stream::GetW(txt, n); + text = ToUtf32(txt, n); + } else { Buffer txt(n); ps.Stream::Get(txt, n); @@ -594,39 +605,6 @@ void Draw::DrawDrawingOp(const Rect& target, const Drawing& w) { int ht = (int)(font.GetHeight() * min(double(ps.target.cx) / ps.source.cx, double(ps.target.cy) / ps.source.cy)); font.Width((int)q * font.GetWidth()).Height(ht ? ht : 1); DrawText(ps.GetX(x), ps.GetY(y), angle, text, font, ink, dx); - /* - FontInfo fi = font.Info(); - const wchar *wp = ~text; - int odd = (angle / 900) & 1; - double ang = (double) (angle % 900) * M_2PI / 3600; - double sx = (double) ps.target.cx / ps.source.cx; - double sy = (double) ps.target.cy / ps.source.cy; - double ang2 = atan((odd ? sx / sy : sy / sx) * tan(ang)); - DDUMP(odd); - DDUMP(cx); - DDUMP(sy); - DDUMP(sin(ang)); - DDUMP(sin(ang2)); - double q = (odd ? sx : sy) * sin(ang) / sin(ang2); - double error = 0; - while(nn--) { - int cx; - if(dxb) { - ps / cx; - DDUMP(cx); - } - else - cx = fi[*wp++]; - double ncx = q * cx + error; - DDUMP(q * cx); - *wd++ = cx = (int) ncx; - error = ncx - cx; - } - int ht = (int)(fi.GetFontHeight() * (sx * sin(ang) * sin(ang2) + sy * cos(ang) * cos(ang2))); - font.Width(int(q * fi.GetAveWidth())).Height(ht ? ht : 1); - DrawText(ps.GetX(x), ps.GetY(y), int(ang2 * 3600 / M_2PI) + (angle / 900) * 900, - text, font, ink, dx); - */ } } } diff --git a/uppsrc/Draw/Font.cpp b/uppsrc/Draw/Font.cpp index 19d91f89d..8ec2d4924 100644 --- a/uppsrc/Draw/Font.cpp +++ b/uppsrc/Draw/Font.cpp @@ -386,31 +386,39 @@ String AsString(const Font& f) { struct CharEntry { int64 font; GlyphInfo info; - word chr; + wchar chr; }; -CharEntry fc_cache_global[4093]; +CharEntry fc_cache_global[16384]; inline hash_t GlyphHash(Font font, int chr) { return FoldHash(CombineHash(font.GetHashValue(), chr)); } -bool IsNormal(Font font, int chr) -{ +bool IsNormal_nc(Font font, int chr) +{ // do not change cache - to be used in Replace Mutex::Lock __(sFontLock); font.RealizeStd(); - CharEntry& e = fc_cache_global[GlyphHash(font, chr) % 4093]; + CharEntry& e = fc_cache_global[GlyphHash(font, chr) & 16383]; if(e.font == font.AsInt64() && e.chr == chr) return e.info.IsNormal(); return GetGlyphInfoSys(font, chr).IsNormal(); } -CharEntry GetGlyphEntry(Font font, int chr, hash_t hash) -{ - Mutex::Lock __(sFontLock); - CharEntry& e = fc_cache_global[hash % 4093]; - if(e.font != font.AsInt64() || e.chr != chr) { +struct GlyphInfoMaker : ValueMaker { + Font font; + int chr; + + virtual String Key() const { + StringBuffer s; + int64 h = font.AsInt64(); + RawCat(s, h); + RawCat(s, chr); + return String(s); + } + virtual int Make(Value& object) const { + CharEntry& e = CreateRawValue(object); e.font = font.AsInt64(); e.chr = chr; e.info = GetGlyphInfoSys(font, chr); @@ -419,7 +427,7 @@ CharEntry GetGlyphEntry(Font font, int chr, hash_t hash) Font rfnt; if(Compose(font, chr, cg)) { e.info.lspc = -1; - e.info.rspc = cg.basic_char; + e.info.rspc = (int16)cg.basic_char; } else if(Replace(font, chr, rfnt)) { @@ -429,8 +437,17 @@ CharEntry GetGlyphEntry(Font font, int chr, hash_t hash) else e.info.lspc = -2; } + return sizeof(e); } - return e; +}; + +CharEntry GetGlyphEntry(Font font, int chr, hash_t hash) +{ + Mutex::Lock __(sFontLock); + GlyphInfoMaker m; + m.font = font; + m.chr = chr; + return MakeValue(m).To(); } thread_local CharEntry fc_cache[512]; @@ -548,10 +565,11 @@ int Font::GetRightSpace(int c) const { return GetGlyphMetrics(*this, c).rspc; } -String Font::GetData() const +String Font::GetData(const char *table, int offset, int size) const { Mutex::Lock __(sFontLock); - return GetFontDataSys(*this); + ASSERT(!table || strlen(table) == 4); + return GetFontDataSys(*this, table, offset, size); } void Font::Render(FontGlyphConsumer& sw, double x, double y, int ch) const diff --git a/uppsrc/Draw/FontCR.cpp b/uppsrc/Draw/FontCR.cpp index 8b094c3f4..c50c5e791 100644 --- a/uppsrc/Draw/FontCR.cpp +++ b/uppsrc/Draw/FontCR.cpp @@ -1,5 +1,7 @@ #include "Draw.h" +#define LLOG(x) // LOG(x) + namespace Upp { enum { @@ -226,91 +228,223 @@ bool Compose(Font font, int chr, ComposedGlyph& cg) struct sRFace { const char *name; - dword l, h; + byte panose[10]; + dword coverage[8]; } sFontReplacements[] = { - { "Lucida Grande", 0, 0 }, - { "Apple Symbols", 0, 0 }, - { "sans-serif", 0xffee0008, 0xdc000801 }, - { "Arial", 0xfffe0000, 0x9c000801 }, - {"\346\226\260\345\256\213\344\275\223", 0xfd800000, 0x9ffff00d },//SimSun (or New Song Ti) - {"SimSun", 0xfd800000, 0x9ffff00d },//SimSun (or New Song Ti) - {"\345\256\213\344\275\223", 0xfd800000, 0x9ffff00d }, // Song Ti - {"\345\276\256\350\275\257\351\233\205\351\273\221", 0xfd800000, 0x9ffff00f }, //MS Ya Hei - {"Microsoft YaHei", 0xfd800000, 0x9ffff00f }, //MS Ya Hei -// {"\351\273\221\344\275\223", 0xfd800000, 0x09ffff00 }, // Hei Ti -// {"\346\226\207\346\263\211\351\251\277\346\255\243\351\273\221", 0xfd800000, 0x09ffff00 }, //WenQuanYi Zheng Hi -// {"\346\226\207\346\263\211\351\251\277\347\255\211\345\256\275\345\276\256\347\261\263\351\273\221", 0xfd800000, 0x09ffff00 },//WenQuanYi Wei Hei -// {"\344\273\277\345\256\213", 0xfd800000, 0x09ffff00 }, //Fang Song -// {"\346\245\267\344\275\223", 0xfd800000, 0x09ffff00 }, // Kai Ti - { "Arial Unicode MS", 0xfffc3fef, 0xfa7ff7ef }, - { "MS UI Gothic", 0xffc01008, 0xfffff001 }, - { "MS Mincho", 0xffc01008, 0xfffff001 }, - { "VL Gothic", 0xfd800000, 0x9a7ff80f }, - { "VL PGothic", 0xffe00008, 0xde7ff80f }, - { "UnDotum", 0xe5800000, 0xaa7ff7ef }, - { "UnBatang", 0xe5800000, 0xaa7ff7ef }, - { "DejaVu Sans Mono", 0xffec0004, 0xfc00080f }, - { "DejaVu Sans", 0xfffd000c, 0xfc40080f }, - { "AlArabiyaFreeSerif", 0xffdc0008, 0xd800000f }, - { "Kochi Mincho", 0xffdc0008, 0xd800000f }, - { "Kochi Gothic", 0xffdc0008, 0xd800000f }, - { "Sazanami Mincho", 0xffdc0008, 0xd800000f }, - { "Sazanami Gothic", 0xffdc0008, 0xd800000f }, - { "Gulim", 0xf7c00000, 0xba7ff7e1 }, - { "PMingLiU", 0xff800000, 0x9ffff001 }, // <--- SHOULD MOVE UP - { "FreeSans", 0xfff23d00, 0xfc00000f }, - { "FreeSerif", 0xfffd3938, 0xfc00080f }, - { "FreeMono", 0xfffc0000, 0xbc000c01 }, - { "Symbol", 0xe4000000, 0x8800000f }, - { "NanumGothic", 0xe5800000, 0xae7ff7e1 }, - { "WenQuanYi Micro Hei Mono", 0xffe00008, 0xda7ff7e1 }, - { "NanumMyeongjo", 0xe5800000, 0x8a0007e1 }, - { "WenQuanYi Micro Hei", 0xffe00008, 0xda7ff7e1 }, - { "FontAwesome", 0xc0000000, 0x88000002 }, + #include "Fonts.i" }; +bool ReadCmap(Font font, Event range, bool glyphs = false) { + String data = font.GetData("cmap"); + auto Get16 = [&](int i) { return i >= 0 && i + 2 <= data.GetCount() ? Peek16be(~data + i) : 0; }; + auto Get32 = [&](int i) { return i >= 0 && i + 4 <= data.GetCount() ? Peek32be(~data + i) : 0; }; + for(int pass = 0; pass < 2; pass++) { + int p = 0; + p += 2; + int n = Get16(p); + p += 2; + while(n-- && p < data.GetCount()) { + int pid = Get16(p); p += 2; + int psid = Get16(p); p += 2; + int offset = Get32(p); p += 4; + if(offset < 0 || offset > data.GetCount()) + return false; + int format = Get16(offset); + LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format); + if((pid == 3 && psid == 10) || (pid == 0 && psid == 4) && format == 12 && pass == 0) { + int p = offset; + int ngroups = Get32(p + 12); + p += 16; // pointer to groups table + for(int i = 0; i < ngroups; i++) { + int start = Get32(p); + int end = Get32(p + 4); + range(start, end, Get32(p + 8)); + p += 12; + } + return true; + } + else + if((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4 && pass == 1) { + int p = offset; + int n = Get16(p + 6) >> 1; + int seg_end = p + 14; + int seg_start = seg_end + 2 * n + 2; + int idDelta = seg_start + 2 * n; + int idRangeOffset = idDelta + 2 * n; + for(int i = 0; i < n; i++) { + int start = Get16(seg_start + 2 * i); + int end = Get16(seg_end + 2 * i); + int delta = Get16(idDelta + 2 * i); + int ro = Get16(idRangeOffset + 2 * i); + if(glyphs) { + if (ro && delta == 0) { + LLOG("RangeOffset start: " << start << ", end: " << end << ", delta: " << (int16)delta); + int q = idRangeOffset + 2 * i + ro; + for(int c = start; c <= end; c++) { + range(c, c, (word)Get16(q)); + q += 2; + } + } + else { + LLOG("Delta start: " << start << ", end: " << end << ", delta: " << (int16)delta); + range(start, end, start + delta); + } + } + else + range(start, end, 0); + } + return true; + } + } + } + return false; +} + +bool GetPanoseNumber(Font font, byte *panose) +{ + memset(panose, 0, 10); + String data = font.GetData("OS/2", 32, 10); + if(data.GetCount() != 10) + return false; + memcpy(panose, data, data.GetCount()); + return true; +} + struct sFontMetricsReplacement { Font src; Font dst; Font mdst; }; +int PanoseDistance(byte *a, byte *b) +{ + int distance = 0; + auto pval = [&](int val, int def) { + if(val) return val; + distance += 5; + return def; + }; + if(pval(a[0], 2) != pval(b[0], 2)) return INT_MAX; + + auto Add = [&](int i, int def) { + int q = pval(a[i], def) - pval(b[i], def); + distance += q * q; + }; + Add(1, 6); + Add(2, 6); + Add(3, 4); + return distance; +} + bool Replace(Font fnt, int chr, Font& rfnt) { - static Vector rface; -// static Vector l, h; - ONCELOCK { - for(int i = 0; i < __countof(sFontReplacements) && rface.GetCount() < 20; i++) { + static VectorMap rface[2]; // face index to font info + static bool all_loaded; + if(rface[0].GetCount() == 0) { + for(int i = 0; i < __countof(sFontReplacements); i++) { int q = Font::FindFaceNameIndex(sFontReplacements[i].name); if(q > 0) { - rface.Add(q); -// l.Add(sFontReplacements[i].l); -// h.Add(sFontReplacements[i].h); + rface[0].Add(q) = &sFontReplacements[i]; } } } - Font f = fnt; - for(int i = 0; i < rface.GetCount(); i++) { - if(IsNormal(f.Face(rface[i]), chr)) { - int a = fnt.GetAscent(); - static WString apple_kbd = "⌘⌃⇧⌥"; // do not make these smaller it looks ugly... - if(f.GetAscent() > a && apple_kbd.Find(chr) < 0) { - static sFontMetricsReplacement cache[256]; - int q = CombineHash(fnt, f) & 255; - if(cache[q].src != fnt || cache[q].dst != f) { - cache[q].src = fnt; - cache[q].dst = f; - while(f.GetAscent() > a && f.GetHeight() > 1) { - f.Height(max(1, f.GetHeight() - max(1, f.GetHeight() / 20))); - } - cache[q].mdst = f; - } - else - f = cache[q].mdst; + int face = fnt.GetFace(); + byte *panose; + int q = rface[0].Find(face); // if we have this font in database, we do not need to load panose + if(q >= 0) + panose = rface[0][q]->panose; + else { + int q = rface[1].Find(face); // if we have this font in database, we do not need to load panose + if(q >= 0) + panose = rface[1][q]->panose; + else { + struct Panose : Moveable { + byte panose[10]; + }; + static ArrayMap cache; + int q = cache.Find(face); + if(q < 0) { + q = cache.GetCount(); + Font f2(face, 20); + GetPanoseNumber(f2, cache.Add(face).panose); + } + panose = cache[q].panose; + } + } + + int wi; + dword bit; + + auto ChrBit = [&](int c) { + wi = 0; + c = max(c, 0); + if(c < 2048) + bit = 0x80000000 >> (c >> 6); + else { + int bi = clamp(c - 2048, 0, 7*32*1024 - 1) >> 10; + ASSERT((bi >> 5) + 1 < 8); + wi = (bi >> 5) + 1; + bit = 0x80000000 >> (bi & 31); + } + }; + + for(int pass = 0; pass < 2; pass++) { + Font f = fnt; + Vector distance; + Vector candidate; + ChrBit(chr); + for(int i = 0; i < rface[pass].GetCount(); i++) + if(rface[pass][i]->coverage[wi] & bit) { + distance.Add(PanoseDistance(rface[pass][i]->panose, panose)); + candidate.Add(rface[pass].GetKey(i)); + } + StableIndexSort(distance, candidate); + for(int fi : candidate) { + f.Face(fi); + if(IsNormal_nc(f, chr)) { + int a = fnt.GetAscent(); + static WString apple_kbd = "⌘⌃⇧⌥"; // do not make these smaller it looks ugly... + if(f.GetAscent() > a && apple_kbd.Find(chr) < 0) { + static sFontMetricsReplacement cache[256]; + int q = CombineHash(fnt, f) & 255; + if(cache[q].src != fnt || cache[q].dst != f) { + cache[q].src = fnt; + cache[q].dst = f; + while(f.GetAscent() > a && f.GetHeight() > 1) { + f.Height(max(1, f.GetHeight() - max(1, f.GetHeight() / 20))); + } + cache[q].mdst = f; + } + else + f = cache[q].mdst; + } + rfnt = f; + return true; + } + } + if(!all_loaded) { + all_loaded = true; + for(int i = 1; i < Font::GetFaceCount(); i++) { + dword fi = Font::GetFaceInfo(i); + if(rface[1].Find(i) < 0 && !(fi & Font::SPECIAL) && (fi & Font::SCALEABLE)) { + Font fnt(i, 40); + sRFace fi; + memset(&fi, 0, sizeof(fi)); + bool hascmap = ReadCmap(fnt, [&](int start, int end, int) { + for(int c = start; c <= end; c = (c + 64) & ~63) { + ChrBit(c); + fi.coverage[wi] |= bit; + } + }); + if(hascmap && GetPanoseNumber(fnt, fi.panose)) { + static Array xface; // for those additionally loaded + sRFace& n = xface.Add(); + n = fi; + rface[1].Add(i, &n); + } + } } - rfnt = f; - return true; } } return false; diff --git a/uppsrc/Draw/FontCoco.mm b/uppsrc/Draw/FontCoco.mm index 0490a00fd..94fad406a 100644 --- a/uppsrc/Draw/FontCoco.mm +++ b/uppsrc/Draw/FontCoco.mm @@ -48,9 +48,9 @@ WString ToWString(CFStringRef s) if(!s) return Null; CFIndex l = CFStringGetLength(s); if(!l) return Null; - WStringBuffer b(l); - CFStringGetCharacters(s, CFRangeMake(0, l), (UniChar *)~b); - return b; + Buffer h(l); + CFStringGetCharacters(s, CFRangeMake(0, l), (UniChar *)~h); + return ToUtf32(~h, l); } String ToString(CFStringRef s) @@ -108,10 +108,10 @@ CTFontRef CT_Font(Font fnt, bool& synth) CGGlyph GetCharGlyph(CTFontRef ctfont, int chr) { - CGGlyph glyph_index; - UniChar h = chr; - CTFontGetGlyphsForCharacters(ctfont, &h, &glyph_index, 1); - return glyph_index; + CGGlyph glyph_index[2]; + Vector h = ToUtf16(chr); + CTFontGetGlyphsForCharacters(ctfont, (UniChar *)h.begin(), glyph_index, h.GetCount()); + return glyph_index[0]; } GlyphInfo GetGlyphInfoSys(CTFontRef ctfont, int chr, bool bold_synth, CGRect *bounds = NULL) @@ -270,9 +270,44 @@ Vector GetAllFacesSys() return r; } -String GetFontDataSys(Font font) -{ - return LoadFile(font.Fi().path); +String GetFontDataSys(Font font, const char *table, int offset, int size) +{ // read truetype or opentype table + FileIn in(font.Fi().path); + int q = in.Get32be(); + if(q == 0x74746366) { // font collection + in.Get32(); // skip major/minor version + int nfonts = in.Get32be(); + if(font.Fi().fonti >= nfonts) + return Null; + in.SeekCur(font.Fi().fonti * 4); + int offset = in.Get32be(); + if(offset < 0 || offset >= in.GetSize()) + return Null; + in.Seek(offset); + q = in.Get32be(); + } + if(q != 0x74727565 && q != 0x00010000 && q != 0x4f54544f) // 0x4f54544f means CCF font! + return Null; + int n = in.Get16be(); + in.Get32(); + in.Get16(); + while(n--) { + if(in.IsError() || in.IsEof()) return Null; + String tab = in.Get(4); + in.Get32(); + int off = in.Get32be(); + int len = in.Get32be(); + if(tab == table) { + if(off < 0 || len < 0 || off + len > in.GetSize()) + return Null; + len = min(len - offset, size); + if(len < 0) + return Null; + in.Seek(off + offset); + return in.Get(len); + } + } + return Null; } struct sCGPathTarget { diff --git a/uppsrc/Draw/FontFc.cpp b/uppsrc/Draw/FontFc.cpp index 9e8ecfe6f..b839e4f29 100644 --- a/uppsrc/Draw/FontFc.cpp +++ b/uppsrc/Draw/FontFc.cpp @@ -148,7 +148,8 @@ CommonFontInfo GetFontInfoSys(Font font) fi.avewidth = fi.maxwidth; fi.default_char = '?'; fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH; - fi.ttf = path.EndsWith(".ttf") || path.EndsWith(".otf"); + fi.ttf = path.EndsWith(".ttf") || path.EndsWith(".otf") || path.EndsWith(".otc") || path.EndsWith(".ttc"); + fi.fonti = face->face_index; if(path.GetCount() < 250) strcpy(fi.path, ~path); else @@ -164,21 +165,6 @@ CommonFontInfo GetFontInfoSys(Font font) GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr); -#ifdef flagLINUXGL -#include -#include -GlyphInfo GetGlyphInfoSys(Font font, int chr) -{ - static GlyphInfo gi; - const OpenGLFont& fi = resources.GetFont(font); - gi.width = chr < fi.chars.GetCount() - ? int(fi.chars[chr].xadvance * fi.scale + 0.5f) - : 0; - gi.lspc = 0; - gi.rspc = 0; - return gi; -} -#else GlyphInfo GetGlyphInfoSys(Font font, int chr) { LTIMING("GetGlyphInfoSys"); @@ -207,7 +193,6 @@ GlyphInfo GetGlyphInfoSys(Font font, int chr) } return gi; } -#endif Vector GetAllFacesSys() { @@ -218,10 +203,11 @@ Vector GetAllFacesSys() "monospace", }; - Vector list; + VectorMap list; for(int i = 0; i < __countof(basic_fonts); i++) { - FaceInfo& fi = list.Add(); - fi.name = basic_fonts[i]; + String name = (const char *)basic_fonts[i]; + FaceInfo& fi = list.Add(name); + fi.name = name; fi.info = Font::SCALEABLE; if(i == Font::SERIF) fi.info |= Font::SERIFSTYLE; @@ -229,7 +215,7 @@ Vector GetAllFacesSys() fi.info |= Font::FIXEDPITCH; } FcPattern *p = FcPatternCreate(); - FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_SCALABLE, (void *)0); + FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_SCALABLE, FC_SYMBOL, FC_COLOR, (void *)0); FcFontSet *fs = FcFontList(NULL, p, os); FcPatternDestroy(p); FcObjectSetDestroy(os); @@ -237,29 +223,68 @@ Vector GetAllFacesSys() FcChar8 *family = NULL; FcPattern *pt = fs->fonts[i]; if(FcPatternGetString(pt, FC_FAMILY, 0, &family) == 0 && family) { - FaceInfo& fi = list.Add(); - fi.name = (const char *)family; - fi.info = 0; + String name = (const char *)family; + FaceInfo& fi = list.GetAdd(name); + fi.name = name; int iv; + FcBool bv; if(FcPatternGetInteger(pt, FC_SPACING, 0, &iv) == 0 && iv == FC_MONO) fi.info |= Font::FIXEDPITCH; - FcBool bv; + if(FcPatternGetBool(pt, FC_SYMBOL, 0, &bv) == 0 && bv) + fi.info |= Font::SPECIAL; + if(FcPatternGetBool(pt, FC_COLOR, 0, &bv) == 0 && bv) + fi.info |= Font::SPECIAL; if(FcPatternGetBool(pt, FC_SCALABLE, 0, &bv) == 0 && bv) fi.info |= Font::SCALEABLE; String h = ToLower(fi.name); - if(h.Find("serif") >= 0 && h.Find("sans") < 0) + if((h.Find("serif") >= 0 || h.Find("roman") >= 0) && h.Find("sans") < 0) fi.info |= Font::SERIFSTYLE; if(h.Find("script") >= 0) fi.info |= Font::SCRIPTSTYLE; } } FcFontSetDestroy(fs); - return list; + return list.PickValues(); } -String GetFontDataSys(Font font) -{ - return LoadFile(font.Fi().path); +String GetFontDataSys(Font font, const char *table, int offset, int size) +{ // read truetype or opentype table + FileIn in(font.Fi().path); + int q = in.Get32be(); + if(q == 0x74746366) { // font collection + in.Get32(); // skip major/minor version + int nfonts = in.Get32be(); + if(font.Fi().fonti >= nfonts) + return Null; + in.SeekCur(font.Fi().fonti * 4); + int offset = in.Get32be(); + if(offset < 0 || offset >= in.GetSize()) + return Null; + in.Seek(offset); + q = in.Get32be(); + } + if(q != 0x74727565 && q != 0x00010000 && q != 0x4f54544f) // 0x4f54544f means CCF font! + return Null; + int n = in.Get16be(); + in.Get32(); + in.Get16(); + while(n--) { + if(in.IsError() || in.IsEof()) return Null; + String tab = in.Get(4); + in.Get32(); + int off = in.Get32be(); + int len = in.Get32be(); + if(tab == table) { + if(off < 0 || len < 0 || off + len > in.GetSize()) + return Null; + len = min(len - offset, size); + if(len < 0) + return Null; + in.Seek(off + offset); + return in.Get(len); + } + } + return Null; } static inline double ft_dbl(int p) diff --git a/uppsrc/Draw/FontInt.h b/uppsrc/Draw/FontInt.h index e76a57bb5..1f1886e93 100644 --- a/uppsrc/Draw/FontInt.h +++ b/uppsrc/Draw/FontInt.h @@ -5,7 +5,7 @@ struct FaceInfo : Moveable { String name; - dword info; + dword info = 0; }; struct CommonFontInfo { @@ -26,7 +26,8 @@ struct CommonFontInfo { bool ttf; int aux; - char path[256]; // optional + char path[256]; // optional (linux only) + int fonti = 0; // font index in .ttc, .otc }; class Font; @@ -35,7 +36,7 @@ struct GlyphInfo { int16 width; int16 lspc; int16 rspc; - word glyphi; // optional, not available in Win32 + word glyphi = 0; // optional, not available in Win32, X11 bool IsNormal() const { return (word)width != 0x8000; } bool IsComposed() const { return !IsNormal() && (lspc == -1 || lspc == -11); } @@ -47,7 +48,7 @@ struct GlyphInfo { void Std(Font& font); GlyphInfo GetGlyphInfo(Font font, int chr); const CommonFontInfo& GetFontInfo(Font font); -bool IsNormal(Font font, int chr); +bool IsNormal_nc(Font font, int chr); void GlyphMetrics(GlyphInfo& f, Font font, int chr); void InvalidateFontList(); @@ -57,7 +58,7 @@ void InvalidateFontList(); CommonFontInfo GetFontInfoSys(Font font); GlyphInfo GetGlyphInfoSys(Font font, int chr); Vector GetAllFacesSys(); -String GetFontDataSys(Font font); +String GetFontDataSys(Font font, const char *table, int offset, int size); void RenderCharacterSys(FontGlyphConsumer& sw, double x, double y, int ch, Font fnt); diff --git a/uppsrc/Draw/FontWin32.cpp b/uppsrc/Draw/FontWin32.cpp index e1594cc89..650d202c4 100644 --- a/uppsrc/Draw/FontWin32.cpp +++ b/uppsrc/Draw/FontWin32.cpp @@ -6,6 +6,8 @@ namespace Upp { #ifdef PLATFORM_WIN32 +#include + #define LLOG(x) // LOG(x) #define LTIMING(x) // TIMING(x) @@ -152,7 +154,7 @@ static int CALLBACK Win32_AddFace(const LOGFONTW *logfont, const TEXTMETRICW *, static int Win32_EnumFace(HDC hdc, const char *face) { - return EnumFontFamiliesW(hdc, face ? ~ToSystemCharsetW(face) : NULL, Win32_AddFace, (LPARAM)face); + return EnumFontFamiliesW(hdc, face ? ToSystemCharsetW(face).begin() : NULL, Win32_AddFace, (LPARAM)face); } static void Win32_ForceFace(HDC hdc, const char *face, const char *aface) @@ -183,8 +185,87 @@ Vector GetAllFacesSys() #define GLYPHINFOCACHE 31 +GlyphInfo GetUnicodeGlyphInfo(Font fnt, wchar ch) +{ + struct FontRec { + Font font = Null; + SCRIPT_CACHE sc = NULL; + HDC hdc = NULL; + dword default_glyph = 0; + }; + + static FontRec cache[4]; + static int cachei; + + int ii = -1; + for(int i = 0; i < 4; i++) + if(cache[0].font == fnt) { + ii = i; + break; + } + + if(ii < 0) { + ii = cachei = (cachei + 1) & 3; + FontRec& f = cache[ii]; + f.font = fnt; + if(!f.hdc) + f.hdc = ::CreateIC("DISPLAY", NULL, NULL, NULL); + if(f.sc) { + ScriptFreeCache(&f.sc); + f.sc = 0; + } + HFONT hfont = GetWin32Font(fnt, 0); + if(hfont) + ::SelectObject(f.hdc, hfont); + + SCRIPT_FONTPROPERTIES props; + props.cBytes = sizeof(props); + ScriptGetFontProperties(f.hdc, &f.sc, &props); + f.default_glyph = props.wgDefault; + } + + GlyphInfo gi; + + memset(&gi, 0, sizeof(gi)); + gi.width = (int16)0x8000; + + FontRec& f = cache[ii]; + + char16 buf[2]; + int len = ToUtf16(buf, &ch, 1); + + SCRIPT_ITEM items[2]; + int nitems; + if(FAILED(ScriptItemize(buf, len, 2, 0, 0, items, &nitems))) + return gi; + + WORD glyphs[10]; + WORD cluster[10]; + int nglyphs; + SCRIPT_VISATTR attr[10]; + if(FAILED(ScriptShape(f.hdc, &f.sc, buf, len, 10, &items[0].a, glyphs, cluster, attr, &nglyphs))) + return gi; + + if(nglyphs == 0 || *glyphs == f.default_glyph) + return gi; + + ABC abc; + if(FAILED(ScriptGetGlyphABCWidth(f.hdc, &f.sc, glyphs[0], &abc))) + return gi; + + gi.width = abc.abcA + abc.abcB + abc.abcC; + gi.lspc = abc.abcA; + gi.rspc = abc.abcC; + gi.glyphi = *glyphs; + + return gi; +} + GlyphInfo GetGlyphInfoSys(Font font, int chr) { + if(chr >= 0x10000) + return GetUnicodeGlyphInfo(font, chr); + static Font fnt[GLYPHINFOCACHE]; static int pg[GLYPHINFOCACHE]; static GlyphInfo li[GLYPHINFOCACHE][256]; @@ -203,7 +284,8 @@ GlyphInfo GetGlyphInfoSys(Font font, int chr) HFONT hfont = GetWin32Font(font, 0); if(!hfont) { GlyphInfo n; - memset8(&n, 0, sizeof(GlyphInfo)); + memset(&n, 0, sizeof(GlyphInfo)); + n.width = (int16)0x8000; return n; } HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL); @@ -255,20 +337,22 @@ GlyphInfo GetGlyphInfoSys(Font font, int chr) return li[q][chr & 255]; } -String GetFontDataSys(Font font) +String GetFontDataSys(Font font, const char *table, int offset, int size) { String r; HFONT hfont = GetWin32Font(font, 0); if(hfont) { HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL); HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); - DWORD size = GetFontData(hdc, 0, 0, NULL, 0); - if(size == GDI_ERROR) { + int tbl = table ? ((byte)table[0] << 0) | ((byte)table[1] << 8) | ((byte)table[2] << 16) | ((byte)table[3] << 24) : 0; + DWORD sz = GetFontData(hdc, tbl, offset, NULL, 0); + if(sz == GDI_ERROR) { LLOG("PdfDraw::Finish: GDI_ERROR on font " << pdffont.GetKey(i)); } else { + size = min(size, (int)sz); StringBuffer b(size); - GetFontData(hdc, 0, 0, b, size); + GetFontData(hdc, tbl, offset, ~b, size); r = b; } ::SelectObject(hdc, ohfont); @@ -327,10 +411,20 @@ void RenderCharacterSys(FontGlyphConsumer& sw, double x, double y, int ch, Font memset8(&m_matrix, 0, sizeof(m_matrix)); m_matrix.eM11.value = 1; m_matrix.eM22.value = 1; - int gsz = GetGlyphOutlineW(hdc, ch, GGO_NATIVE|GGO_UNHINTED, &gm, 0, NULL, &m_matrix); + dword flags = GGO_NATIVE|GGO_UNHINTED; + if(ch >= 0x10000) { + GlyphInfo f = GetGlyphInfo(fnt, ch); + if(f.IsNormal()) { + flags |= GGO_GLYPH_INDEX; + ch = f.glyphi; + } + else + ch = 0x25a1; + } + int gsz = GetGlyphOutlineW(hdc, ch, flags, &gm, 0, NULL, &m_matrix); if(gsz >= 0) { StringBuffer gb(gsz); - gsz = GetGlyphOutlineW(hdc, ch, GGO_NATIVE|GGO_UNHINTED, &gm, gsz, ~gb, &m_matrix); + gsz = GetGlyphOutlineW(hdc, ch, flags, &gm, gsz, ~gb, &m_matrix); if(gsz >= 0) RenderCharPath(~gb, gsz, sw, x, y + fnt.GetAscent()); } diff --git a/uppsrc/Draw/Fonts.i b/uppsrc/Draw/Fonts.i new file mode 100644 index 000000000..ccbb43751 --- /dev/null +++ b/uppsrc/Draw/Fonts.i @@ -0,0 +1,388 @@ +// Predefined replacement fonts; if codepoint is not found in these, remaining fonts cmaps from host are loaded + +#if defined(PLATFORM_POSIX) && !defined(PLATFORM_COCOA) +{ "Abyssinica SIL", { 2,0,0,0,0,0,0,0,0,0 }, { 0xfe1d0000,0x23400000,0x0080010c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Andale Mono", { 2,11,5,9,0,0,0,0,0,4 }, { 0xff17e000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "AnjaliOldLipi", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Chandas", { 2,0,0,0,0,0,0,0,0,0 }, { 0xe0000000,0x82000000,0x00000034,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Chilanka", { 2,0,5,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "DejaVu Sans", { 2,11,6,3,3,8,4,2,2,4 }, { 0xfffffff1,0x77c04000,0x0100007e,0x00000000,0x00003070,0x00000000,0x00000000,0x00000000 } }, +{ "DejaVu Sans Mono", { 2,11,6,9,3,8,4,2,2,4 }, { 0xfffffef0,0x67c00000,0x0100001c,0x00000000,0x00001000,0x00000000,0x00000000,0x00000000 } }, +{ "DejaVu Serif", { 2,6,6,3,5,6,5,2,2,4 }, { 0xfffffe00,0x67c00000,0x0100001c,0x00000000,0x00001000,0x00000000,0x00000000,0x00000000 } }, +{ "Droid Sans Fallback", { 2,11,5,2,0,0,0,0,0,1 }, { 0x80000000,0x623fffff,0xfc40100d,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Dyuthi", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "FreeMono", { 2,15,4,9,2,2,5,2,4,4 }, { 0xfffffff0,0x37c00000,0x0180000e,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "FreeSans", { 2,11,5,4,2,2,2,2,2,4 }, { 0xffffff0c,0xffc00000,0x0100000f,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "FreeSerif", { 2,2,6,3,5,4,5,2,3,4 }, { 0xfffffff6,0xffc00000,0x0180000e,0x00000000,0x00003020,0x00000000,0x00000000,0x00000000 } }, +{ "Gargi", { 2,0,5,6,0,0,0,0,0,0 }, { 0xc0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Garuda", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfeba0000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gayathri", { 0,0,5,3,0,0,0,0,0,0 }, { 0xfd000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gubbi", { 0,0,4,0,0,0,0,0,0,0 }, { 0x80000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Impact", { 2,11,8,6,3,9,2,5,2,4 }, { 0xff17e000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Jamrul", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstArt", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstBook", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstDecorative", { 2,0,0,0,0,0,0,0,0,0 }, { 0xc00000f0,0x00000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstDigital", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstFarsi", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstLetter", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstNaskh", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstOffice", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstOne", { 2,0,5,3,0,0,0,0,0,0 }, { 0xf00000f0,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstPen", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstPoster", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstQurn", { 0,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstScreen", { 0,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstTitle", { 2,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KacstTitleL", { 0,0,0,0,0,0,0,0,0,0 }, { 0x800000d0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kalapi", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf0080000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kalimati", { 0,0,4,0,0,0,0,0,0,0 }, { 0xc0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Karumbi", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Keraleeyam", { 2,11,8,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Khmer OS", { 2,0,5,0,0,0,0,2,0,4 }, { 0xfe1b0000,0x1f000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Khmer OS System", { 2,0,5,0,0,0,0,2,0,4 }, { 0xfe1b0000,0x1f000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kinnari", { 0,0,0,0,0,0,0,0,0,0 }, { 0xfeb80000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Laksaman", { 2,11,5,0,4,2,0,2,0,3 }, { 0xfe380000,0x47000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Liberation Mono", { 2,7,4,9,2,2,5,2,4,4 }, { 0xfffffb00,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Liberation Mono", { 2,7,4,9,2,2,5,2,4,4 }, { 0xfffffb00,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Liberation Sans", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffb00,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Liberation Sans Narrow", { 2,11,6,6,2,2,2,3,2,4 }, { 0xff97e000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Liberation Serif", { 2,2,6,3,5,4,5,2,3,4 }, { 0xfffffb00,0x07400000,0x0100002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Likhan", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Assamese", { 2,11,6,0,0,0,0,0,0,0 }, { 0xf0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Bengali", { 2,11,6,0,0,0,0,0,0,0 }, { 0xf0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Devanagari", { 2,11,6,0,0,0,0,0,0,0 }, { 0xfeb90000,0x87000000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Gujarati", { 2,11,6,0,0,0,0,0,0,0 }, { 0xd0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Gurmukhi", { 2,11,6,0,0,0,0,0,0,0 }, { 0xd0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Kannada", { 2,11,6,0,0,0,0,0,0,0 }, { 0xf0000000,0xc3000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Malayalam", { 2,11,6,0,0,0,0,0,0,0 }, { 0x80000000,0xc3000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Odia", { 2,11,6,0,0,0,0,0,0,0 }, { 0x80000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Tamil", { 2,11,6,0,0,0,0,0,0,0 }, { 0xf0280000,0x83000000,0x00000024,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Tamil Classical", { 2,11,6,0,0,0,0,0,0,0 }, { 0xf0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lohit Telugu", { 2,11,6,0,0,0,0,0,0,0 }, { 0xfeb00000,0xc3000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Loma", { 2,11,5,4,2,2,2,2,2,4 }, { 0xfcb80000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Manjari", { 2,0,5,3,0,0,0,0,0,0 }, { 0xfd100000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Manjari", { 2,0,5,3,0,0,0,0,0,0 }, { 0xfd100000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Meera", { 2,11,6,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mitra Mono", { 0,11,0,9,0,0,0,0,0,0 }, { 0xf0000000,0x81000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mukti Narrow", { 0,0,0,0,0,0,0,0,0,0 }, { 0xf0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mukti Narrow", { 0,0,0,0,0,0,0,0,0,0 }, { 0xf0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Nakula", { 0,0,4,0,0,0,0,0,0,0 }, { 0xff13e000,0x87000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Navilu", { 0,0,4,0,0,0,0,0,0,0 }, { 0x80000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Norasi", { 2,7,5,6,6,0,0,2,0,4 }, { 0xfeb80000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Mono", { 2,11,6,9,3,8,4,2,2,4 }, { 0xffbbf800,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans CJK HK", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans CJK JP", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans CJK KR", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans CJK SC", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans CJK TC", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans Mono CJK HK", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans Mono CJK JP", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans Mono CJK KR", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans Mono CJK SC", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Sans Mono CJK TC", { 2,11,5,0,0,0,0,0,0,0 }, { 0xff7bc000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Serif CJK JP", { 2,2,4,0,0,0,0,0,0,0 }, { 0xff53c000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Serif CJK KR", { 2,2,4,0,0,0,0,0,0,0 }, { 0xff53c000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Serif CJK SC", { 2,2,4,0,0,0,0,0,0,0 }, { 0xff53c000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Noto Serif CJK TC", { 2,2,4,0,0,0,0,0,0,0 }, { 0xff53c000,0x27ffffff,0xfcfff00c,0x00000000,0x00000023,0xffffffff,0xffffd308,0x00000000 } }, +{ "Padauk", { 2,0,4,0,2,0,0,2,0,4 }, { 0xfe150000,0x33000000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Padauk Book", { 2,0,4,0,2,0,0,2,0,4 }, { 0xfe150000,0x33000000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Pagul", { 2,0,5,0,0,0,0,0,0,0 }, { 0xf8140000,0x02000000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Phetsarath OT", { 2,0,5,0,0,0,0,0,0,1 }, { 0xfe100000,0x42000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Pothana2000", { 0,0,4,0,0,0,0,0,0,0 }, { 0xd0000000,0x42000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Purisa", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfcb80000,0x43000000,0x0000003c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Rachana", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "RaghuMalayalamSans", { 2,11,4,0,0,0,0,0,0,0 }, { 0xc0000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Rasa", { 2,13,0,0,0,4,0,0,0,0 }, { 0xfffb0000,0xc7000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Rekha", { 2,0,6,0,4,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Saab", { 2,0,5,0,0,0,0,2,0,4 }, { 0xf0100000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sahadeva", { 0,0,4,0,0,0,0,0,0,0 }, { 0xff13e000,0x87000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Samanata", { 0,0,4,0,0,0,0,0,0,0 }, { 0xd0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Samyak Devanagari", { 2,0,6,3,0,0,0,0,0,0 }, { 0x80000000,0x81000000,0x00000080,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001 } }, +{ "Samyak Gujarati", { 2,0,6,3,0,0,0,0,0,0 }, { 0x80000000,0x80000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Samyak Malayalam", { 0,0,4,0,0,0,0,0,0,0 }, { 0x80000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Samyak Tamil", { 2,0,6,3,0,0,0,0,0,0 }, { 0x84000000,0x80000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sarai", { 0,0,4,0,0,0,0,0,0,0 }, { 0xd0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sawasdee", { 2,0,5,3,0,0,0,0,0,0 }, { 0xfeb80000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Suruma", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Symbola", { 2,2,5,3,6,8,5,2,2,4 }, { 0xfffff810,0x0fe04000,0x0180000e,0x00000000,0x00003038,0x00000000,0x00000000,0x00000001 } }, +{ "Tibetan Machine Uni", { 1,0,5,3,2,0,0,2,0,2 }, { 0xffbd0000,0x47203000,0x0000007c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001 } }, +{ "Tlwg Mono", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfcb80000,0x43000000,0x00000014,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tlwg Typewriter", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfcb80000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tlwg Typist", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfcb80000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tlwg Typo", { 2,0,6,3,0,0,0,0,0,0 }, { 0xfcb80000,0x43000000,0x00000014,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ubuntu", { 2,11,5,4,3,6,2,3,2,4 }, { 0xfffbf000,0x07000000,0x0000027c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ubuntu", { 2,11,5,4,3,6,2,3,2,4 }, { 0xfffbf000,0x07000000,0x0000027c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ubuntu", { 2,11,5,4,3,6,2,3,2,4 }, { 0xfffbf000,0x07000000,0x0000027c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ubuntu Condensed", { 2,11,5,6,3,6,2,3,2,4 }, { 0xfffbf000,0x07000000,0x0000027c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ubuntu Mono", { 2,11,5,9,3,6,2,3,2,4 }, { 0xfffbf000,0x07000000,0x0000027c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Uroob", { 0,0,8,0,0,0,0,0,0,0 }, { 0xfc100000,0x43000000,0x00000264,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Vemana2000", { 0,0,4,0,0,0,0,0,0,0 }, { 0xd0000000,0x42000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Verdana", { 2,11,6,4,3,5,4,4,2,4 }, { 0xff1fe000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Waree", { 2,11,5,4,2,2,2,2,2,4 }, { 0xfebb0000,0x43000000,0x0000005c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Yrsa", { 2,13,0,0,0,4,0,0,0,0 }, { 0xfffb0000,0x07000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "mry_KacstQurn", { 2,6,6,3,5,6,5,2,2,4 }, { 0x800000f0,0x00000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "padmaa", { 2,0,8,0,4,0,0,0,0,0 }, { 0xf6100000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "padmaa-Bold.1.1", { 2,0,8,0,4,0,0,0,0,0 }, { 0xf6100000,0x82000000,0x00000084,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +#endif + +#ifdef PLATFORM_WIN32 +{ "Alef", { 0,0,5,0,0,0,0,0,0,0 }, { 0xfc900300,0x06000000,0x0000020c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Amiri", { 0,0,5,0,0,0,0,0,0,0 }, { 0xfdb800f4,0x87000000,0x0000000c,0x00000000,0x00000040,0x00000000,0x00000000,0x00000000 } }, +{ "Amiri Quran", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe00800f0,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arabic Transparent", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffff4,0x87400000,0x0180002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffff4,0x87400000,0x0180002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Black", { 2,11,10,4,2,1,2,2,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Caladea", { 2,0,5,6,0,0,0,2,0,0 }, { 0xff900000,0x06000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Carlito", { 2,15,5,2,2,2,4,3,2,4 }, { 0xfffff800,0x47400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Consolas", { 2,11,6,9,2,2,4,3,2,4 }, { 0xfffffe00,0x47400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Constantia", { 2,3,6,2,5,3,6,3,3,3 }, { 0xff9fe000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Corbel", { 2,11,5,3,2,2,4,2,2,4 }, { 0xffffea80,0xd7000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Corbel Light", { 2,11,3,3,2,2,4,2,2,4 }, { 0xffffea80,0xd7000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Courier New", { 2,7,3,9,2,2,5,2,4,4 }, { 0xfffffff4,0xc7400000,0x0100002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "David CLM", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000300,0x03000000,0x0000008c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "David Libre", { 0,0,5,0,0,0,0,0,0,0 }, { 0xffff0300,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ebrima", { 2,0,0,0,0,0,0,0,0,0 }, { 0xffff00c1,0x27400000,0x0180000d,0x00000000,0x00000080,0x00000000,0x00000000,0x00000000 } }, +{ "Frank Ruehl CLM", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000300,0x03000000,0x0000008c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Frank Ruhl Hofshi", { 0,0,5,0,0,0,0,0,0,0 }, { 0xfe990300,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Franklin Gothic Medium", { 2,11,6,3,2,1,2,2,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gadugi", { 2,11,5,2,4,2,4,2,2,3 }, { 0xff5c0000,0x3b000000,0x00800009,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gentium Basic", { 2,0,5,3,6,0,0,2,0,4 }, { 0xffff0000,0x07400000,0x0100002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gentium Book Basic", { 2,0,5,3,6,0,0,2,0,4 }, { 0xffff0000,0x07400000,0x0100002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "HoloLens MDL2 Assets", { 5,10,1,2,1,1,1,1,1,1 }, { 0x80000000,0x00000000,0x000001e4,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ink Free", { 3,8,4,2,0,5,0,0,0,0 }, { 0xff900000,0x02000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Javanese Text", { 2,0,0,0,0,0,0,0,0,0 }, { 0xf6140000,0x03000000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Leelawadee UI", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe190000,0x5f000000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Leelawadee UI Semilight", { 2,11,4,2,4,2,4,2,2,3 }, { 0xfe190000,0x5f000000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lucida Console", { 2,11,6,9,4,5,4,2,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lucida Sans Unicode", { 2,11,6,2,3,5,4,2,2,4 }, { 0xfffff300,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "MS Gothic", { 2,11,6,9,7,2,5,8,2,4 }, { 0xff7ff000,0xd7bfffff,0xfc00000c,0x00000000,0x00000023,0xffffffff,0xff000000,0x00000000 } }, +{ "MS PGothic", { 2,11,6,0,7,2,5,8,2,4 }, { 0xff7ff000,0xd7bfffff,0xfc00000c,0x00000000,0x00000023,0xffffffff,0xff000000,0x00000000 } }, +{ "MS UI Gothic", { 2,11,6,0,7,2,5,8,2,4 }, { 0xff7ff000,0xd7bfffff,0xfc00000c,0x00000000,0x00000023,0xffffffff,0xff000000,0x00000000 } }, +{ "MV Boli", { 2,0,5,0,3,2,0,9,0,0 }, { 0xfe120082,0x03000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Malgun Gothic", { 2,11,5,3,2,0,0,2,0,4 }, { 0xfe13c000,0x233fffff,0xfcfff00c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Malgun Gothic Semilight", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe13c000,0x23200000,0x007ff004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft Himalaya", { 1,1,1,0,1,1,1,1,1,1 }, { 0xf6120000,0x43200000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft JhengHei", { 2,11,6,4,3,5,4,4,2,4 }, { 0xfe1f0000,0x037fffff,0xfc00000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft JhengHei Light", { 2,11,3,4,3,5,4,4,2,4 }, { 0xfe1fc000,0x037fffff,0xfc00000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft JhengHei UI", { 2,11,6,4,3,5,4,4,2,4 }, { 0xfe1f0000,0x037fffff,0xfc00000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft JhengHei UI Light", { 2,11,3,4,3,5,4,4,2,4 }, { 0xfe1fc000,0x037fffff,0xfc00000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft New Tai Lue", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe100000,0x0b200000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft PhagsPa", { 2,11,5,2,4,2,4,2,2,3 }, { 0xffd80000,0x0f202000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft Sans Serif", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffff6,0xf7400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft Tai Le", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe180000,0x2b200000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft YaHei", { 2,11,5,3,2,2,4,2,2,4 }, { 0xffd7e000,0x077fffff,0xfc00000c,0x00000000,0x00000003,0x701497c5,0xc5ffc000,0x00000000 } }, +{ "Microsoft YaHei Light", { 2,11,5,2,4,2,4,2,2,3 }, { 0xffd7e000,0x077fffff,0xfc00000c,0x00000000,0x00000003,0x701497c5,0xc5ffc000,0x00000000 } }, +{ "Microsoft YaHei UI", { 2,11,5,3,2,2,4,2,2,4 }, { 0xffd7e000,0x077fffff,0xfc00000c,0x00000000,0x00000003,0x701497c5,0xc5ffc000,0x00000000 } }, +{ "Microsoft YaHei UI Light", { 2,11,5,2,4,2,4,2,2,3 }, { 0xffd7e000,0x077fffff,0xfc00000c,0x00000000,0x00000003,0x701497c5,0xc5ffc000,0x00000000 } }, +{ "Microsoft Yi Baiti", { 3,0,5,0,0,0,0,0,0,0 }, { 0xf6100000,0x03200000,0x03000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "MingLiU-ExtB", { 2,2,5,0,0,0,0,0,0,0 }, { 0xf6100000,0x02000000,0x00000000,0x00000000,0x00000003,0xffffffff,0xfff80008,0x00000000 } }, +{ "MingLiU_HKSCS-ExtB", { 2,2,5,0,0,0,0,0,0,0 }, { 0xf6100000,0x02000000,0x00000000,0x00000000,0x00000003,0xffffffff,0xfff80008,0x00000000 } }, +{ "Miriam CLM", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000300,0x03000000,0x0000008c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Miriam Libre", { 0,0,5,0,0,0,0,0,0,0 }, { 0xfe990300,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Miriam Mono CLM", { 2,0,5,3,0,0,0,0,0,0 }, { 0xe0000300,0x03000000,0x0000008c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mongolian Baiti", { 3,0,5,0,0,0,0,0,0,0 }, { 0xf61a0000,0x0b200000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Myanmar Text", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe140000,0x23000000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "NSimSun", { 2,1,6,9,3,1,1,1,1,1 }, { 0xff53c000,0x037fffff,0xfc00018c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Nachlieli CLM", { 2,0,6,3,0,0,0,0,0,0 }, { 0xe0000300,0x03000000,0x0000008c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Kufi Arabic", { 2,11,5,6,3,8,4,2,2,4 }, { 0xa00000f4,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Mono", { 2,11,6,9,3,8,4,2,2,4 }, { 0xffbbf800,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Naskh Arabic", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa00000f4,0x83400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Naskh Arabic UI", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa00000f4,0x83400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans", { 2,11,5,2,4,5,4,2,2,4 }, { 0xfffff800,0x0e400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Arabic", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa00400f4,0x83400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Arabic UI", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa00400f4,0x83400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Armenian", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa0000e00,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Cond", { 2,11,5,6,4,5,4,2,2,4 }, { 0xfffff800,0x0e400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Georgian", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa0080200,0x22400000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Hebrew", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa0000300,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Lao", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa0000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Light", { 2,11,4,2,4,5,4,2,2,4 }, { 0xfffff800,0x0e400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Lisu", { 2,11,5,2,4,5,4,2,2,4 }, { 0xa0300000,0x02200000,0x01000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif", { 2,2,5,2,6,5,5,2,2,4 }, { 0xfffff800,0x0e400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Armenian", { 2,2,5,2,6,5,5,2,2,4 }, { 0xa0000e00,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Cond", { 2,2,5,6,6,5,5,2,2,4 }, { 0xfffff800,0x0e400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Georgian", { 2,2,5,2,6,5,5,2,2,4 }, { 0xa0080200,0x22400000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Hebrew", { 2,2,5,2,6,5,5,2,2,4 }, { 0xa0000300,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Lao", { 2,2,5,2,6,5,5,2,2,4 }, { 0xa0000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Light", { 2,2,4,2,6,5,5,2,2,4 }, { 0xfffff800,0x0e400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "OpenSymbol", { 5,1,0,0,0,0,0,0,0,0 }, { 0xf61b0000,0x03a00000,0x0000030c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PMingLiU-ExtB", { 2,2,5,0,0,0,0,0,0,0 }, { 0xf6100000,0x02000000,0x00000000,0x00000000,0x00000003,0xffffffff,0xfff80008,0x00000000 } }, +{ "Segoe Print", { 2,0,6,0,0,0,0,0,0,0 }, { 0xffd7e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe Script", { 3,11,5,4,2,0,0,0,0,3 }, { 0xff9be000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfffffff5,0xff400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Black", { 2,11,10,2,4,2,4,2,2,3 }, { 0xfffff800,0x47400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Emoji", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe100000,0x03a00000,0x0000020c,0x00000000,0x00000038,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Historic", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe1f00cc,0x13400000,0x00000007,0xe3300000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Light", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfffffff5,0xff400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Semibold", { 2,11,7,2,4,2,4,2,2,3 }, { 0xfffffff5,0xff400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Semilight", { 2,11,4,2,4,2,4,2,2,3 }, { 0xfffffff5,0xff400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Segoe UI Symbol", { 2,11,5,2,4,2,4,2,2,3 }, { 0xfe1f0000,0x03e04000,0x00000225,0x00000000,0x00003038,0x00000000,0x00000000,0x00000000 } }, +{ "SimSun", { 2,1,6,0,3,1,1,1,1,1 }, { 0xff53c000,0x037fffff,0xfc00018c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "SimSun-ExtB", { 2,1,6,9,6,1,1,1,1,1 }, { 0xc0000000,0x00000000,0x00000000,0x00000000,0x00000003,0xffffffff,0xffffc000,0x00000000 } }, +{ "Sylfaen", { 1,10,5,2,5,3,6,3,3,3 }, { 0xff9fee00,0x27400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tahoma", { 2,11,6,4,3,5,4,4,2,4 }, { 0xfffffff6,0xd7400000,0x0180000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Times New Roman", { 2,2,6,3,5,4,5,2,3,4 }, { 0xfffffff4,0x87400000,0x0180002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Yu Gothic", { 2,11,4,0,0,0,0,0,0,0 }, { 0xffffc000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +{ "Yu Gothic Light", { 2,11,3,0,0,0,0,0,0,0 }, { 0xffffc000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +{ "Yu Gothic Medium", { 2,11,5,0,0,0,0,0,0,0 }, { 0xffffc000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +{ "Yu Gothic UI", { 2,11,5,0,0,0,0,0,0,0 }, { 0xffffe000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +{ "Yu Gothic UI Light", { 2,11,3,0,0,0,0,0,0,0 }, { 0xffffe000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +{ "Yu Gothic UI Semibold", { 2,11,7,0,0,0,0,0,0,0 }, { 0xffffe000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +{ "Yu Gothic UI Semilight", { 2,11,4,0,0,0,0,0,0,0 }, { 0xffffe000,0xd7ffffff,0xfc00000c,0x00000000,0x00200023,0xffffffff,0xff981308,0x00000000 } }, +#endif + +#ifdef PLATFORM_COCOA +{ "Al Bayan", { 0,0,0,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Al Nile", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Al Tarikh", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Andale Mono", { 2,11,5,9,0,0,0,0,0,4 }, { 0xff17e000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Apple Chancery", { 3,2,7,2,4,5,6,6,5,4 }, { 0xff9b0000,0x03000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Apple Color Emoji", { 0,0,0,0,0,0,0,0,0,0 }, { 0xa0000000,0x03a00000,0x00000004,0x00000000,0x00000038,0x00000000,0x00000000,0x00000001 } }, +{ "Apple SD Gothic Neo", { 2,0,3,0,0,0,0,0,0,0 }, { 0xfdbfd000,0x27e07fff,0xfc7ff00c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Apple Symbols", { 2,0,0,0,0,0,0,0,0,0 }, { 0xf23f0000,0x17e04000,0x01000007,0x00000000,0x00003030,0x00000000,0x00000000,0x00000000 } }, +{ "Arial", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffbf4,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Black", { 2,11,10,4,2,1,2,2,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Hebrew", { 0,0,0,0,0,0,0,0,0,0 }, { 0xe0040300,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Hebrew Scholar", { 0,0,0,0,0,0,0,0,0,0 }, { 0xe0040300,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Narrow", { 2,11,6,6,2,2,2,3,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Rounded MT Bold", { 2,15,7,4,3,5,4,3,2,4 }, { 0xfe110000,0x03000000,0x00000024,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Arial Unicode MS", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffff0,0xe7207fff,0xfc7ff0bc,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Avenir", { 2,0,5,3,2,0,0,2,0,3 }, { 0xfe930000,0x03000000,0x0000020c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Avenir Next", { 2,11,8,3,2,2,2,2,2,4 }, { 0xffbff000,0x07000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Avenir Next Condensed", { 2,11,8,6,2,2,2,2,2,4 }, { 0xfe970000,0x03000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Ayuthaya", { 0,0,4,0,0,0,0,0,0,0 }, { 0xffdff000,0x47000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Baghdad", { 1,0,5,0,0,0,0,2,0,4 }, { 0xf00000f0,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bangla MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bangla Sangam MN", { 2,0,0,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Baskerville", { 2,2,5,2,7,4,1,2,3,3 }, { 0xfffff000,0x07400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Beirut", { 0,0,6,0,0,0,0,0,0,0 }, { 0xf00000f0,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Big Caslon", { 2,0,6,3,9,0,0,2,0,3 }, { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bodoni 72", { 0,0,4,0,0,0,0,0,0,0 }, { 0xffff1000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bodoni 72 Oldstyle", { 0,0,4,0,0,0,0,0,0,0 }, { 0xfe130000,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bodoni 72 Smallcaps", { 0,0,4,0,0,0,0,0,0,0 }, { 0xfe130000,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bodoni Ornaments", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf0030000,0x02000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Bradley Hand", { 0,0,7,0,0,0,0,0,0,0 }, { 0xfffff800,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Brush Script MT", { 3,6,8,2,4,4,6,7,3,4 }, { 0xfffff000,0x07000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Chalkboard", { 3,5,6,2,4,2,2,2,2,5 }, { 0xff9f1000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Chalkboard SE", { 3,5,6,2,4,2,2,2,2,5 }, { 0xfffff000,0x27200000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Chalkduster", { 3,5,6,2,4,2,2,2,2,5 }, { 0xffbf1000,0x27200000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Charter", { 2,4,5,3,5,5,6,2,2,3 }, { 0xfffff800,0x07400000,0x0100003c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Comic Sans MS", { 3,15,7,2,3,3,2,2,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Copperplate", { 2,0,5,4,0,0,0,2,0,4 }, { 0xffbff800,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Corsiva Hebrew", { 0,0,0,0,0,0,0,0,0,0 }, { 0xe0040300,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Courier New", { 2,7,3,9,2,2,5,2,4,4 }, { 0xfffffbf4,0x07400000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Damascus", { 0,0,4,0,0,0,0,0,0,0 }, { 0xa00000f4,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "DecoType Naskh", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Devanagari MT", { 2,0,5,0,2,0,0,0,0,0 }, { 0xd0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Devanagari Sangam MN", { 2,0,0,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Didot", { 2,0,5,3,0,0,0,2,0,3 }, { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Diwan Kufi", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Diwan Thuluth", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000c0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Farah", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Farisi", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000c0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Futura", { 2,11,6,2,2,2,4,2,3,3 }, { 0xfebb0000,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Galvji", { 2,11,5,4,2,2,2,2,2,4 }, { 0xfe1f0000,0x27000000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Geeza Pro", { 2,0,4,0,0,0,0,0,0,0 }, { 0xa00000f4,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Georgia", { 2,4,5,2,5,4,5,2,3,3 }, { 0xfffff000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gill Sans", { 2,11,5,2,2,1,4,2,2,3 }, { 0xfe18f000,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Grantha Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xfe9f0000,0x87000000,0x00000008,0x24000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gujarati MT", { 0,0,5,0,7,0,0,0,0,0 }, { 0xf0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gujarati Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gurmukhi MN", { 2,2,6,0,5,4,5,2,3,4 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gurmukhi MT", { 0,0,0,0,0,0,0,0,0,0 }, { 0xd0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Gurmukhi Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Helvetica", { 0,0,0,0,0,0,0,0,0,0 }, { 0xfffff800,0x67400000,0x0100001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Hiragino Maru Gothic ProN", { 2,15,4,0,0,0,0,0,0,0 }, { 0xff7fc000,0x07ffffff,0xfc00000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Hiragino Mincho ProN", { 2,2,3,0,0,0,0,0,0,0 }, { 0xffffc000,0x47ffffff,0xfd80000c,0x00000000,0x00000023,0xffffffff,0xff981308,0x00000000 } }, +{ "Hiragino Sans", { 2,11,3,0,0,0,0,0,0,0 }, { 0xffffc000,0x47ffffff,0xfd80000c,0x00000000,0x00000023,0xffffffff,0xff981308,0x00000000 } }, +{ "Hiragino Sans GB", { 2,11,3,0,0,0,0,0,0,0 }, { 0xfd53c000,0x077fffff,0xfc00018c,0x00000000,0x00000003,0x90820000,0x00000000,0x00000000 } }, +{ "Hoefler Text", { 2,3,6,2,5,5,6,2,2,3 }, { 0xffdbf000,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "ITF Devanagari", { 2,0,0,0,0,0,0,0,0,0 }, { 0xf0200000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "ITF Devanagari Marathi", { 2,0,0,0,0,0,0,0,0,0 }, { 0xf0200000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Impact", { 2,11,8,6,3,9,2,5,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "InaiMathi", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0340000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kailasa", { 2,0,5,0,0,0,0,2,0,4 }, { 0xa0000000,0x40000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kannada MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kannada Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kefa", { 2,0,5,6,0,0,0,2,0,4 }, { 0xfe130000,0x23400000,0x0080000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Khmer MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x1b000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Khmer Sangam MN", { 2,0,4,0,0,0,0,0,0,0 }, { 0xe0000000,0x1b000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kohinoor Bangla", { 2,0,0,0,0,0,0,0,0,0 }, { 0xfeb10000,0x87000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kohinoor Devanagari", { 2,0,0,0,0,0,0,0,0,0 }, { 0xfeb10000,0x87000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kohinoor Gujarati", { 0,0,8,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kohinoor Telugu", { 2,0,0,0,0,0,0,0,0,0 }, { 0xfe910000,0xc7000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Kokonor", { 1,0,5,0,0,0,0,2,0,3 }, { 0x80000000,0x43000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Krungthep", { 2,0,4,0,0,0,0,0,0,0 }, { 0xffdf1000,0x47000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "KufiStandardGK", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lao MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lao Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Lucida Grande", { 2,11,6,0,4,5,2,2,2,4 }, { 0xfffffb00,0x07800000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Luminari", { 2,0,5,5,0,0,0,2,0,4 }, { 0xffbff000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Malayalam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Malayalam Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Marker Felt", { 2,0,4,0,0,0,0,0,0,0 }, { 0xfffbf000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Menlo", { 2,11,6,9,3,8,4,2,2,4 }, { 0xfffff800,0x27c00000,0x0100001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Microsoft Sans Serif", { 2,11,6,4,2,2,2,2,2,4 }, { 0xfffffbf4,0x47400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mishafi", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000c0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mishafi Gold", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x00000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mshtakan", { 2,0,4,0,0,0,0,0,0,0 }, { 0xf2000e00,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Mukta Mahee", { 2,11,0,0,0,0,0,0,0,0 }, { 0xff910000,0x87000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Muna", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Myanmar MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x23000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Myanmar Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x23000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Nadeem", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "New Peninim MT", { 0,0,0,0,0,0,0,0,0,0 }, { 0xe0040300,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noteworthy", { 2,0,4,0,0,0,0,0,0,0 }, { 0xfffff000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Nastaliq Urdu", { 2,11,5,2,4,5,4,2,2,4 }, { 0xf00000f4,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Kannada", { 2,11,10,2,4,5,4,2,2,4 }, { 0xf0000000,0xc7000000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Myanmar", { 2,11,10,2,4,5,4,2,2,4 }, { 0xa0000000,0x23000000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Sans Oriya", { 2,11,5,2,4,5,4,2,2,4 }, { 0xf0000000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Noto Serif Myanmar", { 2,2,10,2,6,5,5,2,2,4 }, { 0xa0000000,0x23000000,0x00800004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Optima", { 2,0,5,3,6,0,0,2,0,4 }, { 0xfe180000,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Oriya MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Oriya Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PT Mono", { 2,6,7,9,2,2,5,2,2,4 }, { 0xffbbf800,0x07400000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PT Sans", { 2,11,5,3,2,2,3,2,2,4 }, { 0xffbbf800,0x07400000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PT Sans Caption", { 2,11,5,3,2,2,3,2,2,4 }, { 0xffbbf800,0x07400000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PT Sans Narrow", { 2,11,5,3,2,2,3,2,2,4 }, { 0xffbbf800,0x07400000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PT Serif", { 2,10,6,3,4,5,5,2,2,4 }, { 0xffbbf800,0x07400000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PT Serif Caption", { 2,6,6,3,5,5,5,2,2,4 }, { 0xffbbf800,0x07400000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Palatino", { 0,0,0,0,0,0,0,0,0,0 }, { 0xfffff000,0x27200000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Papyrus", { 2,11,6,2,4,2,0,2,3,3 }, { 0xffff1000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Party LET", { 0,0,0,0,0,0,0,0,0,0 }, { 0xffbe1000,0x06000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Phosphate", { 2,0,5,6,5,0,0,2,0,4 }, { 0xfffff000,0x07000000,0x0000002c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "PingFang HK", { 2,11,4,0,0,0,0,0,0,0 }, { 0xffffc000,0x07ffffff,0xfc00000c,0x00000000,0x00000023,0xffffffff,0xff400008,0x00000000 } }, +{ "PingFang SC", { 2,11,4,0,0,0,0,0,0,0 }, { 0xffffc000,0x07ffffff,0xfc00000c,0x00000000,0x00000023,0xffffffff,0xff400008,0x00000000 } }, +{ "PingFang TC", { 2,11,4,0,0,0,0,0,0,0 }, { 0xffffc000,0x07ffffff,0xfc00000c,0x00000000,0x00000023,0xffffffff,0xff400008,0x00000000 } }, +{ "Plantagenet Cherokee", { 2,2,0,0,0,0,0,0,0,0 }, { 0xf61c0000,0x22000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Raanana", { 0,0,0,0,0,0,0,0,0,0 }, { 0xe0040300,0x02000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Rockwell", { 2,6,5,3,2,2,5,2,4,3 }, { 0xffffea80,0xd6000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "STSong", { 2,1,8,0,4,1,1,1,1,1 }, { 0xfd53c000,0x07207fff,0xfc000184,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sana", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000f0,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sathu", { 0,0,4,0,0,0,0,0,0,0 }, { 0xfffff000,0x47000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Savoye LET", { 0,0,0,0,0,0,0,0,0,0 }, { 0xfffff800,0x06800000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Shree Devanagari 714", { 2,0,6,0,0,0,0,0,0,0 }, { 0xf6100000,0x83000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "SignPainter", { 2,0,0,6,7,0,0,2,0,4 }, { 0xff9bf800,0x07000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Silom", { 0,0,4,0,0,0,0,0,0,0 }, { 0xffdf1000,0x47000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sinhala MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sinhala Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Skia", { 2,13,5,2,2,2,4,2,2,4 }, { 0xff9b0000,0x03000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Snell Roundhand", { 2,0,6,3,8,0,0,9,0,4 }, { 0xfffff800,0x26e00000,0x0100001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Songti SC", { 2,1,8,0,4,1,1,1,1,1 }, { 0xfd53c000,0x07207fff,0xfc000184,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Songti TC", { 2,1,8,0,4,1,1,1,1,1 }, { 0xfd53c000,0x07207fff,0xfc000184,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Sukhumvit Set", { 2,0,5,6,0,0,0,2,0,4 }, { 0xfe130000,0x43000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Symbol", { 0,0,0,0,0,0,0,0,0,0 }, { 0xf22b0000,0x03200000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tahoma", { 2,11,6,4,3,5,4,4,2,4 }, { 0xfffffbf4,0x47400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tamil MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x83000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Tamil Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xfe9f0000,0x87000000,0x00000008,0x24000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Telugu MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Telugu Sangam MN", { 0,0,5,0,0,0,0,0,0,0 }, { 0xe0000000,0x43000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Thonburi", { 0,0,4,0,0,0,0,0,0,0 }, { 0xfffff000,0x47000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Times", { 0,0,5,0,0,0,0,2,0,0 }, { 0xfffff000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Times New Roman", { 2,2,6,3,5,4,5,2,3,4 }, { 0xfffffbf4,0x07400000,0x0100000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Trattatello", { 2,15,4,3,2,2,0,2,3,3 }, { 0xffbff000,0x07000000,0x0000001c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Trebuchet MS", { 2,11,6,3,2,2,2,2,2,4 }, { 0xff97e000,0x07000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Verdana", { 2,11,6,4,3,5,4,4,2,4 }, { 0xffdff600,0x47000000,0x0000000c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +{ "Waseem", { 0,0,4,0,0,0,0,0,0,0 }, { 0xf00000c0,0x00000000,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 } }, +#endif diff --git a/uppsrc/Draw/Image.cpp b/uppsrc/Draw/Image.cpp index 9730a1a1d..1698c9e8d 100644 --- a/uppsrc/Draw/Image.cpp +++ b/uppsrc/Draw/Image.cpp @@ -281,7 +281,7 @@ bool Image::operator==(const Image& img) const Get2ndSpot() == img.Get2ndSpot() && GetDots() == img.GetDots() && GetResolution() == img.GetResolution() && - memeq32(~*this, ~img, GetLength()); + memeq_t(~*this, ~img, GetLength()); } bool Image::operator!=(const Image& img) const diff --git a/uppsrc/Draw/src.tpp/Font_en-us.tpp b/uppsrc/Draw/src.tpp/Font_en-us.tpp index 0d720fabe..544a9d1b7 100644 --- a/uppsrc/Draw/src.tpp/Font_en-us.tpp +++ b/uppsrc/Draw/src.tpp/Font_en-us.tpp @@ -347,7 +347,7 @@ there is a space inside the cell not used for glyph.&] [s5;:Font`:`:GetRightSpace`(int`)const: [@(0.0.255) int]_[* GetRightSpace]([@(0.0.255) int]_ [@3 c])_[@(0.0.255) const]&] [s2;%% Similar to GetLeftSpace for the right edge of character cell.&] -[s3; &] +[s3;%% &] [s4; &] [s5;:Font`:`:IsFixedPitch`(`)const: [@(0.0.255) bool]_[* IsFixedPitch]()_[@(0.0.255) const]&] [s2;%% True if font is mono`-spaced.&] @@ -393,6 +393,16 @@ onst]_[@(0.0.255) char]_`*[*@3 s])&] [s5;:Font`:`:GetData`(`)const: [_^String^ String]_[* GetData]()_[@(0.0.255) const]&] [s2;%% Returns the raw content of font file.&] [s3; &] +[s3; &] +[s4; &] +[s5;:Upp`:`:Font`:`:GetData`(const char`*`,int`,int`)const: [_^Upp`:`:String^ String]_[* G +etData]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 table]_`=_NULL, +[@(0.0.255) int]_[*@3 offset]_`=_`-[@3 1], [@(0.0.255) int]_[*@3 size]_`=_`-[@3 1])_[@(0.0.255) c +onst]&] +[s2;%% Returns the raw content of font file. [%-*@3 table] [%-*@3 offset] +[%-*@3 size] can specify which part of TTF or OTF font data to +retrieve.&] +[s0;%% &] [s4; &] [s5;:Font`:`:Render`(FontGlyphConsumer`&`,double`,double`,int`)const: [@(0.0.255) void]_ [* Render]([_^FontGlyphConsumer^ FontGlyphConsumer][@(0.0.255) `&]_[*@3 sw], diff --git a/uppsrc/Esc/Esc.cpp b/uppsrc/Esc/Esc.cpp index 829d5c7aa..a47cad40e 100644 --- a/uppsrc/Esc/Esc.cpp +++ b/uppsrc/Esc/Esc.cpp @@ -320,11 +320,11 @@ void Esc::Term(SRVal& r) return; } if(IsString()) { - r = EscValue(FromUtf8(ReadString())); + r = EscValue(ToUtf32(ReadString())); return; } if(IsChar('\'')) { - WString s = FromUtf8(ReadString('\'')); + WString s = ToUtf32(ReadString('\'')); if(s.GetLength() != 1) ThrowError("invalid character literal"); r = (int64)s[0]; diff --git a/uppsrc/GLCtrl/GLCtrl.cpp b/uppsrc/GLCtrl/GLCtrl.cpp index 955a63de2..44961cde5 100644 --- a/uppsrc/GLCtrl/GLCtrl.cpp +++ b/uppsrc/GLCtrl/GLCtrl.cpp @@ -12,6 +12,8 @@ extern void (*restore_gl_viewport__)(); void GLCtrl::DoGLPaint() { + MemoryIgnoreLeaksBlock __; + glClearDepth(1); glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); @@ -47,6 +49,8 @@ void GLCtrl::SetCurrentViewport() void GLCtrl::StdView() { + MemoryIgnoreLeaksBlock __; + glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); diff --git a/uppsrc/HexView/HexView.cpp b/uppsrc/HexView/HexView.cpp index f29cf3283..de84abeb7 100644 --- a/uppsrc/HexView/HexView.cpp +++ b/uppsrc/HexView/HexView.cpp @@ -85,7 +85,7 @@ void HexViewInfo::Paint(Draw& w) break; sh[i] = data[i]; } - WString ws = FromUtf8(sh, i); + WString ws = ToUtf32(sh, i); w.DrawText(x, 0, ws, font, Cyan, i); if(mode < 2) return; diff --git a/uppsrc/ODBC/ODBC.cpp b/uppsrc/ODBC/ODBC.cpp index 42ea1bfd4..0e20c1dcd 100644 --- a/uppsrc/ODBC/ODBC.cpp +++ b/uppsrc/ODBC/ODBC.cpp @@ -620,11 +620,10 @@ bool ODBCConnection::Fetch0() break; if(li != SQL_NULL_DATA && li >= 0) { if(ct == SQL_C_WCHAR) { - WStringBuffer sb; - sb.SetLength(li / 2); + Buffer sb(li / 2); if(!IsOk(SQLGetData(session->hstmt, i + 1, ct, ~sb, li + 2, &li))) break; - v = WString(sb); + v = ToUtf32(sb, li / 2); } else { StringBuffer sb; diff --git a/uppsrc/Painter/DrawOp.cpp b/uppsrc/Painter/DrawOp.cpp index 76d504bbc..1095999e5 100644 --- a/uppsrc/Painter/DrawOp.cpp +++ b/uppsrc/Painter/DrawOp.cpp @@ -215,7 +215,7 @@ void Painter::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, if(angle) Rotate(-angle * M_2PI / 3600); if(n < 0) - n = wstrlen(text); + n = strlen__(text); double *ddx = NULL; Buffer h; if(dx) { diff --git a/uppsrc/Painter/Painter.cpp b/uppsrc/Painter/Painter.cpp index 47fbb465b..fa0a09bb2 100644 --- a/uppsrc/Painter/Painter.cpp +++ b/uppsrc/Painter/Painter.cpp @@ -242,7 +242,7 @@ void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, const double *dx) { - return Text(Pointf(x, y), text, fnt, n < 0 ? wstrlen(text) : n, dx); + return Text(Pointf(x, y), text, fnt, n < 0 ? strlen__(text) : n, dx); } Painter& Painter::Text(const Pointf& p, const WString& s, Font fnt, const double *dx) @@ -267,7 +267,7 @@ Painter& Painter::Text(double x, double y, const String& s, Font fnt, const doub Painter& Painter::Text(const Pointf& p, const char *text, Font fnt, int n, const double *dx) { - WString s = ToUnicode(text, CHARSET_DEFAULT); + WString s = ToUtf32(text, n); return Text(p, s, fnt, n < 0 ? s.GetCount() : n, dx); } diff --git a/uppsrc/RichEdit/Kbd.cpp b/uppsrc/RichEdit/Kbd.cpp index 5022551fc..84d7436c4 100644 --- a/uppsrc/RichEdit/Kbd.cpp +++ b/uppsrc/RichEdit/Kbd.cpp @@ -184,7 +184,7 @@ bool RichEdit::Key(dword key, int count) } if(key == K_SHIFT_SPACE) key = ' '; - if(key == 9 || key >= 32 && key < 65536) { + if(key == 9 || key >= 32 && key < K_CHAR_LIM) { RichPara::Format f; if(IsSelection()) { f = text.GetRichPos(min(cursor, anchor)).format; diff --git a/uppsrc/RichText/ParaData.cpp b/uppsrc/RichText/ParaData.cpp index 220473e7c..cd82235c5 100644 --- a/uppsrc/RichText/ParaData.cpp +++ b/uppsrc/RichText/ParaData.cpp @@ -562,7 +562,7 @@ void RichPara::UnpackParts(Stream& in, const RichPara::CharFormat& chrstyle, b.Reserve(512); while(in.Term() >= 32 || in.Term() == 9) b.Cat(in.Get()); - part.Top().text.Cat(FromUtf8(~b)); + part.Top().text.Cat(ToUtf32(~b)); } if(part.Top().text.GetLength() == 0 && part.Top().IsText()) part.Drop(); @@ -736,7 +736,7 @@ void RichPara::Mid(int pos) } void ApplyCharStyle(RichPara::CharFormat& format, const RichPara::CharFormat& f0, - const RichPara::CharFormat& newstyle) { + const RichPara::CharFormat& newstyle) { if(format.IsBold() == f0.IsBold()) format.Bold(newstyle.IsBold()); if(format.IsUnderline() == f0.IsUnderline()) diff --git a/uppsrc/RichText/ParseQtf.cpp b/uppsrc/RichText/ParseQtf.cpp index 866144131..d2d45d46d 100644 --- a/uppsrc/RichText/ParseQtf.cpp +++ b/uppsrc/RichText/ParseQtf.cpp @@ -628,7 +628,7 @@ void RichQtfParser::Parse(const char *qtf, int _accesskey) case '`': format.sscript = format.sscript == 1 ? 0 : 1; break; case ',': format.sscript = format.sscript == 2 ? 0 : 2; break; case '^': format.link = GetText('^'); break; - case 'I': format.indexentry = FromUtf8(GetText(';')); break; + case 'I': format.indexentry = ToUtf32(GetText(';')); break; case '+': format.Height(GetNumber()); break; case '@': format.ink = GetColor(); break; case '$': format.paper = GetColor(); break; @@ -1011,25 +1011,10 @@ void RichQtfParser::Parse(const char *qtf, int _accesskey) if(istable) EndPart(); if(format.charset == CHARSET_UTF8) { - word code = (byte)*term++; - if(code <= 0x7F) - Cat(code); - else - if(code <= 0xDF) { - if(*term == '\0') break; - int c0 = (byte)*term++; - if(c0 < 0x80) - Error("Invalid UTF-8 sequence"); - Cat(((code - 0xC0) << 6) + c0 - 0x80); - } - else - if(code <= 0xEF) { - int c0 = (byte)*term++; - int c1 = (byte)*term++; - if(c0 < 0x80 || c1 < 0x80) - Error("Invalid UTF-8 sequence"); - Cat(((code - 0xE0) << 12) + ((c0 - 0x80) << 6) + c1 - 0x80); - } + bool ok = true; + wchar c = FetchUtf8(term, ok); + if(ok) + Cat(c); else Error("Invalid UTF-8 sequence"); } diff --git a/uppsrc/ide/About.cpp b/uppsrc/ide/About.cpp index a7fea4a1f..80d54d5a0 100644 --- a/uppsrc/ide/About.cpp +++ b/uppsrc/ide/About.cpp @@ -21,6 +21,8 @@ String SplashCtrl::GenerateVersionInfo(char separator) h << "(64 bit)"; else h << "(32 bit)"; + if(sizeof(wchar) == 4) + h << " (wchar32)"; #ifdef _MSC_VER h << " (MSC)"; #endif @@ -114,7 +116,9 @@ void HideSplash() void ShowSplash() { Single().PopUp(nullptr, false, false); - SetTimeCallback(750, [] { HideSplash(); }); + SetTimeCallback(750, [] { + HideSplash(); + }); } bool IsSplashOpen() diff --git a/uppsrc/ide/Browser/Base.cpp b/uppsrc/ide/Browser/Base.cpp index 47386d6fe..5d8812d67 100644 --- a/uppsrc/ide/Browser/Base.cpp +++ b/uppsrc/ide/Browser/Base.cpp @@ -38,6 +38,15 @@ void LockCodeBase() sGLock.Enter(); } +bool TryLockCodeBase() +{ + if(sGLockLevel == 0 && sGLock.TryEnter()) { + sGLockLevel++; + return true; + } + return false; +} + void UnlockCodeBase() { if(sGLockLevel > 0 && --sGLockLevel == 0) @@ -454,6 +463,16 @@ void CodeBaseScanFile(Stream& in, const String& fn) FinishCodeBase(); } +bool TryCodeBaseScanFile(Stream& in, const String& fn) +{ + if(DeadLockCheck() || !CppBaseMutex.TryEnter()) + return false; + CodeBaseScanFile0(in, fn); + FinishCodeBase(); + CppBaseMutex.Leave(); + return true; +} + void CodeBaseScanFile(const String& fn, bool auto_check) { LLOG("CodeBaseScanFile " << fn); diff --git a/uppsrc/ide/Browser/Browser.h b/uppsrc/ide/Browser/Browser.h index 4e12f3434..d520892a8 100644 --- a/uppsrc/ide/Browser/Browser.h +++ b/uppsrc/ide/Browser/Browser.h @@ -21,6 +21,7 @@ class Browser; void ReduceCacheFolder(const char *path, int max_total); void LockCodeBase(); +bool TryLockCodeBase(); void UnlockCodeBase(); void UnlockCodeBaseAll(); @@ -47,6 +48,7 @@ void NewCodeBase(); void ParseSrc(Stream& in, int file, Event error); void CodeBaseScanFile(Stream& in, const String& fn); void CodeBaseScanFile(const String& fn, bool auto_check); +bool TryCodeBaseScanFile(Stream& in, const String& fn); void ClearCodeBase(); // void CheckCodeBase(); void RescanCodeBase(); diff --git a/uppsrc/ide/Builders/Build.cpp b/uppsrc/ide/Builders/Build.cpp index 78323e935..c53786d07 100644 --- a/uppsrc/ide/Builders/Build.cpp +++ b/uppsrc/ide/Builders/Build.cpp @@ -521,10 +521,16 @@ bool MakeBuild::Build(const Workspace& wspc, String mainparam, String outfile, b return ok; } +void MakeBuild::BuildWorkspace(Workspace& wspc, Host& host, Builder& builder) +{ + Index p = PackageConfig(GetIdeWorkspace(), 0, GetMethodVars(method), mainconfigparam, + host, builder); + wspc.Scan(GetMain(), p.GetKeys()); +} + bool MakeBuild::Build() { - VectorMap bm = GetMethodVars(method); - if(bm.GetCount() == 0) { + if(GetMethodVars(method).GetCount() == 0) { PutConsole(GetInvalidBuildMethodError(method)); ConsoleShow(); return false; @@ -534,10 +540,8 @@ bool MakeBuild::Build() One builder = CreateBuilder(&host); if(!builder) return false; - Index p = PackageConfig(GetIdeWorkspace(), 0, bm, mainconfigparam, - host, *builder); Workspace wspc; - wspc.Scan(GetMain(), p.GetKeys()); + BuildWorkspace(wspc, host, *builder); return Build(wspc, mainconfigparam, Null); } @@ -568,7 +572,8 @@ void MakeBuild::Clean() return; builder->target = target; - const Workspace& wspc = GetIdeWorkspace(); + Workspace wspc; + BuildWorkspace(wspc, host, *builder); for(int i = 0; i < wspc.GetCount(); i++) CleanPackage(wspc, i); diff --git a/uppsrc/ide/Builders/Build.h b/uppsrc/ide/Builders/Build.h index 8b5be2663..4d257dbd2 100644 --- a/uppsrc/ide/Builders/Build.h +++ b/uppsrc/ide/Builders/Build.h @@ -85,6 +85,7 @@ public: Vector GetAllLibraries(const Workspace& wspc, int index, const VectorMap& bm, String mainparam, Host& host, Builder& builder); + void BuildWorkspace(Workspace& wspc, Host& host, Builder& builder); bool Build(const Workspace& wspc, String mainparam, String outfile, bool clear_console = true); bool Build(); void CleanPackage(const Workspace& wspc, int package); diff --git a/uppsrc/ide/Calc.cpp b/uppsrc/ide/Calc.cpp index 2029dd0cb..38e6c54d1 100644 --- a/uppsrc/ide/Calc.cpp +++ b/uppsrc/ide/Calc.cpp @@ -50,7 +50,7 @@ void IdeCalc::Execute() Paste("$"); SetCursor(GetLength64()); Paste("\n"); - Paste(FromUtf8(txt)); + Paste(ToUtf32(txt)); Paste("\n"); } diff --git a/uppsrc/ide/Core/Util.cpp b/uppsrc/ide/Core/Util.cpp index e6ea0d3ff..748760f22 100644 --- a/uppsrc/ide/Core/Util.cpp +++ b/uppsrc/ide/Core/Util.cpp @@ -7,7 +7,8 @@ int GetRepo(String& path) if(DirectoryExists(AppendFileName(path, ".svn")) || DirectoryExists(AppendFileName(path, "_svn"))) return SVN_DIR; for(;;) { - if(DirectoryExists(AppendFileName(path, ".git"))) + String git = AppendFileName(path, ".git"); + if(DirectoryExists(git) || FileExists(git)) return GIT_DIR; if(DirectoryExists(AppendFileName(path, ".svn"))) return SVN_DIR; diff --git a/uppsrc/ide/Debug.cpp b/uppsrc/ide/Debug.cpp index fd25c8e3d..43d1e8cb0 100644 --- a/uppsrc/ide/Debug.cpp +++ b/uppsrc/ide/Debug.cpp @@ -144,7 +144,7 @@ void Ide::ExecuteBinary() Minimize(); if(!runexternal) cmdline << '\"' << target << "\" "; - cmdline << ToSystemCharset(runarg); + cmdline << runarg; int exitcode; switch(runmode) { diff --git a/uppsrc/ide/Debuggers/Sym.cpp b/uppsrc/ide/Debuggers/Sym.cpp index 80cc1e96d..dc3db9e53 100644 --- a/uppsrc/ide/Debuggers/Sym.cpp +++ b/uppsrc/ide/Debuggers/Sym.cpp @@ -321,7 +321,7 @@ String Pdb::GetSymName(adr_t modbase, dword typeindex) { WCHAR *pwszTypeName; if(SymGetTypeInfo(hProcess, modbase, typeindex, TI_GET_SYMNAME, &pwszTypeName)) { - WString w((const wchar *)pwszTypeName); + WString w = pwszTypeName; LocalFree(pwszTypeName); return w.ToString(); } @@ -416,6 +416,13 @@ const Pdb::Type& Pdb::GetType(int ti) return t; } +static int CALLBACK sSymEnum(PSYMBOL_INFO pSym, ULONG SymbolSize, PVOID UserContext) +{ + auto type_index = (VectorMap *)UserContext; + type_index->GetAdd(pSym->Name) = pSym->TypeIndex; + return TRUE; +} + int Pdb::FindType(adr_t modbase, const String& name) { static VectorMap primitive = { @@ -443,11 +450,7 @@ int Pdb::FindType(adr_t modbase, const String& name) return q; if(type_bases.Find(modbase) < 0) { type_bases.Add(modbase); - SymEnumTypes(hProcess, current_modbase, [](PSYMBOL_INFO pSym, ULONG SymbolSize, PVOID UserContext)->int { - auto type_index = (VectorMap *)UserContext; - type_index->GetAdd(pSym->Name) = pSym->TypeIndex; - return TRUE; - }, &type_index); + SymEnumTypes(hProcess, current_modbase, sSymEnum, &type_index); // DDUMPM(type_index); } int ndx = type_index.Get(name, Null); diff --git a/uppsrc/ide/Errors.cpp b/uppsrc/ide/Errors.cpp index ce5dc364e..a687dfb54 100644 --- a/uppsrc/ide/Errors.cpp +++ b/uppsrc/ide/Errors.cpp @@ -715,8 +715,8 @@ void Ide::FoundDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, int fcy = GetStdFontCy(); int y = r.top + (r.GetHeight() - fcy) / 2; w.DrawRect(r, paper); - int sl = utf8len(~h[3], atoi(h[1])); - int sh = utf8len(~h[3] + sl, atoi(h[2])) + sl; + int sl = Utf32Len(~h[3], atoi(h[1])); + int sh = Utf32Len(~h[3] + sl, atoi(h[2])) + sl; for(int text = 0; text < 2; text++) { int x = r.left; for(int i = 0; i < hln.GetCount(); i++) { diff --git a/uppsrc/ide/FindInFiles.cpp b/uppsrc/ide/FindInFiles.cpp index 2946dbb1b..5b53511bb 100644 --- a/uppsrc/ide/FindInFiles.cpp +++ b/uppsrc/ide/FindInFiles.cpp @@ -322,7 +322,7 @@ void Ide::FindFileAll(const Vector>& f) editor.CachePos(pos.a); int linei = editor.GetLinePos64(pos.a); WString ln = editor.GetWLine(linei); - AddFoundFile(editfile, linei + 1, ln.ToString(), lenAsUtf8(~ln, (int)pos.a), lenAsUtf8(~ln + pos.a, pos.b)); + AddFoundFile(editfile, linei + 1, ln.ToString(), Utf8Len(~ln, (int)pos.a), Utf8Len(~ln + pos.a, pos.b)); } FFound().HeaderTab(2).SetText(Format("Source line (%d)", FFound().GetCount())); FFound().Add(Null, Null, AsString(f.GetCount()) + " occurrence(s) have been found."); diff --git a/uppsrc/ide/Help.cpp b/uppsrc/ide/Help.cpp index 840ba6b33..9805eacaf 100644 --- a/uppsrc/ide/Help.cpp +++ b/uppsrc/ide/Help.cpp @@ -147,7 +147,7 @@ void TopicCtrl::SyncDocTree() Vector sdx; for(int i = 0; i < ss.GetCount(); i++) - sdx.Add(ToUtf8(ToLower(FromUtf8(ss[i])))); + sdx.Add(ToUtf8(ToLower(ToUtf32(ss[i])))); ClearTree(); diff --git a/uppsrc/ide/LayDes/laydes.cpp b/uppsrc/ide/LayDes/laydes.cpp index 9f3338d25..775dfd51c 100644 --- a/uppsrc/ide/LayDes/laydes.cpp +++ b/uppsrc/ide/LayDes/laydes.cpp @@ -286,6 +286,7 @@ void LayDes::Paint(Draw& w) if(HasCapture() && draghandle == 14) DrawFrame(w, dragrect.Normalized(), LtRed); w.End(); + w.End(); } void LayDes::SaveState() diff --git a/uppsrc/ide/LayDes/textprop.cpp b/uppsrc/ide/LayDes/textprop.cpp index 2161d19c8..1b2ca64c3 100644 --- a/uppsrc/ide/LayDes/textprop.cpp +++ b/uppsrc/ide/LayDes/textprop.cpp @@ -123,7 +123,7 @@ void LTProperty::Read(CParser& p) String LTProperty::Save() const { String px = ~lid; - String txt = FromUnicode((WString)Get(), charset); + String txt = FromUnicode(Get(), charset); if(id) return "t_(" + AsCString(px + "\a" + txt) + ')'; else diff --git a/uppsrc/ide/Navigator.cpp b/uppsrc/ide/Navigator.cpp index 74dc3cd2f..fe335aa10 100644 --- a/uppsrc/ide/Navigator.cpp +++ b/uppsrc/ide/Navigator.cpp @@ -730,8 +730,10 @@ void Navigator::Scope() litem.Add(m); } } + int lsc = list.GetScroll(); list.Clear(); list.SetVirtualCount(litem.GetCount()); + list.ScrollTo(lsc); } void Navigator::ListLineEnabled(int i, bool& b) diff --git a/uppsrc/ide/ide.cpp b/uppsrc/ide/ide.cpp index b6e7d3344..57e94d22d 100644 --- a/uppsrc/ide/ide.cpp +++ b/uppsrc/ide/ide.cpp @@ -646,8 +646,8 @@ void Ide::Periodic() if(debugger && debugger->IsFinished() && !IdeIsDebugLock()) IdeEndDebug(); if(file_scanned) { - EditFileAssistSync2(); - file_scanned = false; + if(EditFileAssistSync2()) + file_scanned = false; } } diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index c4b0815ec..5183d4b47 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -765,10 +765,10 @@ public: void PosSync(); String IncludesMD5(); - void EditFileAssistSync2(); + bool EditFileAssistSync2(); void EditFileAssistSync(); - TimeCallback text_updated; + TimeCallback text_updated, trigger_assist; std::atomic file_scan; bool file_scanned = false; diff --git a/uppsrc/ide/idefile.cpp b/uppsrc/ide/idefile.cpp index 9cad3b98f..13a5d51bc 100644 --- a/uppsrc/ide/idefile.cpp +++ b/uppsrc/ide/idefile.cpp @@ -661,10 +661,15 @@ void Ide::ScanFile(bool check_includes) } } -void Ide::EditFileAssistSync2() +bool Ide::EditFileAssistSync2() { - editor.Annotate(editfile); - editor.SyncNavigator(); + if(TryLockCodeBase()) { + editor.Annotate(editfile); + editor.SyncNavigator(); + UnlockCodeBase(); + return true; + } + return false; } void Ide::EditFileAssistSync() @@ -683,11 +688,14 @@ void Ide::TriggerAssistSync() file_scan++; if(!CoWork::TrySchedule([=] { StringStream ss(s); - CodeBaseScanFile(ss, editfile); + file_scanned = TryCodeBaseScanFile(ss, editfile); file_scan--; - file_scanned = true; - })) + if(!file_scanned) + trigger_assist.KillSet(100, [=] { TriggerAssistSync(); }); + })) { file_scan--; + trigger_assist.KillSet(100, [=] { TriggerAssistSync(); }); + } } }); } diff --git a/upptst/CJK/CJK.upp b/upptst/CJK/CJK.upp new file mode 100644 index 000000000..78e4a082c --- /dev/null +++ b/upptst/CJK/CJK.upp @@ -0,0 +1,12 @@ +uses + CtrlLib, + CtrlLib; + +file + main.cpp; + +mainconfig + "" = "GUI DEBUGCODE", + "" = "GUI", + "" = "GUI X11"; + diff --git a/upptst/CJK/main.cpp b/upptst/CJK/main.cpp new file mode 100644 index 000000000..a555b7499 --- /dev/null +++ b/upptst/CJK/main.cpp @@ -0,0 +1,37 @@ +#include + +using namespace Upp; + +struct MyApp : TopWindow { + void Paint(Draw& w) { + String text; + text << WString(0x1F603, 1).ToString(); + text << " Quick brown fox, 訓民正音 (훈민정음) "; + + w.DrawRect(GetSize(), White()); + int y = 10; + int x = 10; + for(int i = 0; i < Font::GetFaceCount(); i++) + { + Font fnt(i, 30); + if(fnt.IsSpecial()) continue; + fnt.Italic(); + String n = AsString(i) + ": " + fnt.GetFaceName() + ": "; + if(fnt.IsSpecial()) + n << " (special)"; + w.DrawText(x, y, n, StdFont()); + w.DrawText(x + GetTextSize(n, StdFont()).cx, y, text, fnt); + y += fnt.GetLineHeight() + 10; + if(y > GetSize().cy) { + x += GetSize().cx / 3; + if(x > GetSize().cx) + return; + y = 10; + } + } + } +}; + +GUI_APP_MAIN { + MyApp().Sizeable().Zoomable().Run(); +} \ No newline at end of file diff --git a/upptst/FileSel/main.cpp b/upptst/FileSel/main.cpp index 19dc71464..83ab8859a 100644 --- a/upptst/FileSel/main.cpp +++ b/upptst/FileSel/main.cpp @@ -10,30 +10,14 @@ GUI_APP_MAIN sel.Type("All", "*.*"); sel.Type("All 2", "*"); sel.ActiveType(1); - for(int i = 0; i < sel.GetCount(); i++) - DDUMP(sel[i]); - sel.Multi(); - if(!sel.ExecuteSaveAs("Test!")) - return; - for(int i = 0; i < sel.GetCount(); i++) - DDUMP(sel[i]); - sel = "/home/cxl/Temp/Gui2/main.cpp"; + while(sel.ExecuteSaveAs("Test!")) { + for(int i = 0; i < sel.GetCount(); i++) + DDUMP(sel[i]); + sel.Multi(); + sel.NoAsking(); + } + sel = GetDataFile("main.cpp"); if(!sel.ExecuteSaveAs("as")) return; DDUMP(~sel); - sel.NoAsking(); - if(!sel.ExecuteSaveAs("as")) - return; - return; -/* - DocEdit a; - TopWindow w1, w2; - w1.Add(a.SizePos()); - w1.OpenMain(); - Button b; - b <<= callback(Sel); - w2.Add(b.SizePos()); - w2.Open(&w1); - w2.Run(); -*/ }