sizeof(wchar) is changed to 4 (32 bits) to support non BMP unicode characters

This might bring some incompatibilities in the code that expects wchar to be 16 bit, which
  escpecially involves dealing with Win32 (and to lesser extend MacOS) APIs, so if your application
  is doing that, please check all instances of WCHAR (UniChar on MacOS) or even wchar
  especially type casts.

  To support host APIs, char16 is introduced (but there is no 16-bit String varian).

  Use ToSystemCharsetW, FromSystemCharsetW to convert texts to Win32 API.

- Support of drawing non-BMP characters in GUI
- Vastly improved character font replacement code (when drawing characters missing with requested font, replacement font is used)
- Last instances of Win32 ANSI calls (those ending with A) are removed
- UTF handling routines are refactored and their's naming is unified
- RTF is now being able to handle non-BMP characters (RTF is used as clipboard format for RichText)

Other minor changes:

- fixed TryRealloc issue
- improved MemoryCheck
- Removed MemoryAlloc48/MemoryFree48
- In theide Background parsing should less often cause delays in the main thread
This commit is contained in:
Mirek Fidler 2021-12-02 12:03:19 +01:00
parent a6a071a16c
commit 34ff691308
149 changed files with 2373 additions and 1446 deletions

View file

@ -82,7 +82,7 @@ CONSOLE_APP_MAIN
ASSERT(comb == UnicodeDecompose(code)); ASSERT(comb == UnicodeDecompose(code));
Vector<dword> h = UnicodeDecompose(code, true); WString h = UnicodeDecompose(code, true);
if(h.GetCount() > 1) { if(h.GetCount() > 1) {
DUMP(h); DUMP(h);
ASSERT(code == UnicodeCompose(h)); ASSERT(code == UnicodeCompose(h));

View file

@ -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: x:
[0] = x [0] = 0
[1] = xx [1] = 01
[2] = xxx [2] = 012
[3] = xxxx [3] = 0123
[4] = xxxxx [4] = 01234
[5] = xxxxxx [5] = 012345
[6] = xxxxxxx [6] = 0123456
[7] = xxxxxxxx [7] = 01234567
[8] = xxxxxxxxx [8] = 012345678
[9] = xxxxxxxxxx [9] = 0123456789
[10] = xxxxxxxxxxx [10] = 012345678910
[11] = xxxxxxxxxxxx [11] = 01234567891011
[12] = xxxxxxxxxxxxx [12] = 0123456789101112
[13] = xxxxxxxxxxxxxx [13] = 012345678910111213
[14] = xxxxxxxxxxxxxxx [14] = 01234567891011121314
[15] = xxxxxxxxxxxxxxxx [15] = 0123456789101112131415
[16] = xxxxxxxxxxxxxxxxx [16] = 012345678910111213141516
[17] = xxxxxxxxxxxxxxxxxx [17] = 01234567891011121314151617
[18] = xxxxxxxxxxxxxxxxxxx [18] = 0123456789101112131415161718
[19] = xxxxxxxxxxxxxxxxxxxx [19] = 012345678910111213141516171819
[20] = xxxxxxxxxxxxxxxxxxxxx [20] = 01234567891011121314151617181920
[21] = xxxxxxxxxxxxxxxxxxxxxx [21] = 0123456789101112131415161718192021
[22] = xxxxxxxxxxxxxxxxxxxxxxx [22] = 012345678910111213141516171819202122
[23] = xxxxxxxxxxxxxxxxxxxxxxxx [23] = 01234567891011121314151617181920212223
[24] = xxxxxxxxxxxxxxxxxxxxxxxxx [24] = 0123456789101112131415161718192021222324
[25] = xxxxxxxxxxxxxxxxxxxxxxxxxx [25] = 012345678910111213141516171819202122232425
[26] = xxxxxxxxxxxxxxxxxxxxxxxxxxx [26] = 01234567891011121314151617181920212223242526
[27] = xxxxxxxxxxxxxxxxxxxxxxxxxxxx [27] = 0123456789101112131415161718192021222324252627
[28] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx [28] = 012345678910111213141516171819202122232425262728
[29] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [29] = 01234567891011121314151617181920212223242526272829
[30] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [30] = 0123456789101112131415161718192021222324252627282930
[31] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [31] = 012345678910111213141516171819202122232425262728293031
[32] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [32] = 01234567891011121314151617181920212223242526272829303132
[33] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [33] = 0123456789101112131415161718192021222324252627282930313233
[34] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [34] = 012345678910111213141516171819202122232425262728293031323334
[35] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [35] = 01234567891011121314151617181920212223242526272829303132333435
[36] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [36] = 0123456789101112131415161718192021222324252627282930313233343536
[37] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [37] = 012345678910111213141516171819202122232425262728293031323334353637
[38] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [38] = 01234567891011121314151617181920212223242526272829303132333435363738
[39] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [39] = 0123456789101112131415161718192021222324252627282930313233343536373839
[40] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [40] = 012345678910111213141516171819202122232425262728293031323334353637383940
[41] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [41] = 01234567891011121314151617181920212223242526272829303132333435363738394041
[42] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [42] = 0123456789101112131415161718192021222324252627282930313233343536373839404142
[43] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [43] = 012345678910111213141516171819202122232425262728293031323334353637383940414243
[44] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [44] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344
[45] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [45] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445
[46] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [46] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546
[47] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [47] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647
[48] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [48] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
[49] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [49] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
[50] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [50] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
[51] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [51] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
[52] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [52] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
[53] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [53] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
[54] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [54] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
[55] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [55] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
[56] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [56] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
[57] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [57] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
[58] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [58] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
[59] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [59] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
[60] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [60] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
[61] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [61] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
[62] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [62] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
[63] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [63] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
[64] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [64] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
[65] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [65] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
[66] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [66] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
[67] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [67] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
[68] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [68] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
[69] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [69] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
[70] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [70] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
[71] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [71] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
[72] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [72] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
[73] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [73] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
[74] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [74] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
[75] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [75] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
[76] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [76] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
[77] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [77] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
[78] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [78] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
[79] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [79] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
[80] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [80] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
[81] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [81] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
[82] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [82] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
[83] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [83] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
[84] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [84] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
[85] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [85] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
[86] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [86] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
[87] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [87] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
[88] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [88] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
[89] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [89] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
[90] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [90] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
[91] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [91] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
[92] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [92] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
[93] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [93] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
[94] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [94] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
[95] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [95] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
[96] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [96] = 0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
[97] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [97] = 012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
[98] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [98] = 01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
[99] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [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

View file

@ -7,6 +7,6 @@ CONSOLE_APP_MAIN
Vector<WString> x; Vector<WString> x;
LoadFromFile(x, GetDataFile("wstring.bin")); LoadFromFile(x, GetDataFile("wstring.bin"));
DDUMPC(x); DDUMPC(x);
ASSERT(StoreAsString(x) == LoadDataFile("wstring.bin"));
CheckLogEtalon(); CheckLogEtalon();
RLOG("================= OK");
} }

View file

@ -0,0 +1,25 @@
#include <Core/Core.h>
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");
}

View file

@ -0,0 +1,9 @@
uses
Core;
file
std_wstring.cpp;
mainconfig
"" = "";

View file

@ -0,0 +1,17 @@
#include <Core/Core.h>
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);
}
}

View file

@ -0,0 +1,9 @@
uses
Core;
file
GetMemoryBlockSize.cpp;
mainconfig
"" = "DEBUGCODE";

View file

@ -0,0 +1,17 @@
#include <Core/Core.h>
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);
}
}

View file

@ -0,0 +1,9 @@
uses
Core;
file
MemorySize.cpp;
mainconfig
"" = "DEBUGCODE";

View file

@ -0,0 +1,13 @@
#include <Core/Core.h>
using namespace Upp;
Vector<ValueMap> 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);
}

View file

@ -0,0 +1,9 @@
uses
Core;
file
WeirdBug.cpp;
mainconfig
"" = "DEBUGCODE";

View file

@ -34,10 +34,11 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon
double sina, cosa; double sina, cosa;
Draw::SinCos(angle, sina, cosa); Draw::SinCos(angle, sina, cosa);
Size offset; 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 else
::ExtTextOutW(handle, x, y + ascent, 0, NULL, (const WCHAR *)text, ::ExtTextOutW(handle, x, y + ascent, 0, NULL, ToSystemCharsetW(text),
n, dx); n, dx);
::SelectObject(handle, orgfont); ::SelectObject(handle, orgfont);
} }

View file

@ -78,7 +78,7 @@ void TopWindow::SyncTitle0()
#ifndef PLATFORM_WINCE #ifndef PLATFORM_WINCE
if(hwnd) if(hwnd)
if(IsWindowUnicode(hwnd)) if(IsWindowUnicode(hwnd))
::SetWindowTextW(hwnd, (const WCHAR*)~title); ::SetWindowTextW(hwnd, ToSystemCharsetW(title));
else else
#endif #endif
::SetWindowText(hwnd, ToSystemCharset(title.ToString())); ::SetWindowText(hwnd, ToSystemCharset(title.ToString()));

View file

@ -2,7 +2,7 @@ description "GLCtrl widget example\377";
uses uses
GLCtrl, GLCtrl,
CodeEditor; CtrlLib;
file file
main.cpp; main.cpp;

View file

@ -1,21 +1,31 @@
#include "TypeReader.h" #include "TypeReader.h"
#define LLOG(x) // LOG(x) #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) 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) 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) 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) int FontTypeReader::Peek8(const char *s, int i)
@ -54,45 +64,11 @@ int FontTypeReader::Read32(const char *&s)
return q; return q;
} }
const char *FontTypeReader::Seek(const char *tab, int& len) bool FontTypeReader::Open(Font font, bool symbol, bool justcheck)
{
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)
{ {
// DDUMP(fnt.GetCount()); // DDUMP(fnt.GetCount());
try { try {
int i; 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 #if 0
for(i = 0; i < table.GetCount(); i++) for(i = 0; i < table.GetCount(); i++)
LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length); 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); << ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size);
#endif #endif
data = font.GetData("OS/2");
panose.Clear();
if(data.GetCount() > 32 + 10)
panose = data.Mid(32, 10);
bool found = false; bool found = false;
data = font.GetData("cmap");
for(int pass = 0; pass < 2; pass++) { for(int pass = 0; pass < 2; pass++) {
const char *s = Seek("cmap"); const char *p = data;
const char *p = s;
// LOGHEXDUMP(p, 256); // LOGHEXDUMP(p, 256);
p += 2; p += 2;
n = Read16(p); int n = Read16(p);
// DDUMP(n); // DDUMP(n);
while(n--) { while(n--) {
int pid = Read16(p); int pid = Read16(p);
int psid = Read16(p); int psid = Read16(p);
int offset = Read32(p); int offset = Read32(p);
if(offset < 0 || offset > font.GetLength()) if(offset < 0 || offset > data.GetCount())
Error(); Error();
int format = Peek16(s + offset); int format = Peek16(~data + offset);
LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format); LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format);
//Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol... //Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol...
if(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"); LLOG("Reading symbol table");
p = s + offset + 6; p = ~data + offset + 6;
for(int i = 0; i < 256; i++); for(int i = 0; i < 256; i++);
//SetGlyph(i, (byte)p[i]); //SetGlyph(i, (byte)p[i]);
goto done; goto done;
} }
} }
else else
if(pid == 3 && psid == 10 && format == 12 && pass == 0) { if((pid == 3 && psid == 10) || (pid == 0 && psid == 4) && format == 12 && pass == 0) {
const char *p = s + offset; const char *p = ~data + offset;
int ngroups = Peek32(p + 12); int ngroups = Peek32(p + 12);
p += 16; // pointer to groups table p += 16; // pointer to groups table
for(int i = 0; i < ngroups; i++) { for(int i = 0; i < ngroups; i++) {
@ -163,8 +144,8 @@ bool FontTypeReader::Open(const String& fnt, bool symbol, bool justcheck)
goto done; goto done;
} }
else else
if(pid == 3 && psid == 1 && format == 4 && pass == 1) { if((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4 && pass == 1) {
const char *p = s + offset; const char *p = ~data + offset;
int n = Peek16(p + 6) >> 1; int n = Peek16(p + 6) >> 1;
LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n); LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n);
const char *seg_end = p + 14; const char *seg_end = p + 14;
@ -199,35 +180,38 @@ bool FontTypeReader::Open(const String& fnt, bool symbol, bool justcheck)
} }
} }
} }
done: done:;
#if 0
int len; String names = font.GetData("name");
const char *strings = Seek("name", len); if(names.GetCount()) {
s = strings + 2; const char *strings = names;
int count = Read16(s); const char *s = strings + 2;
strings += (word)Read16(s); int count = Read16(s);
for(int i = 0; i < count; i++) { strings += (word)Read16(s);
int platform = Read16(s); for(int i = 0; i < count; i++) {
s += 4; int platform = Read16(s);
if(Read16(s) == 6) { s += 4;
int len = Read16(s); if(Read16(s) == 6) {
int offset = Read16(s); int len = Read16(s);
if(platform == 1) int offset = Read16(s);
ps_name = String(strings + offset, len); if(platform == 1)
else { ps_name = String(strings + offset, len);
s = strings + offset; else {
len >>= 1; s = strings + offset;
while(len--) len >>= 1;
ps_name.Cat(Read16(s)); while(len--)
ps_name.Cat(Read16(s));
}
break;
} }
break; s += 4;
} }
s += 4;
} }
DDUMP(ps_name); DDUMP(ps_name);
#endif
} }
catch(Fail) { catch(Fail) {
DLOG("ERROR"); LLOG("ERROR");
return false; return false;
} }

View file

@ -6,7 +6,7 @@
using namespace Upp; using namespace Upp;
class FontTypeReader { class FontTypeReader {
String font; String data;
struct Table : Moveable<Table> { struct Table : Moveable<Table> {
int offset; int offset;
@ -15,7 +15,7 @@ class FontTypeReader {
VectorMap<String, Table> table; VectorMap<String, Table> table;
struct Fail {}; struct Fail {};
static int Error() { throw Fail(); return 0; } static int Error();
int Peek8(const char *s); int Peek8(const char *s);
int Peek16(const char *s); int Peek16(const char *s);
@ -27,17 +27,14 @@ class FontTypeReader {
int Read16(const char *&s); int Read16(const char *&s);
int Read32(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: public:
String ps_name; String ps_name;
Array<Tuple<int, int>> ranges; Array<Tuple<int, int>> ranges;
bool Open(const String& fnt, bool symbol = false, bool justcheck = false); String panose;
bool Open(Font font, bool symbol = false, bool justcheck = false);
}; };
#endif #endif

View file

@ -8,6 +8,8 @@ using namespace Upp;
#define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p')) #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
#ifdef PLATFORM_WIN32
namespace Upp { namespace Upp {
HFONT GetWin32Font(Font fnt, int angle); HFONT GetWin32Font(Font fnt, int angle);
}; };
@ -34,20 +36,70 @@ String GetFontDataSys(Font font, dword table)
return r; 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 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 #if 0
// Font font(Font::FindFaceNameIndex("Microsoft JhengHei"), 20); Font font(Font::FindFaceNameIndex("Noto Serif CJK KR"), 20);
Font font = StdFont();
// Font font = Roman(20);
// SaveFile("d:/xxx/font.bin", GetFontDataSys(font, 0)); // SaveFile("d:/xxx/font.bin", GetFontDataSys(font, 0));
String cmap = GetFontDataSys(font, CMAP); // String cmap = GetFontDataSys(font, CMAP);
LOGHEXDUMP(~cmap, 256); // LOGHEXDUMP(~cmap, 256);
FontTypeReader r; FontTypeReader r;
// r.Open(Arial(20).GetData()); // r.Open(Arial(20).GetData());
r.Open(font.GetData()); DDUMP(font.GetFaceName());
r.Open(font);
DDUMPHEX(r.panose);
return; return;
@ -55,34 +107,52 @@ GUI_APP_MAIN
#endif #endif
Progress pi; Progress pi;
pi.SetTotal(Font::GetFaceCount()); pi.SetTotal(Font::GetFaceCount());
for(int i = 0; i < Font::GetFaceCount(); i++) { Vector<String> name;
for(int i = 0; i < Font::GetFaceCount(); i++)
name.Add(Font::GetFaceName(i));
for(int i : GetSortOrder(name)) {
String f = Font::GetFaceName(i); String f = Font::GetFaceName(i);
pi.SetText(f); pi.SetText(f);
if(pi.StepCanceled()) if(pi.StepCanceled())
break; break;
Font fnt; Font fnt;
fnt.FaceName(f); fnt.FaceName(f);
DLOG("===========");
DDUMP(f);
FontTypeReader r; FontTypeReader r;
// r.Open(Arial(20).GetData()); // r.Open(Arial(20).GetData());
r.Open(fnt.GetData()); r.Open(fnt);
Sort(r.ranges, [](Tuple<int, int> a, Tuple<int, int> b) { return a.a < b.a; }); if(r.panose.GetCount() == 10) {
DDUMP(r.ranges); dword h[8] = {0};
while(r.ranges.GetCount() > 8) { for(auto r : r.ranges) {
int mini = 0; for(int c = r.a; c <= r.b; c++) {
int mind = INT_MAX; c = max(c, 0);
for(int i = 0; i < r.ranges.GetCount() - 1; i++) { if(c < 2048)
int d = r.ranges[i + 1].a - r.ranges[i].b; h[0] |= 0x80000000 >> (c >> 6);
if(d < mind) { else {
mind = d; int bi = clamp(c - 2048, 0, 7*32*1024 - 1) >> 10;
mini = i; ASSERT((bi >> 5) + 1 < 8);
h[(bi >> 5) + 1] |= 0x80000000 >> (bi & 31);
}
} }
} }
r.ranges[mini].b = r.ranges[mini + 1].b; String l;
r.ranges.Remove(mini + 1); 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()); // r.Open(Font(Font::FindFaceNameIndex("Segoe UI Emoji"), 20).GetData());

View file

@ -218,8 +218,8 @@ bool CodeEditor::RegExpFind(int64 pos, bool block)
for(int i = 0; i < regex.GetCount(); i++) for(int i = 0; i < regex.GetCount(); i++)
SetFound(i, WILDANY, regex.GetString(i).ToWString()); SetFound(i, WILDANY, regex.GetString(i).ToWString());
int off = regex.GetOffset(); int off = regex.GetOffset();
int len = utf8len(~ln + off, regex.GetLength()); int len = Utf32Len(~ln + off, regex.GetLength());
pos = GetPos64(line, utf8len(~ln, off) + (int)pos); pos = GetPos64(line, Utf32Len(~ln, off) + (int)pos);
foundtext = GetW(pos, len); foundtext = GetW(pos, len);
if(!block) { if(!block) {
foundsel = true; foundsel = true;

View file

@ -59,7 +59,7 @@ String GetHomeDirectory() {
String GetEnv(const char *id) String GetEnv(const char *id)
{ {
return WString(_wgetenv(WString(id))).ToString(); return WString(_wgetenv(ToSystemCharsetW(id))).ToString();
} }
String GetExeFilePath() String GetExeFilePath()
@ -500,27 +500,27 @@ void AppInitEnvironment__()
int nArgs; int nArgs;
LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs); LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if(szArglist) { if(szArglist) {
strcpy(Argv0__, WString(szArglist[0]).ToString()); strcpy(Argv0__, FromSystemCharsetW(szArglist[0]));
for(int i = 1; i < nArgs; i++) for(int i = 1; i < nArgs; i++)
coreCmdLine__().Add(szArglist[i]); coreCmdLine__().Add(FromSystemCharsetW(szArglist[i]).ToWString());
LocalFree(szArglist); LocalFree(szArglist);
} }
wchar *env = GetEnvironmentStringsW(); WCHAR *env = GetEnvironmentStringsW();
for(wchar *ptr = env; *ptr; ptr++) for(WCHAR *ptr = env; *ptr; ptr++)
{ {
const wchar *b = ptr; const WCHAR *b = ptr;
if(*ptr) if(*ptr)
ptr++; ptr++;
while(*ptr && *ptr != '=') while(*ptr && *ptr != '=')
ptr++; ptr++;
WString varname(b, ptr); WString varname = ToUtf32(b, int(ptr - b));
if(*ptr) if(*ptr)
ptr++; ptr++;
b = ptr; b = ptr;
while(*ptr) while(*ptr)
ptr++; ptr++;
EnvMap().GetAdd(ToUpper(varname)) = WString(b, ptr); EnvMap().GetAdd(ToUpper(varname)) = ToUtf32(b, int(ptr - b));
} }
FreeEnvironmentStringsW(env); FreeEnvironmentStringsW(env);
@ -556,16 +556,16 @@ void LaunchWebBrowser(const String& url)
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE) #if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
static auxthread_t auxthread__ sShellExecuteOpen(void *str) 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); free(str);
return 0; return 0;
} }
void LaunchWebBrowser(const String& url) void LaunchWebBrowser(const String& url)
{ {
WString wurl = ToSystemCharsetW(url); Vector<WCHAR> wurl = ToSystemCharsetW(url);
if ((int64)(ShellExecuteW(NULL, L"open", wurl, NULL, L".", SW_SHOWDEFAULT)) <= 32) { 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); char *curl = (char *)malloc(l);
memcpy(curl, wurl, l); memcpy(curl, wurl, l);
StartAuxThread(sShellExecuteOpen, curl); StartAuxThread(sShellExecuteOpen, curl);
@ -619,27 +619,29 @@ String LoadDataFile(const char *filename)
String GetComputerName() String GetComputerName()
{ {
char temp[256];
*temp = 0;
#if defined(PLATFORM_WIN32) #if defined(PLATFORM_WIN32)
WCHAR temp[256];
*temp = 0;
dword w = 255; dword w = 255;
::GetComputerNameA(temp, &w); ::GetComputerNameW(temp, &w);
#else #else
char temp[256];
gethostname(temp, sizeof(temp)); gethostname(temp, sizeof(temp));
#endif #endif
return FromSystemCharset(temp); return temp;
} }
String GetUserName() String GetUserName()
{ {
char temp[256];
*temp = 0;
#if defined(PLATFORM_WIN32) #if defined(PLATFORM_WIN32)
WCHAR temp[256];
*temp = 0;
dword w = 255; dword w = 255;
::GetUserNameA(temp, &w); ::GetUserNameW(temp, &w);
return FromSystemCharset(temp); return temp;
#else #else
return Nvl(GetEnv("USER"), "boot"); char temp[256];
return Nvl(GetEnv("USER"), "root");
#endif #endif
} }
@ -661,9 +663,9 @@ String GetDesktopManager()
String GetShellFolder(int clsid) String GetShellFolder(int clsid)
{ {
wchar path[MAX_PATH]; WCHAR path[MAX_PATH];
if(SHGetFolderPathW(NULL, clsid, NULL, /*SHGFP_TYPE_CURRENT*/0, path) == S_OK) if(SHGetFolderPathW(NULL, clsid, NULL, /*SHGFP_TYPE_CURRENT*/0, path) == S_OK)
return FromUnicodeBuffer(path); return FromSystemCharsetW(path);
return Null; return Null;
} }
@ -691,7 +693,7 @@ String GetDownloadFolder()
if(SHGetKnownFolderPath) { if(SHGetKnownFolderPath) {
PWSTR path = NULL; PWSTR path = NULL;
if(SHGetKnownFolderPath(&MY_FOLDERID_Downloads, 0, NULL, &path) == S_OK && path) { if(SHGetKnownFolderPath(&MY_FOLDERID_Downloads, 0, NULL, &path) == S_OK && path) {
String s = FromUnicodeBuffer(path, wstrlen(path)); String s = FromSystemCharsetW(path);
CoTaskMemFree(path); CoTaskMemFree(path);
return s; return s;
} }

View file

@ -35,7 +35,7 @@ static void sLoadBom(Stream& in, String *t, WString *wt, byte def_charset)
byte *h = (byte *)&header; byte *h = (byte *)&header;
if(h[0] == 0xef && h[1] == 0xbb && c == 0xbf) { if(h[0] == 0xef && h[1] == 0xbb && c == 0xbf) {
if(wt) if(wt)
*wt = FromUtf8(LoadStream(in)); *wt = ToUtf32(LoadStream(in));
else else
*t = ToCharset(CHARSET_DEFAULT, LoadStream(in), CHARSET_UTF8); *t = ToCharset(CHARSET_DEFAULT, LoadStream(in), CHARSET_UTF8);
return; return;

View file

@ -1998,12 +1998,6 @@ int ToAscii(int c, byte charset)
return cs.FromUnicode(ToAscii(cs.ToUnicode(c))); 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) void ToUpper(char *t, const char *s, int len, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
@ -2050,7 +2044,7 @@ WString ToUnicode(const char *src, int l, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return FromUtf8(src, l); return ToUtf32(src, l);
WStringBuffer result(l); WStringBuffer result(l);
ToUnicode(result, src, l, charset); ToUnicode(result, src, l, charset);
return WString(result); return WString(result);
@ -2073,7 +2067,7 @@ String FromUnicodeBuffer(const wchar *src, int len, byte charset, int defchar)
String FromUnicodeBuffer(const wchar *src) String FromUnicodeBuffer(const wchar *src)
{ {
return FromUnicodeBuffer(src, wstrlen(src)); return FromUnicodeBuffer(src, strlen__(src));
} }
String FromUnicode(const WString& src, byte charset, int defchar) 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; return src;
int slen = src.GetLength(); int slen = src.GetLength();
if(scharset == CHARSET_UTF8) if(scharset == CHARSET_UTF8)
return FromUnicode(FromUtf8(src, slen), charset, def); return FromUnicode(ToUtf32(src, slen), charset, def);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return ToUtf8(ToUnicode(src, scharset)); return ToUtf8(ToUnicode(src, scharset));
StringBuffer result(slen); StringBuffer result(slen);
@ -2161,7 +2155,7 @@ String ToUpper(const char *s, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return ToUtf8(ToUpper(FromUtf8(s))); return ToUtf8(ToUpper(ToUtf32(s)));
int l = (int)strlen(s); int l = (int)strlen(s);
StringBuffer r(l); StringBuffer r(l);
ToUpper(r, s, l, charset); ToUpper(r, s, l, charset);
@ -2172,7 +2166,7 @@ String ToLower(const char *s, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return ToUtf8(ToLower(FromUtf8(s))); return ToUtf8(ToLower(ToUtf32(s)));
int l = (int)strlen(s); int l = (int)strlen(s);
StringBuffer r(l); StringBuffer r(l);
ToLower(r, s, l, charset); ToLower(r, s, l, charset);
@ -2183,7 +2177,7 @@ String ToAscii(const char *s, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return ToUtf8(ToAscii(FromUtf8(s))); return ToUtf8(ToAscii(ToUtf32(s)));
int l = (int)strlen(s); int l = (int)strlen(s);
StringBuffer r(l); StringBuffer r(l);
ToAscii(r, s, l, charset); ToAscii(r, s, l, charset);
@ -2194,7 +2188,7 @@ String ToUpper(const String& s, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return ToUtf8(ToUpper(FromUtf8(s))); return ToUtf8(ToUpper(ToUtf32(s)));
int l = s.GetLength(); int l = s.GetLength();
StringBuffer r(l); StringBuffer r(l);
ToUpper(r, s, l, charset); ToUpper(r, s, l, charset);
@ -2205,7 +2199,7 @@ String ToLower(const String& s, byte charset)
{ {
charset = ResolveCharset(charset); charset = ResolveCharset(charset);
if(charset == CHARSET_UTF8) if(charset == CHARSET_UTF8)
return ToUtf8(ToLower(FromUtf8(s))); return ToUtf8(ToLower(ToUtf32(s)));
int l = s.GetLength(); int l = s.GetLength();
StringBuffer r(l); StringBuffer r(l);
ToLower(r, s, l, charset); ToLower(r, s, l, charset);

View file

@ -8,6 +8,7 @@ enum {
#undef CHRSET_ #undef CHRSET_
#define CHARSET_TOASCII 253 #define CHARSET_TOASCII 253
#define CHARSET_UTF32 254 // auxilary
#define CHARSET_UTF8 255 #define CHARSET_UTF8 255
#define CHARSET_UNICODE 255 #define CHARSET_UNICODE 255
@ -23,86 +24,83 @@ enum {
#include "Utf.hpp" #include "Utf.hpp"
int strlen32(const dword *s); inline bool IsUtf8Lead(int c) { return (c & 0xc0) != 0x80; }
inline bool IsUtf8Lead(int c) wchar ReadSurrogatePair(const char16 *s, const char16 *lim);
{
return (c & 0xc0) != 0x80;
}
dword FetchUtf8(const char *&s, const char *lim, bool& ok); wchar 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); } 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); 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()); } 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<dword>& s) { return Utf8Len(s, s.GetCount()); }
inline int Utf8Len(dword code) { return Utf8Len(&code, 1); }
int Utf8Len(const wchar *s, int len); 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()); } inline int Utf8Len(const WString& s) { return Utf8Len(~s, s.GetCount()); }
void ToUtf8(char *t, const dword *s, int len); int Utf8Len(const char16 *s, int len);
String ToUtf8(const dword *s, int len); inline int Utf8Len(const char16 *s) { return Utf8Len(s, strlen16(s)); }
inline String ToUtf8(const dword *s) { return ToUtf8(s, strlen32(s)); } inline int Utf8Len(const Vector<char16>& s) { return Utf8Len(s, s.GetCount()); }
inline String ToUtf8(const Vector<dword>& s) { return ToUtf8(s, s.GetCount()); }
inline String ToUtf8(dword code) { return ToUtf8(&code, 1); }
void ToUtf8(char *t, const wchar *s, int len); void ToUtf8(char *t, const wchar *s, int len);
String ToUtf8(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()); } inline String ToUtf8(const WString& s) { return ToUtf8(~s, s.GetCount()); }
int Utf16Len(const dword *s, int len); void ToUtf8(char *t, const char16 *s, int len);
inline int Utf16Len(const dword *s) { return Utf16Len(s, strlen32(s)); } String ToUtf8(const char16 *s, int len);
inline int Utf16Len(const Vector<dword>& s) { return Utf16Len(s, s.GetCount()); } inline String ToUtf8(const char16 *s) { return ToUtf8(s, strlen16(s)); }
inline int Utf16Len(dword code) { return Utf16Len(&code, 1); } inline String ToUtf8(const Vector<char16>& 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); 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()); } inline int Utf16Len(const String& s) { return Utf16Len(~s, s.GetCount()); }
void ToUtf16(wchar *t, const dword *s, int len); int ToUtf16(char16 *t, const wchar *s, int len);
WString ToUtf16(const dword *s, int len); Vector<char16> ToUtf16(const wchar *s, int len);
inline WString ToUtf16(const dword *s) { return ToUtf16(s, strlen32(s)); } inline Vector<char16> ToUtf16(const wchar *s) { return ToUtf16(s, strlen32(s)); }
inline WString ToUtf16(const Vector<dword>& s) { return ToUtf16(s, s.GetCount()); } inline Vector<char16> ToUtf16(const WString& s) { return ToUtf16(s, s.GetCount()); }
inline WString ToUtf16(dword code) { return ToUtf16(&code, 1); } inline Vector<char16> ToUtf16(wchar code) { return ToUtf16(&code, 1); }
void ToUtf16(wchar *t, const char *s, int len); int ToUtf16(char16 *t, const char *s, int len);
WString ToUtf16(const char *s, int len); Vector<char16> ToUtf16(const char *s, int len);
inline WString ToUtf16(const char *s) { return ToUtf16(s, (int)strlen(s)); } inline Vector<char16> ToUtf16(const char *s) { return ToUtf16(s, (int)strlen8(s)); }
inline WString ToUtf16(const String& s) { return ToUtf16(~s, s.GetCount()); } inline Vector<char16> ToUtf16(const String& s) { return ToUtf16(~s, s.GetCount()); }
int Utf32Len(const wchar *s, int len); int Utf32Len(const char16 *s, int len);
inline int Utf32Len(const wchar *s) { return Utf32Len(s, wstrlen(s)); } inline int Utf32Len(const char16 *s) { return Utf32Len(s, strlen16(s)); }
inline int Utf32Len(const WString& s) { return Utf32Len(~s, s.GetCount()); } inline int Utf32Len(const Vector<char16>& s) { return Utf32Len(s, s.GetCount()); }
int Utf32Len(const char *s, int len); 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()); } 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<char16>& s) { return ToUtf32(s, s.GetCount()); }
void ToUtf32(dword *t, const wchar *s, int len); void ToUtf32(wchar *t, const char *s, int len);
Vector<dword> ToUtf32(const wchar *s, int len); WString ToUtf32(const char *s, int len);
inline Vector<dword> ToUtf32(const wchar *s) { return ToUtf32(s, wstrlen(s)); } inline WString ToUtf32(const char *s) { return ToUtf32(s, (int)strlen8(s)); }
inline Vector<dword> ToUtf32(const WString& s) { return ToUtf32(~s, s.GetCount()); } inline WString ToUtf32(const String& s) { return ToUtf32(~s, s.GetCount()); }
void ToUtf32(dword *t, const char *s, int len);
Vector<dword> ToUtf32(const char *s, int len);
inline Vector<dword> ToUtf32(const char *s) { return ToUtf32(s, (int)strlen(s)); }
inline Vector<dword> ToUtf32(const String& s) { return ToUtf32(~s, s.GetCount()); }
enum { MAX_DECOMPOSED = 18 }; enum { MAX_DECOMPOSED = 18 };
int UnicodeDecompose(dword codepoint, dword t[MAX_DECOMPOSED], bool only_canonical = false); int UnicodeDecompose(wchar codepoint, wchar t[MAX_DECOMPOSED], bool only_canonical = false);
Vector<dword> UnicodeDecompose(dword codepoint, bool only_canonical = false); WString UnicodeDecompose(wchar codepoint, bool only_canonical = false);
dword UnicodeCompose(const dword *t, int count); wchar UnicodeCompose(const WString& t);
inline dword UnicodeCompose(const Vector<dword>& t) { return UnicodeCompose(t, t.GetCount()); }
void SetDefaultCharset(byte charset); void SetDefaultCharset(byte charset);
byte GetDefaultCharset(); byte GetDefaultCharset();
@ -127,62 +125,62 @@ extern byte unicode_fast_info__[2048];
extern byte unicode_fast_upper_ascii__[]; extern byte unicode_fast_upper_ascii__[];
extern byte unicode_fast_lower_ascii__[]; extern byte unicode_fast_lower_ascii__[];
dword ToUpperRest_(dword c); wchar ToUpperRest_(wchar c);
dword ToLowerRest_(dword c); wchar ToLowerRest_(wchar c);
char ToAsciiRest_(dword c); char ToAsciiRest_(wchar c);
bool IsRTL_(dword c); bool IsRTL_(wchar c);
bool IsMark_(dword c); bool IsMark_(wchar c);
bool IsLetter_(dword c); bool IsLetter_(wchar c);
bool IsUpper_(dword c); bool IsUpper_(wchar c);
bool IsLower_(dword c); bool IsLower_(wchar c);
inline dword ToUpper(dword c) { return c < 2048 ? unicode_fast_upper__[c] : ToUpperRest_(c); } inline wchar ToUpper(wchar 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 wchar ToLower(wchar 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 ToAscii(wchar 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 ToUpperAscii(wchar 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 char ToLowerAscii(wchar 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 IsLower(wchar 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 IsUpper(wchar 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 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 IsRTL(wchar c) { return (wchar)c >= 1470 && IsRTL_(c); }
inline bool IsMark(dword c) { return c < 0x300 ? false : c <= 0x36f ? true : IsMark_(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 IsLetter(int c) { return IsLetter((wchar) c); }
inline bool IsUpper(int c) { return IsUpper((dword) c); } inline bool IsUpper(int c) { return IsUpper((wchar) c); }
inline bool IsLower(int c) { return IsLower((dword) c); } inline bool IsLower(int c) { return IsLower((wchar) c); }
inline int ToUpper(int c) { return ToUpper((dword) c); } inline int ToUpper(int c) { return ToUpper((wchar) c); }
inline int ToLower(int c) { return ToLower((dword) c); } inline int ToLower(int c) { return ToLower((wchar) c); }
inline char ToAscii(int c) { return ToAscii((dword) c); } inline char ToAscii(int c) { return ToAscii((wchar) c); }
inline char ToUpperAscii(int c) { return ToUpperAscii((dword) c); } inline char ToUpperAscii(int c) { return ToUpperAscii((wchar) c); }
inline char ToLowerAscii(int c) { return ToUpperAscii((dword) c); } inline char ToLowerAscii(int c) { return ToUpperAscii((wchar) c); }
inline bool IsLetter(char c) { return IsLetter((dword)(byte) c); } inline bool IsLetter(char c) { return IsLetter((wchar)(byte) c); }
inline bool IsUpper(char c) { return IsUpper((dword)(byte) c); } inline bool IsUpper(char c) { return IsUpper((wchar)(byte) c); }
inline bool IsLower(char c) { return IsLower((dword)(byte) c); } inline bool IsLower(char c) { return IsLower((wchar)(byte) c); }
inline dword ToUpper(char c) { return ToUpper((dword)(byte) c); } inline wchar ToUpper(char c) { return ToUpper((wchar)(byte) c); }
inline dword ToLower(char c) { return ToLower((dword)(byte) c); } inline wchar ToLower(char c) { return ToLower((wchar)(byte) c); }
inline char ToAscii(char c) { return ToAscii((dword)(byte) c); } inline char ToAscii(char c) { return ToAscii((wchar)(byte) c); }
inline char ToUpperAscii(char c) { return ToUpperAscii((dword)(byte) c); } inline char ToUpperAscii(char c) { return ToUpperAscii((wchar)(byte) c); }
inline char ToLowerAscii(char c) { return ToLowerAscii((dword)(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 IsLetter(signed char c) { return IsLetter((wchar)(byte) c); }
inline bool IsUpper(signed char c) { return IsUpper((dword)(byte) c); } inline bool IsUpper(signed char c) { return IsUpper((wchar)(byte) c); }
inline bool IsLower(signed char c) { return IsLower((dword)(byte) c); } inline bool IsLower(signed char c) { return IsLower((wchar)(byte) c); }
inline dword ToUpper(signed char c) { return ToUpper((dword)(byte) c); } inline wchar ToUpper(signed char c) { return ToUpper((wchar)(byte) c); }
inline dword ToLower(signed char c) { return ToLower((dword)(byte) c); } inline wchar ToLower(signed char c) { return ToLower((wchar)(byte) c); }
inline char ToAscii(signed char c) { return ToAscii((dword)(byte) c); } inline char ToAscii(signed char c) { return ToAscii((wchar)(byte) c); }
inline char ToUpperAscii(signed char c) { return ToUpperAscii((dword)(byte) c); } inline char ToUpperAscii(signed char c) { return ToUpperAscii((wchar)(byte) c); }
inline char ToLowerAscii(signed char c) { return ToLowerAscii((dword)(byte) c); } inline char ToLowerAscii(signed char c) { return ToLowerAscii((wchar)(byte) c); }
inline bool IsLetter(wchar c) { return IsLetter((dword) c); } inline bool IsLetter(char16 c) { return IsLetter((wchar) c); }
inline bool IsUpper(wchar c) { return IsUpper((dword) c); } inline bool IsUpper(char16 c) { return IsUpper((wchar) c); }
inline bool IsLower(wchar c) { return IsLower((dword) c); } inline bool IsLower(char16 c) { return IsLower((wchar) c); }
inline dword ToUpper(wchar c) { return ToUpper((dword) c); } inline wchar ToUpper(char16 c) { return ToUpper((wchar) c); }
inline dword ToLower(wchar c) { return ToLower((dword) c); } inline wchar ToLower(char16 c) { return ToLower((wchar) c); }
inline char ToAscii(wchar c) { return ToAscii((dword) c); } inline char ToAscii(char16 c) { return ToAscii((wchar) c); }
inline char ToUpperAscii(wchar c) { return ToUpperAscii((dword) c); } inline char ToUpperAscii(char16 c) { return ToUpperAscii((wchar) c); }
inline char ToLowerAscii(wchar c) { return ToLowerAscii((dword) c); } inline char ToLowerAscii(char16 c) { return ToLowerAscii((wchar) c); }
inline bool IsDigit(int c) { return c >= '0' && c <= '9'; } inline bool IsDigit(int c) { return c >= '0' && c <= '9'; }
inline bool IsAlpha(int c) { return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; } 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 Utf8ToUpperAscii(const String& src);
String Utf8ToLowerAscii(const String& src); String Utf8ToLowerAscii(const String& src);
void ToUpper(wchar *t, const wchar *s, int len); void ToUpper(char16 *t, const char16 *s, int len);
void ToLower(wchar *t, const wchar *s, int len); void ToLower(char16 *t, const char16 *s, int len);
void ToAscii(wchar *t, const wchar *s, int len); void ToAscii(char16 *t, const char16 *s, int len);
void ToUpper(wchar *s, int len); void ToUpper(char16 *s, int len);
void ToLower(wchar *s, int len); void ToLower(char16 *s, int len);
void ToAscii(wchar *s, int len); void ToAscii(char16 *s, int len);
bool IsLetter(int c, byte charset); bool IsLetter(int c, byte charset);
bool IsUpper(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); 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 String& src, byte charset);
WString ToUnicode(const char *src, int n, 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, int len, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR);
String FromUnicodeBuffer(const wchar *src); String FromUnicodeBuffer(const wchar *src);
String FromUnicode(const WString& src, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR); String FromUnicode(const WString& src, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR);
inline WString FromUtf8(const char *s, int len) { return ToUtf16(s, len); } int ToUnicode(int chr, byte charset);
inline WString FromUtf8(const char *s) { return ToUtf16(s); } int FromUnicode(wchar wchr, byte charset, int defchar = DEFAULTCHAR);
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); }

View file

@ -1,7 +1,7 @@
#ifndef CORE_H #ifndef CORE_H
#define CORE_H #define CORE_H
#define UPP_VERSION 0x20200200 #define UPP_VERSION 0x20210900
#ifndef flagMT #ifndef flagMT
#define flagMT // MT is now always on #define flagMT // MT is now always on
@ -63,6 +63,11 @@
#ifdef CPU_X86 #ifdef CPU_X86
#include <immintrin.h> #include <immintrin.h>
#ifdef PLATFORM_WIN32
#include <intrin.h>
#endif
#endif #endif
#if defined(PLATFORM_POSIX) #if defined(PLATFORM_POSIX)
@ -306,7 +311,6 @@ class JsonIO;
#include "String.h" #include "String.h"
#include "TimeDate.h" #include "TimeDate.h"
#include "Path.h"
#include "Stream.h" #include "Stream.h"
#include "Diag.h" #include "Diag.h"
@ -324,6 +328,8 @@ class JsonIO;
#include "CharSet.h" #include "CharSet.h"
#include "Path.h"
#include "SplitMerge.h" #include "SplitMerge.h"
#include "Other.h" #include "Other.h"

View file

@ -1,12 +1,8 @@
#include "Core.h" #include "Core.h"
#ifdef CPU_X86 #if !(defined(CPU_X86) && defined(COMPILER_MSC))
#ifdef COMPILER_MSC
#include <intrin.h>
#else
#include <cpuid.h> #include <cpuid.h>
#endif #endif
#endif
#ifdef PLATFORM_FREEBSD #ifdef PLATFORM_FREEBSD
#include <sys/vmmeter.h> #include <sys/vmmeter.h>

View file

@ -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 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 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; }; auto U16 = [&] { u1 = u / 10000000000000000; u = u % 10000000000000000; };
switch(precision) { switch(precision) {
case 1: FP(10); D1(u); break; case 1: FP(10); D1((dword)u); break;
case 2: FP(100); D2(u); break; case 2: FP(100); D2((dword)u); break;
case 3: FP(1000); D3(u); break; case 3: FP(1000); D3((dword)u); break;
case 4: FP(10000); D4(u); break; case 4: FP(10000); D4((dword)u); break;
case 5: FP(100000); D5(u); break; case 5: FP(100000); D5((dword)u); break;
case 6: FP(1000000); D6(u); break; case 6: FP(1000000); D6((dword)u); break;
case 7: FP(10000000); D7(u); break; case 7: FP(10000000); D7((dword)u); break;
case 8: FP(100000000); D8(u); break; case 8: FP(100000000); D8((dword)u); break;
case 9: FP(1000000000); U8(); D1(u1); D8(u); break; case 9: FP(1000000000); U8(); D1((dword)u1); D8((dword)u); break;
case 10: FP(10000000000); U8(); D2(u1); D8(u); break; case 10: FP(10000000000); U8(); D2((dword)u1); D8((dword)u); break;
case 11: FP(100000000000); U8(); D3(u1); D8(u); break; case 11: FP(100000000000); U8(); D3((dword)u1); D8((dword)u); break;
case 12: FP(1000000000000); U8(); D4(u1); D8(u); break; case 12: FP(1000000000000); U8(); D4((dword)u1); D8((dword)u); break;
case 13: FP(10000000000000); U8(); D5(u1); D8(u); break; case 13: FP(10000000000000); U8(); D5((dword)u1); D8((dword)u); break;
case 14: FP(100000000000000); U8(); D6(u1); D8(u); break; case 14: FP(100000000000000); U8(); D6((dword)u1); D8((dword)u); break;
case 15: FP(1000000000000000); U8(); D7(u1); D8(u); break; case 15: FP(1000000000000000); U8(); D7((dword)u1); D8((dword)u); break;
case 16: FP(10000000000000000); U8(); D8(u1); D8(u); break; case 16: FP(10000000000000000); U8(); D8((dword)u1); D8((dword)u); break;
case 17: FP(100000000000000000); U16(); D1(u1); U8(); D8(u1); D8(u); break; case 17: FP(100000000000000000); U16(); D1((dword)u1); U8(); D8((dword)u1); D8((dword)u); break;
case 18: FP(1000000000000000000u); U16(); D2(u1); U8(); D8(u1); D8(u); break; case 18: FP(1000000000000000000u); U16(); D2((dword)u1); U8(); D8((dword)u1); D8((dword)u); break;
} }
return -e10; return -e10;
} }

View file

@ -145,14 +145,16 @@ typedef short unsigned uint16;
typedef unsigned long dword; typedef unsigned long dword;
typedef long int32; typedef long int32;
typedef unsigned long uint32; typedef unsigned long uint32;
typedef WCHAR wchar; typedef WCHAR char16;
#else #else
typedef unsigned int dword; typedef unsigned int dword;
typedef int int32; typedef int int32;
typedef unsigned int uint32; typedef unsigned int uint32;
typedef word wchar; typedef word char16;
#endif #endif
typedef uint32 wchar;
#ifdef COMPILER_MSC #ifdef COMPILER_MSC
typedef __int64 int64; typedef __int64 int64;

View file

@ -47,7 +47,7 @@ bool FileMapping::Open(const char *file, bool delete_share)
write = false; write = false;
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
hfile = CreateFileW(ToSystemCharsetW(file), GENERIC_READ, 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); NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(hfile == INVALID_HANDLE_VALUE) if(hfile == INVALID_HANDLE_VALUE)
return false; return false;

View file

@ -559,7 +559,7 @@ String DoubleFormatter(const Formatting& f)
dword n; dword n;
bool overflow = false; bool overflow = false;
s = ScanUint<char, byte, dword, 10>(n, s, overflow); s = ScanUint<char, byte, dword, 10>(n, s, overflow);
if(overflow || !s || n > (wd ? 1000 : 100)) if(overflow || !s || n > (wd ? 1000u : 100u))
return Null; return Null;
(wd ? width : precision) = n; (wd ? width : precision) = n;
} }

View file

@ -23,9 +23,6 @@ void *MemoryAlloc(size_t size);
void MemoryFree(void *ptr); void MemoryFree(void *ptr);
void *MemoryAlloc32(); void *MemoryAlloc32();
void MemoryFree32(void *ptr); void MemoryFree32(void *ptr);
void *MemoryAlloc48();
void MemoryFree48(void *ptr);
void MemoryFreeThread();
void MemoryCheck(); void MemoryCheck();
void MemoryDumpLarge(); void MemoryDumpLarge();
void MemoryDumpHuge(); void MemoryDumpHuge();

View file

@ -410,7 +410,7 @@ struct Heap : BlkHeap<HugeHeapDetail, 4096> {
void Init(); void Init();
static int CheckFree(FreeLink *l, int k); static int CheckFree(FreeLink *l, int k, bool page = true);
void Check(); void Check();
static void DblCheck(Page *p); static void DblCheck(Page *p);
static void AssertLeaks(bool b); static void AssertLeaks(bool b);

View file

@ -68,9 +68,9 @@ public:
WString GetIndexLetter(const wchar *text) const { return (*getindexletter)(text, language); } 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, 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(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()); } 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; } bool operator()(const wchar *a, const wchar *b) const { return Compare(a, b) < 0; }

View file

@ -193,14 +193,14 @@ int CSCZLanguageCompare(const wchar *a, int a_length, const wchar *b, int b_leng
String GetLocaleInfoA(LCID lcid, LCTYPE lctype) String GetLocaleInfoA(LCID lcid, LCTYPE lctype)
{ {
wchar cbuf[1000]; WCHAR cbuf[1000];
::GetLocaleInfoW(lcid, lctype, cbuf, __countof(cbuf)); ::GetLocaleInfoW(lcid, lctype, cbuf, __countof(cbuf));
return FromSystemCharsetW(cbuf); return cbuf;
} }
WString GetLocaleInfoW(LCID lcid, LCTYPE lctype) WString GetLocaleInfoW(LCID lcid, LCTYPE lctype)
{ {
wchar wbuf[1000]; WCHAR wbuf[1000];
Zero(wbuf); Zero(wbuf);
if(::GetLocaleInfoW(lcid, lctype, (WCHAR *)wbuf, __countof(wbuf))) if(::GetLocaleInfoW(lcid, lctype, (WCHAR *)wbuf, __countof(wbuf)))
return wbuf; return wbuf;

View file

@ -68,14 +68,11 @@ static void sNoBlock(int fd)
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
bool Win32CreateProcess(const char *command, const char *envptr, STARTUPINFOW& si, PROCESS_INFORMATION& pi, const char *cd) bool Win32CreateProcess(const char *command, const char *envptr, STARTUPINFOW& si, PROCESS_INFORMATION& pi, const char *cd)
{ // provides conversion of charset for cmdline and envptr { // provides conversion of charset for cmdline and envptr
WString wcmd(command); Vector<WCHAR> cmd = ToSystemCharsetW(command);
int n = wcmd.GetCount() + 1; cmd.Add(0);
WString wcd(cd);
Buffer<wchar> cmd(n);
memcpy(cmd, wcmd, n * sizeof(wchar));
#if 0 // unicode environment not necessary for now #if 0 // unicode environment not necessary for now
wchar wenvptr = NULL; wchar wenvptr = NULL;
Buffer<wchar> env(n); Buffer<WCHAR> env(n);
if(envptr) { if(envptr) {
int len = 0; int len = 0;
while(envptr[len] || envptr[len + 1]) 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)); memcpy(env, wenv, (len + 2) * sizeof(wchar));
} }
#endif #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 #endif

View file

@ -641,4 +641,22 @@ int inline_memcmp_aligned(const char *a, const char *b, size_t count)
} }
#endif #endif
template <class T>
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); hash_t memhash(const void *ptr, size_t count);

View file

@ -12,10 +12,10 @@ NetNode::NetNode()
NetNode& NetNode::operator=(const NetNode& s) NetNode& NetNode::operator=(const NetNode& s)
{ {
net = s.net; net = s.net;
local = s.local; local = clone(s.local);
remote = s.remote; remote = clone(s.remote);
comment = s.comment; comment = clone(s.comment);
provider = s.provider; provider = clone(s.provider);
name = s.name; name = s.name;
path = s.path; path = s.path;
SetPtrs(); SetPtrs();
@ -30,25 +30,23 @@ String DosInitCaps(const char *name)
return InitCaps(name); return InitCaps(name);
} }
void NetNode::SetPtr(String& s, char *& ptr)
{
if(ptr) ptr = (char *)~s;
}
void NetNode::SetPtrs() void NetNode::SetPtrs()
{ {
auto SetPtr = [](Vector<char16>& s, char16 *& ptr) { if(ptr) ptr = s; };
SetPtr(local, net.lpLocalName); SetPtr(local, net.lpLocalName);
SetPtr(remote, net.lpRemoteName); SetPtr(remote, net.lpRemoteName);
SetPtr(comment, net.lpComment); SetPtr(comment, net.lpComment);
SetPtr(provider, net.lpProvider); SetPtr(provider, net.lpProvider);
} }
/*
void NetNode::Serialize(Stream& s) void NetNode::Serialize(Stream& s)
{ {
s % net.dwScope % net.dwType % net.dwDisplayType % net.dwUsage; s % net.dwScope % net.dwType % net.dwDisplayType % net.dwUsage;
s % local % remote % comment % provider % name % path; s % local % remote % comment % provider % name % path;
SetPtrs(); SetPtrs();
} }
*/
Array<NetNode> NetNode::Enum() const Array<NetNode> NetNode::Enum() const
{ {
@ -78,34 +76,35 @@ Array<NetNode> NetNode::Enum0(HANDLE hEnum)
{ {
Array<NetNode> r; Array<NetNode> r;
DWORD cEntries = (DWORD)-1, cbBuffer = 0x4000; DWORD cEntries = (DWORD)-1, cbBuffer = 0x4000;
Buffer<NETRESOURCE> lpnr(cbBuffer); Buffer<NETRESOURCEW> lpnr(cbBuffer);
while(::WNetEnumResource(hEnum, &cEntries, lpnr, &cbBuffer) == 0) { while(::WNetEnumResourceW(hEnum, &cEntries, lpnr, &cbBuffer) == 0) {
for(int i = 0; i < (int)cEntries; i++) { for(int i = 0; i < (int)cEntries; i++) {
NETRESOURCE& sn = lpnr[i]; NETRESOURCEW& sn = lpnr[i];
const char *s = sn.lpRemoteName; const WCHAR *s = sn.lpRemoteName;
NetNode& nn = r.Add(); NetNode& nn = r.Add();
NETRESOURCE& n = nn.net; NETRESOURCEW& n = nn.net;
n = sn; n = sn;
nn.local = n.lpLocalName; auto get = [](const char16 *s) { Vector<char16> x; while(s && *s) x.Add(*s++); x.Add(0); return x; };
nn.remote = n.lpRemoteName; nn.local = get(n.lpLocalName);
nn.comment = n.lpComment; nn.remote = get(n.lpRemoteName);
nn.provider = n.lpProvider; nn.comment = get(n.lpComment);
nn.provider = get(n.lpProvider);
nn.SetPtrs(); nn.SetPtrs();
if(s) { if(s) {
if(s[0] == '\\' && s[1] == '\\') if(s[0] == '\\' && s[1] == '\\')
nn.name = FromSystemCharset(DosInitCaps(GetFileName(s))); nn.name = DosInitCaps(GetFileName(FromSystemCharsetW(s)));
else else
nn.name = FromSystemCharset(s); nn.name = FromSystemCharsetW(s);
} }
if(n.lpComment && *n.lpComment) { if(n.lpComment && *n.lpComment) {
if(nn.name.GetCount()) if(nn.name.GetCount())
nn.name = String().Cat() << FromSystemCharset(n.lpComment) nn.name = String().Cat() << FromSystemCharsetW(n.lpComment)
<< " (" << nn.name << ")"; << " (" << nn.name << ")";
else else
nn.name = FromSystemCharset(n.lpComment); nn.name = FromSystemCharsetW(n.lpComment);
} }
if(!(n.dwUsage & RESOURCEUSAGE_CONTAINER)) if(!(n.dwUsage & RESOURCEUSAGE_CONTAINER))
nn.path = FromSystemCharset(n.lpRemoteName); nn.path = FromSystemCharsetW(n.lpRemoteName);
} }
} }
::WNetCloseEnum(hEnum); ::WNetCloseEnum(hEnum);

View file

@ -233,8 +233,6 @@ byte addc64(uint64& result, const uint64& value, byte carry) {
#elif defined(COMPILER_MSC) && defined(CPU_64) #elif defined(COMPILER_MSC) && defined(CPU_64)
#include <intrin.h>
inline inline
uint64 mul64(uint64 a, uint64 b, uint64& hi) uint64 mul64(uint64 a, uint64 b, uint64& hi)
{ {

View file

@ -187,7 +187,7 @@ bool PathIsEqual(const char *p1, const char *p2)
#ifndef PLATFORM_WINCE #ifndef PLATFORM_WINCE
String GetCurrentDirectory() { String GetCurrentDirectory() {
#if defined(PLATFORM_WIN32) #if defined(PLATFORM_WIN32)
wchar h[MAX_PATH]; WCHAR h[MAX_PATH];
GetCurrentDirectoryW(MAX_PATH, h); GetCurrentDirectoryW(MAX_PATH, h);
return FromSystemCharsetW(h); return FromSystemCharsetW(h);
#elif defined(PLATFORM_POSIX) #elif defined(PLATFORM_POSIX)
@ -211,7 +211,7 @@ bool SetCurrentDirectory(const char *path)
String GetTempPath() String GetTempPath()
{ {
wchar h[MAX_PATH]; WCHAR h[MAX_PATH];
GetTempPathW(MAX_PATH, h); GetTempPathW(MAX_PATH, h);
return FromSystemCharsetW(h); return FromSystemCharsetW(h);
} }
@ -253,7 +253,7 @@ String ToUnixName(const char* fn, const char* stop = NULL) {
String GetFullPath(const char *file) { String GetFullPath(const char *file) {
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
String ufn = FromUnixName(file); String ufn = FromUnixName(file);
wchar h[MAX_PATH]; WCHAR h[MAX_PATH];
GetFullPathNameW(ToSystemCharsetW(ufn), MAX_PATH, h, 0); GetFullPathNameW(ToSystemCharsetW(ufn), MAX_PATH, h, 0);
return FromSystemCharsetW(h); return FromSystemCharsetW(h);
#else #else
@ -364,10 +364,10 @@ static bool sGetSymLinkPath0(const char *linkpath, String *path)
{ {
bool ret = false; bool ret = false;
HRESULT hres; HRESULT hres;
IShellLink* psl; IShellLinkW* psl;
IPersistFile* ppf; IPersistFile* ppf;
CoInitialize(NULL); CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
(PVOID *) &psl); (PVOID *) &psl);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf); 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); hres = ppf->Load(ToSystemCharsetW(linkpath), STGM_READ);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
if(path) { if(path) {
char fileW[_MAX_PATH] = {0}; WCHAR fileW[_MAX_PATH] = {0};
psl->GetPath(fileW, _MAX_PATH, NULL, 0); psl->GetPath(fileW, _MAX_PATH, NULL, 0);
*path = FromSystemCharset(fileW); *path = fileW;
} }
else else
ret = true; ret = true;
@ -950,20 +950,20 @@ Array<FileSystemInfo::FileInfo> FileSystemInfo::Find(String mask, int max_count,
f.filename = "\\"; f.filename = "\\";
f.root_style = ROOT_FIXED; f.root_style = ROOT_FIXED;
#elif defined(PLATFORM_WIN32) #elif defined(PLATFORM_WIN32)
char drive[4] = "?:\\"; WCHAR drive[4] = L"?:\\";
for(int c = 'A'; c <= 'Z'; c++) { for(int c = 'A'; c <= 'Z'; c++) {
*drive = c; *drive = c;
int n = GetDriveType(drive); int n = GetDriveTypeW(drive);
if(n == DRIVE_NO_ROOT_DIR) if(n == DRIVE_NO_ROOT_DIR)
continue; continue;
FileInfo& f = fi.Add(); FileInfo& f = fi.Add();
f.filename = drive; f.filename = drive;
char name[256], system[256]; WCHAR name[256], system[256];
DWORD d; DWORD d;
if(c != 'A' && c != 'B' && n != DRIVE_UNKNOWN) { 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(b) {
if(*name) f.root_desc << " " << FromSystemCharset(name); if(*name) f.root_desc << " " << FromSystemCharsetW(name);
} }
else if(n == DRIVE_REMOVABLE || n == DRIVE_CDROM) { else if(n == DRIVE_REMOVABLE || n == DRIVE_CDROM) {
if(unmounted) { if(unmounted) {

View file

@ -315,15 +315,14 @@ FileSystemInfo& StdFileSystemInfo();
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
class NetNode : Moveable<NetNode> { class NetNode : Moveable<NetNode> {
NETRESOURCE net; NETRESOURCEW net;
String local, remote, comment, provider; Vector<char16> local, remote, comment, provider;
String name; String name;
String path; String path;
static void Copy(String& t, char *s); static void Copy(String& t, char *s);
static Array<NetNode> Enum0(HANDLE hEnum); static Array<NetNode> Enum0(HANDLE hEnum);
static void SetPtr(String& s, char *& ptr);
void SetPtrs(); void SetPtrs();
@ -334,14 +333,12 @@ public:
String GetName() const { return name; } String GetName() const { return name; }
String GetPath() const { return path; } String GetPath() const { return path; }
int GetDisplayType() const; int GetDisplayType() const;
String GetRemote() const { return remote; } String GetRemote() const { return ToUtf8(remote); }
String GetLocal() const { return local; } String GetLocal() const { return ToUtf8(local); }
String GetProvider() const { return provider; } String GetProvider() const { return ToUtf8(provider); }
String GetComment() const { return comment; } String GetComment() const { return ToUtf8(comment); }
Array<NetNode> Enum() const; Array<NetNode> Enum() const;
void Serialize(Stream& s);
static Array<NetNode> EnumRoot(); static Array<NetNode> EnumRoot();
static Array<NetNode> EnumRemembered(); static Array<NetNode> EnumRemembered();

View file

@ -6,28 +6,25 @@ namespace Upp {
static int64 UPP_SSL_alloc = 0; 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 #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 #else
static void *SslAlloc(size_t size) static void *SslAlloc(size_t size)
#endif #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 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
static void SslFree(void *ptr, const char *, int) static void SslFree(void *ptr, const char *file, int line)
#else #else
static void SslFree(void *ptr) static void SslFree(void *ptr)
#endif #endif
@ -36,35 +33,46 @@ static void SslFree(void *ptr)
return; return;
int64 *aptr = (int64 *)ptr - 1; int64 *aptr = (int64 *)ptr - 1;
UPP_SSL_alloc -= *aptr; 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); MemoryFree(aptr);
} }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #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 #else
static void *SslRealloc(void *ptr, size_t size) static void *SslRealloc(void *ptr, size_t size)
#endif #endif
{ {
LLOG("SslRealloc " << ptr << ", " << size); LLOG("SslRealloc " << ptr << ", " << size);
if(!ptr) if(!ptr) {
return SslAlloc0(size); 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; int64 *aptr = (int64 *)ptr - 1;
if((int64)(size + sizeof(int64)) <= *aptr) { if((int64)(size + sizeof(int64)) <= *aptr) { // TODO: Do we really want this?
LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << *aptr << ") -> keep same block"); LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << *aptr << ") -> keep same block" << ", thread: " << Thread::GetCurrentId());
return ptr; return ptr;
} }
size_t newalloc = size + sizeof(int64); size_t newalloc = size + sizeof(int64);
int64 *newaptr = (int64 *)MemoryAllocSz(newalloc); int64 *newaptr = (int64 *)MemoryAllocSz(newalloc);
if(!newaptr) { 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; return NULL;
} }
*newaptr++ = newalloc; *newaptr++ = newalloc;
memcpy(newaptr, ptr, min<int>((int)(*aptr - sizeof(int64)), (int)size)); memcpy(newaptr, ptr, min<int>((int)(*aptr - sizeof(int64)), (int)size));
UPP_SSL_alloc += newalloc - *aptr; UPP_SSL_alloc += newalloc - *aptr;
LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << newalloc << ") -> " LLOG("UPP_SSL_REALLOC(" << ptr << ", " << (int64)size << ", alloc " << newalloc
<< FormatIntHex(newaptr) << ", total = " << UPP_SSL_alloc); << ", " << file << " " << line
<< ") -> " << newaptr << ", total = " << UPP_SSL_alloc << ", thread: " << Thread::GetCurrentId());
MemoryFree(aptr); MemoryFree(aptr);
return newaptr; return newaptr;
} }
@ -74,7 +82,7 @@ void TcpSocketInit();
INITIALIZER(SSL) INITIALIZER(SSL)
{ {
MemoryIgnoreLeaksBlock __; MemoryIgnoreLeaksBlock __;
LLOG("SSL init"); LLOG("SslInit");
TcpSocketInit(); TcpSocketInit();
CRYPTO_set_mem_functions(SslAlloc, SslRealloc, SslFree); CRYPTO_set_mem_functions(SslAlloc, SslRealloc, SslFree);
SSL_library_init(); SSL_library_init();

View file

@ -167,7 +167,7 @@ Speller *sGetSpeller(int lang)
while(!user.IsEof()) { while(!user.IsEof()) {
String s = user.GetLine(); String s = user.GetLine();
if(!s.IsEmpty()) if(!s.IsEmpty())
f.user.Add(FromUtf8(s)); f.user.Add(ToUtf32(s));
} }
if(in.Get() != 255) if(in.Get() != 255)
f.SetOld(LoadFile(path)); f.SetOld(LoadFile(path));

View file

@ -138,7 +138,7 @@ Vector<WString> Split(int maxcount, const wchar *s, const wchar *text, bool igno
{ {
SplitDelimWText delim; SplitDelimWText delim;
delim.ds = text; delim.ds = text;
delim.l = wstrlen(text); delim.l = strlen__(text);
return delim.l ? SplitGeneric<WString>(maxcount, delim, s, ignoreempty) : Vector<WString>(); return delim.l ? SplitGeneric<WString>(maxcount, delim, s, ignoreempty) : Vector<WString>();
} }

View file

@ -2,11 +2,20 @@
namespace Upp { namespace Upp {
int wstrlen(const wchar *s) int strlen16(const char16 *s)
{ {
const wchar *q = s; if(!s) return 0;
while(*q) q++; const char16 *s0 = s;
return (int)(q - 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) unsigned ctoi(int c)
@ -32,7 +41,7 @@ int CharFilterAscii128(int c)
int CharFilterUnicode(int c) int CharFilterUnicode(int c)
{ {
return c >= 32 && c < 65536 ? c : 0; return c >= 32 && c < 0x10FFFF ? c : 0;
} }
int CharFilterDigit(int c) int CharFilterDigit(int c)

View file

@ -629,36 +629,29 @@ Stream& Stream::operator/(String& s) {
return *this; return *this;
} }
Stream& Stream::operator%(WString& s) { Stream& Stream::operator%(WString& s)
{ // we do not support BE here anymore
if(IsError()) return *this; if(IsError()) return *this;
if(IsLoading()) { if(IsLoading()) {
dword len; dword len = Get();
Pack(len); if(len == 0xff)
if(len < 256 * 1024) { len = Get32le();
WStringBuffer sb(len); String h = GetAll(len * sizeof(char16));
SerializeRaw((byte*)~sb, len * sizeof(wchar)); if(h.IsVoid())
s = sb; LoadError();
} else
else { s = ToUtf32((const char16 *)~h, len);
String h = GetAll(len * sizeof(wchar));
if(h.IsVoid())
LoadError();
else {
WStringBuffer sb(len);
memcpy8(~sb, ~h, len * sizeof(wchar));
s = sb;
}
}
} }
else { else {
dword len = s.GetLength(); Vector<char16> x = ToUtf16(s);
dword len = x.GetCount();
if(len < 0xff) if(len < 0xff)
Put(len); Put(len);
else { else {
Put(0xff); Put(0xff);
Put32le(len); Put32le(len);
} }
SerializeRaw((byte*)~s, len * sizeof(wchar)); SerializeRaw((byte*)x.begin(), len * sizeof(char16));
} }
return *this; return *this;
} }
@ -667,7 +660,7 @@ Stream& Stream::operator/(WString& s) {
if(IsError()) return *this; if(IsError()) return *this;
String h = ToUtf8(s); String h = ToUtf8(s);
*this / h; *this / h;
s = FromUtf8(h); s = ToUtf32(h);
return *this; return *this;
} }
@ -1082,32 +1075,28 @@ Stream& NilStream()
return Single<NilStreamClass>(); return Single<NilStreamClass>();
} }
#ifdef PLATFORM_WIN32
bool IsCoutUTF8;
#endif
void CoutUTF8()
{
#ifdef PLATFORM_WIN32
IsCoutUTF8 = true;
SetConsoleOutputCP(65001);
#endif
}
#ifndef PLATFORM_WINCE #ifndef PLATFORM_WINCE
class CoutStream : public Stream { class CoutStream : public Stream {
#ifdef PLATFORM_WIN32
String buffer; 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) { void Put0(int w) {
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
buffer.Cat(w); buffer.Cat(w);
if(CheckUtf8(buffer)) { // TODO: Use W api if(CheckUtf8(buffer) || buffer.GetCount() > 8)
String ws = ToSystemCharset(buffer, GetConsoleOutputCP()); Flush();
static HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
dword dummy;
WriteFile(h, ~ws, ws.GetCount(), &dummy, NULL);
buffer.Clear();
}
#else #else
putchar(w); putchar(w);
#endif #endif

View file

@ -178,10 +178,6 @@ public:
void PutLine(const char *s); void PutLine(const char *s);
void PutLine(const String& 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); void Put(Stream& s, int64 size = INT64_MAX, dword click = 4096);
// Stream as serialization streamer // Stream as serialization streamer
@ -253,6 +249,9 @@ public:
void PutIL(int c) { Put32le(c); } void PutIL(int c) { Put32le(c); }
void PutMW(int c) { Put16be(c); } void PutMW(int c) { Put16be(c); }
void PutML(int c) { Put32be(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 #endif
private: // No copy private: // No copy
Stream(const Stream& s); Stream(const Stream& s);

View file

@ -216,9 +216,12 @@ WString String::ToWString() const
int String::GetCharCount() 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) String::String(StringBuffer& b)
{ {
Zero(); Zero();
@ -354,26 +357,14 @@ struct StringICompare__
StringICompare__(int e) : encoding(e) {} 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(); return CompareNoCase(ToUtf32(a), ToUtf32(b));
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
} }
int CompareNoCase(const String& a, const char *b, byte encoding) int CompareNoCase(const String& a, const char *b)
{ {
if(encoding == CHARSET_DEFAULT) encoding = GetDefaultCharset(); return CompareNoCase(ToUtf32(a), ToUtf32(b, (int)strlen(b)));
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
} }
} }

View file

@ -1,6 +1,8 @@
class Nuller; 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 #ifdef PLATFORM_POSIX
inline int stricmp(const char *a, const char *b) { return strcasecmp(a, b); } 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); } inline int strnicmp(const char *a, const char *b, int n) { return _strnicmp(a, b, n); }
#endif #endif
force_inline int strlen__(const char *s) { return s ? (int)strlen(s) : 0; } force_inline int strlen__(const char *s) { return strlen8(s); }
inline int strlen__(const wchar *s) { return strlen32(s); }
inline int strlen__(const wchar *s) { return s ? (int)wstrlen(s) : 0; }
inline int cmpval__(char x) { return (byte)x; } 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 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 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(int chr, int count) { String0::Zero(); Cat(chr, count); }
String(StringBuffer& b); String(StringBuffer& b);
String(char16 *s);
String(wchar *s);
WString ToWString() const; WString ToWString() const;
const String& ToString() const { return *this; } const String& ToString() const { return *this; }
@ -618,12 +623,12 @@ inline String AsString(const String& s) { return s; }
template<> template<>
inline hash_t GetHashValue(const String& s) { return s.GetHashValue(); } 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 String& b);
int CompareNoCase(const String& a, const char *b, byte encoding = 0); int CompareNoCase(const String& a, const char *b);
inline inline
int CompareNoCase(const char *a, const String& b, byte encoding = 0) { int CompareNoCase(const char *a, const String& b) {
return -CompareNoCase(b, a, encoding); return -CompareNoCase(b, a);
} }
String TrimLeft(const String& s); String TrimLeft(const String& s);
@ -774,8 +779,8 @@ public:
int GetAlloc() const { return alloc; } int GetAlloc() const { return alloc; }
hash_t GetHashValue() const { return memhash(ptr, length * sizeof(wchar)); } 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 WString0& s) const { return s.length == length && memeq_t(ptr, s.ptr, length); }
bool IsEqual(const wchar *s) const { int l = wstrlen(s); return l == GetCount() && memeq16(begin(), s, l); } bool IsEqual(const wchar *s) const { int l = strlen__(s); return l == GetCount() && memeq_t(begin(), s, l); }
int Compare(const WString0& s) const; int Compare(const WString0& s) const;
void Remove(int pos, int count = 1); void Remove(int pos, int count = 1);
@ -835,6 +840,8 @@ public:
WString(const char *s, int n); WString(const char *s, int n);
WString(const char *s, const char *lim); WString(const char *s, const char *lim);
WString(const char16 *s);
static WString GetVoid(); static WString GetVoid();
bool IsVoid() const { return alloc < 0; } bool IsVoid() const { return alloc < 0; }
@ -845,13 +852,13 @@ public:
#ifndef _HAVE_NO_STDWSTRING #ifndef _HAVE_NO_STDWSTRING
WString(const std::wstring& s); WString(const std::wstring& s);
operator std::wstring() const; operator std::wstring() const { return ToStd(); }
std::wstring ToStd() const { return std::wstring(Begin(), End()); } std::wstring ToStd() const;
#endif #endif
}; };
#ifndef _HAVE_NO_STDWSTRING #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 #endif
class WStringBuffer : NoCopy { class WStringBuffer : NoCopy {
@ -885,7 +892,7 @@ public:
void SetCount(int l) { SetLength(l); } void SetCount(int l) { SetLength(l); }
int GetLength() const { return (int)(pend - pbegin); } int GetLength() const { return (int)(pend - pbegin); }
int GetCount() const { return GetLength(); } int GetCount() const { return GetLength(); }
void Strlen() { SetLength(wstrlen(pbegin)); } void Strlen() { SetLength(strlen__(pbegin)); }
void Clear() { Free(); Zero(); } void Clear() { Free(); Zero(); }
void Reserve(int r) { int l = GetLength(); SetLength(l + r); SetLength(l); } 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(int c, int count);
void Cat(const wchar *s, int l); 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, 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 WString& s) { Cat(s, s.GetLength()); }
void Cat(const char *s) { Cat(WString(s)); } void Cat(const char *s) { Cat(WString(s)); }

View file

@ -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 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); int q = t_find<sizeof(wchar)>((const char *)text, sizeof(wchar) * len, (const char *)needle, sizeof(wchar) * nlen, sizeof(wchar) * from);
return q < 0 ? q : q / 2; return q < 0 ? q : q / sizeof(wchar);
} }
#else #else

View file

@ -76,12 +76,12 @@ struct UnicodeInfo {
} }
}; };
Index<dword> composed; Index<wchar> composed;
Index<String> decomposed; // using String as the vessel for dwords Index<WString> decomposed;
int canonical_count; int canonical_count;
Index<dword> lower; Index<wchar> lower;
Index<dword> upper; Index<wchar> upper;
CharBits rtl; CharBits rtl;
CharBits letter; CharBits letter;
CharBits islower; CharBits islower;
@ -130,8 +130,8 @@ UnicodeInfo::UnicodeInfo()
count += data[1]; count += data[1];
for(int i = 0; i < count; i++) { for(int i = 0; i < count; i++) {
composed.Add(data[i + 2]); composed.Add(data[i + 2]);
String h; WString h;
auto put = [&](dword c) { if(c) h.Cat((char *)&c, 4); }; auto put = [&](dword c) { if(c) h.Cat(c); };
put(data[i + count + 2]); put(data[i + count + 2]);
put(data[i + 2 * count + 2]); put(data[i + 2 * count + 2]);
put(data[i + 3 * count + 2]); put(data[i + 3 * count + 2]);
@ -143,11 +143,11 @@ UnicodeInfo::UnicodeInfo()
int offset = 4 * count + 2; int offset = 4 * count + 2;
while(data[offset]) { while(data[offset]) {
dword code = data[offset++]; wchar code = data[offset++];
int ii = composed.Find(code); int ii = composed.Find(code);
String h = decomposed[ii]; WString h = decomposed[ii];
while(data[offset]) while(data[offset])
h.Cat((char *)&data[offset++], 4); h.Cat(data[offset++]);
decomposed.Set(ii, h); decomposed.Set(ii, h);
offset++; offset++;
} }
@ -169,54 +169,54 @@ UnicodeInfo::UnicodeInfo()
Load(data, ismark, offset); Load(data, ismark, offset);
} }
static int sUnicodeDecompose(dword codepoint, dword *t, Vector<dword> *r, bool only_canonical) static int sUnicodeDecompose(wchar codepoint, wchar *t, WString *r, bool only_canonical)
{ // TODO: Add hangul support { // TODO: Add hangul support
const UnicodeInfo& f = Single<UnicodeInfo>(); const UnicodeInfo& f = Single<UnicodeInfo>();
int q = f.composed.Find(codepoint); int q = f.composed.Find(codepoint);
if(q >= 0 && (!only_canonical || q < f.canonical_count)) { if(q >= 0 && (!only_canonical || q < f.canonical_count)) {
String s = f.decomposed[q]; const WString& s = f.decomposed[q];
if(r) if(r)
r->SetCount(s.GetCount() >> 2); *r = s;
int i; if(t)
for(i = 0; 4 * i < s.GetCount(); i++) memcpy(t, s, sizeof(wchar) * s.GetCount());
(r ? (*r)[i] : t[i]) = ((const dword *)~s)[i]; return s.GetCount();
return i;
} }
return 0; 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); return sUnicodeDecompose(codepoint, t, NULL, only_canonical);
} }
Vector<dword> UnicodeDecompose(dword codepoint, bool only_canonical) WString UnicodeDecompose(wchar codepoint, bool only_canonical)
{ {
Vector<dword> r; WString r;
sUnicodeDecompose(codepoint, NULL, &r, only_canonical); sUnicodeDecompose(codepoint, NULL, &r, only_canonical);
return r; return r;
} }
dword UnicodeCompose(const dword *t, int count) wchar UnicodeCompose(const WString& s)
{ {
int count = s.GetCount();
if(count < 1 || count > 3) if(count < 1 || count > 3)
return 0; return 0;
if(count == 1) if(count == 1)
return t[0]; return *s;
String s((byte *)t, sizeof(dword) * count);
const UnicodeInfo& f = Single<UnicodeInfo>(); const UnicodeInfo& f = Single<UnicodeInfo>();
int q = f.decomposed.Find(s); int q = f.decomposed.Find(s);
return q >= 0 && q < f.canonical_count ? f.composed[q] : 0; return q >= 0 && q < f.canonical_count ? f.composed[q] : 0;
} }
dword ToUpperRest_(dword c) wchar ToUpperRest_(wchar c)
{ {
const UnicodeInfo& f = Single<UnicodeInfo>(); const UnicodeInfo& f = Single<UnicodeInfo>();
int q = f.lower.Find(c); int q = f.lower.Find(c);
return q >= 0 ? f.upper[q] : 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) if(c == 0x1e9e) // Capital sharp S -> small sharp S (but not reverse direction)
return 0xdf; return 0xdf;
@ -233,7 +233,7 @@ dword ToLowerRest_(dword c)
return q >= 0 ? f.lower[q] : c; return q >= 0 ? f.lower[q] : c;
} }
char ToAsciiRest_(dword c) char ToAsciiRest_(wchar c)
{ {
const UnicodeInfo& f = Single<UnicodeInfo>(); const UnicodeInfo& f = Single<UnicodeInfo>();
int q = f.composed.Find(c); int q = f.composed.Find(c);
@ -243,27 +243,27 @@ char ToAsciiRest_(dword c)
return ch >= ' ' && ch < 128 ? ch : ' '; return ch >= ' ' && ch < 128 ? ch : ' ';
} }
bool IsRTL_(dword c) bool IsRTL_(wchar c)
{ {
return Single<UnicodeInfo>().rtl.Get(c); return Single<UnicodeInfo>().rtl.Get(c);
} }
bool IsLetter_(dword c) bool IsLetter_(wchar c)
{ {
return Single<UnicodeInfo>().letter.Get(c); return Single<UnicodeInfo>().letter.Get(c);
} }
bool IsLower_(dword c) bool IsLower_(wchar c)
{ {
return c != (dword)ToUpper((int)c) || Single<UnicodeInfo>().islower.Get(c); return c != (dword)ToUpper((int)c) || Single<UnicodeInfo>().islower.Get(c);
} }
bool IsUpper_(dword c) bool IsUpper_(wchar c)
{ {
return c != (dword)ToLower((int)c) || Single<UnicodeInfo>().isupper.Get(c); return c != (dword)ToLower((int)c) || Single<UnicodeInfo>().isupper.Get(c);
} }
bool IsMark_(dword c) bool IsMark_(wchar c)
{ {
return Single<UnicodeInfo>().ismark.Get(c); return Single<UnicodeInfo>().ismark.Get(c);
} }

View file

@ -2,138 +2,142 @@
namespace Upp { 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) bool CheckUtf8(const char *s, int len)
{ {
return FromUtf8_([](const byte *, dword){}, s, len); return FromUtf8_([](wchar) {}, 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;
} }
int Utf8Len(const wchar *s, int len) int Utf8Len(const wchar *s, int len)
{ {
int rlen = 0; 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; return rlen;
} }
void ToUtf8(char *t, const wchar *s, int len) 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) String ToUtf8(const wchar *s, int len)
{ {
StringBuffer r; String r;
r.Reserve(len); for(const wchar *lim = s + len; s < lim; s++)
FromUtf16_([&](const wchar *, dword code) { ToUtf8_([&](char c) { r.Cat(c); }, code); }, s, len); ToUtf8_([&](char c) { r.Cat(c); }, *s);
return String(r); return r;
} }
int Utf16Len(const dword *s, int len) int Utf8Len(const char16 *s, int len)
{ {
int rlen = 0; int rlen = 0;
for(const dword *lim = s + len; s < lim; s++) FromUtf16_([&](wchar code) { ToUtf8_([&](char c) { rlen++; }, code); }, s, len);
ToUtf16_([&](wchar) { rlen++; }, *s);
return rlen; 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++) FromUtf16_([&](wchar code) { ToUtf8_([&](char c) { *t++ = c; }, code); }, s, len);
ToUtf16_([&](wchar c) { *t++ = c; }, *s);
} }
WString ToUtf16(const dword *s, int len) String ToUtf8(const char16 *s, int len)
{ {
WStringBuffer r; StringBuffer r;
r.Reserve(len); r.Reserve(len);
for(const dword *lim = s + len; s < lim; s++) FromUtf16_([&](wchar code) { ToUtf8_([&](char c) { r.Cat(c); }, code); }, s, len);
ToUtf16_([&](wchar c) { r.Cat(c); }, *s); return String(r);
return WString(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<char16> ToUtf16(const wchar *s, int len)
{
Vector<char16> 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 Utf16Len(const char *s, int len)
{ {
int rlen = 0; 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; 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<char16> ToUtf16(const char *s, int len)
{ {
WStringBuffer r; Vector<char16> r;
FromUtf8_([&](const byte *, dword code) { ToUtf16_([&](wchar c) { r.Cat(c); }, code); }, s, len); FromUtf8_([&](wchar code) {
return WString(r); ToUtf16_([&](char16 c) { r.Add(c); } , code);
}, s, len);
return r;
} }
int Utf32Len(const char *s, int len) int Utf32Len(const char *s, int len)
{ {
int rlen = 0; int rlen = 0;
FromUtf8_([&](const byte *, dword) { rlen++; }, s, len); FromUtf8_([&](wchar) { rlen++; }, s, len);
return rlen; 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<dword> ToUtf32(const char *s, int len) WString ToUtf32(const char *s, int len)
{ {
Vector<dword> r; WStringBuffer r;
FromUtf8_([&](const byte *, dword c) { r.Add(c); }, s, len); FromUtf8_([&](wchar c) { r.Cat(c); }, s, len);
return r; return WString(r);
} }
int Utf32Len(const wchar *s, int len) int Utf32Len(const char16 *s, int len)
{ {
int rlen = 0; int rlen = 0;
FromUtf16_([&](const wchar *, dword) { rlen++; }, s, len); FromUtf16_([&](wchar) { rlen++; }, s, len);
return rlen; 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<dword> ToUtf32(const wchar *s, int len) WString ToUtf32(const char16 *s, int len)
{ {
Vector<dword> r; WStringBuffer r;
FromUtf16_([&](const wchar *, dword c) { r.Add(c); }, s, len); r.Reserve(len);
return r; FromUtf16_([&](wchar c) { r.Cat(c); }, s, len);
return WString(r);
} }
String Utf8ToAscii(const String& src) String Utf8ToAscii(const String& src)

View file

@ -1,5 +1,5 @@
template <class Target> template <class Target>
force_inline bool ToUtf8_(Target t, dword codepoint) force_inline bool ToUtf8_(Target t, wchar codepoint)
{ {
if(codepoint < 0x80) if(codepoint < 0x80)
t((char)codepoint); t((char)codepoint);
@ -29,7 +29,7 @@ force_inline bool ToUtf8_(Target t, dword codepoint)
return true; 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 *s = (const byte *)_s;
const byte *lim = (const byte *)_lim; const byte *lim = (const byte *)_lim;
@ -41,14 +41,14 @@ force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok)
else else
if(code >= 0xC2) { if(code >= 0xC2) {
dword c; dword c;
if(code < 0xE0 && s + 1 < lim && if(code < 0xE0 && (nolim || s + 1 < lim) &&
s[1] >= 0x80 && s[1] < 0xc0 && s[1] >= 0x80 && s[1] < 0xc0 &&
(c = ((code - 0xC0) << 6) + s[1] - 0x80) >= 0x80 && c < 0x800) { (c = ((code - 0xC0) << 6) + s[1] - 0x80) >= 0x80 && c < 0x800) {
_s += 2; _s += 2;
return c; return c;
} }
else 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 && 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 = ((code - 0xE0) << 12) + ((s[1] - 0x80) << 6) + s[2] - 0x80) >= 0x800 &&
!(c >= 0xEE00 && c <= 0xEEFF)) { !(c >= 0xEE00 && c <= 0xEEFF)) {
@ -56,7 +56,7 @@ force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok)
return c; return c;
} }
else 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 && 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 = ((code - 0xF0) << 18) + ((s[1] - 0x80) << 12) + ((s[2] - 0x80) << 6) + s[3] - 0x80) >= 0x10000 &&
c < 0x110000) { c < 0x110000) {
@ -69,13 +69,23 @@ force_inline dword FetchUtf8(const char *&_s, const char *_lim, bool& ok)
return 0xEE00 + code; // ERROR ESCAPE 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 <class Target> template <class Target>
force_inline bool FromUtf8_(Target t, const char *s, size_t len) force_inline bool FromUtf8_(Target t, const char *s, size_t len)
{ {
bool ok = true; bool ok = true;
const char *lim = s + len; const char *lim = s + len;
while(s < lim) while(s < lim)
t((const byte *)s, FetchUtf8(s, lim, ok)); t(FetchUtf8(s, lim, ok));
return ok; return ok;
} }
@ -83,36 +93,36 @@ template <class Target>
force_inline bool ToUtf16_(Target t, size_t codepoint) force_inline bool ToUtf16_(Target t, size_t codepoint)
{ {
if(codepoint < 0x10000) if(codepoint < 0x10000)
t((wchar)codepoint); t((char16)codepoint);
else else
if(codepoint < 0x110000) { if(codepoint < 0x110000) {
codepoint -= 0x10000; codepoint -= 0x10000;
t(wchar(0xD800 + (0x3ff & (codepoint >> 10)))); t(char16(0xD800 + (0x3ff & (codepoint >> 10))));
t(wchar(0xDC00 + (0x3ff & codepoint))); t(char16(0xDC00 + (0x3ff & codepoint)));
} }
else else
return false; return false;
return true; 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 ? 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 <class Target> template <class Target>
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) { while(s < lim) {
dword c = ReadSurrogatePair(s, lim); wchar c = ReadSurrogatePair(s, lim);
if(c) { if(c) {
t(s, c); t(c);
s += 2; s += 2;
} }
else { else {
t(s, *s); t(*s);
s++; s++;
} }
} }

View file

@ -577,25 +577,13 @@ int ChNoInvalid(int c)
return c == DEFAULTCHAR ? '_' : 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 #ifdef PLATFORM_WIN32
String ToSystemCharset(const String& src, int cp) String ToSystemCharset(const String& src, int cp)
{ {
WString s = src.ToWString(); Vector<char16> s = ToUtf16(src);
int l = s.GetLength() * 5; int l = s.GetCount() * 8;
StringBuffer b(l); 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) if(q <= 0)
return src; return src;
b.SetCount(q); b.SetCount(q);
@ -609,12 +597,11 @@ String ToSystemCharset(const String& src)
String FromWin32Charset(const String& src, int cp) String FromWin32Charset(const String& src, int cp)
{ {
WStringBuffer b(src.GetLength()); Buffer<char16> b(src.GetLength());
int q = MultiByteToWideChar(cp, MB_PRECOMPOSED, ~src, src.GetLength(), (WCHAR*)~b, src.GetLength()); int q = MultiByteToWideChar(cp, MB_PRECOMPOSED, ~src, src.GetLength(), b, src.GetLength());
if(q <= 0) if(q <= 0)
return src; return src;
b.SetCount(q); return ToUtf8(b, q);
return WString(b).ToString();
} }
String FromOEMCharset(const String& src) String FromOEMCharset(const String& src)
@ -627,16 +614,6 @@ String FromSystemCharset(const String& src)
return FromWin32Charset(src, CP_ACP); return FromWin32Charset(src, CP_ACP);
} }
WString ToSystemCharsetW(const char *src)
{
return String(src).ToWString();
}
String FromSystemCharsetW(const wchar *src)
{
return WString(src).ToString();
}
#else #else
String ToSystemCharset(const String& src) 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; return IsMainRunning() ? Filter(ToCharset(CHARSET_DEFAULT, src, GetLNGCharset(GetSystemLNG())), ChNoInvalid) : src;
} }
#endif #endif
#endif
Vector<char16> ToSystemCharsetW(const WString& src)
{
Vector<char16> h = ToUtf16(src);
h.Add(0);
return h;
}
Vector<char16> ToSystemCharsetW(const String& src)
{
Vector<char16> h = ToUtf16(src);
h.Add(0);
return h;
}
Vector<char16> ToSystemCharsetW(const wchar *src)
{
Vector<char16> h = ToUtf16(src);
h.Add(0);
return h;
}
Vector<char16> ToSystemCharsetW(const char *src)
{
Vector<char16> h = ToUtf16(src);
h.Add(0);
return h;
}
String FromSystemCharsetW(const char16 *src)
{
return ToUtf8(src);
}
static StaticMutex sGCfgLock; static StaticMutex sGCfgLock;

View file

@ -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 char *s, int len) { return HexDecode(s, s + len); }
inline String HexDecode(const String& s) { return HexDecode(~s, s.GetCount()); } 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, int cp);
String ToSystemCharset(const String& src); String ToSystemCharset(const String& src);
String FromWin32Charset(const String& src, int cp); String FromWin32Charset(const String& src, int cp);
String FromSystemCharset(const String& src); String FromSystemCharset(const String& src);
WString ToSystemCharsetW(const char *src);
String FromSystemCharsetW(const wchar *src); Vector<char16> ToSystemCharsetW(const WString& src);
#endif Vector<char16> ToSystemCharsetW(const String& src);
Vector<char16> ToSystemCharsetW(const wchar *src);
Vector<char16> ToSystemCharsetW(const char *src);
String FromSystemCharsetW(const char16 *src);
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
String FromOEMCharset(const String& src); String FromOEMCharset(const String& src);

View file

@ -289,21 +289,13 @@ bool ValueMap::Data::IsNull() const {
} }
void ValueMap::Data::Serialize(Stream& s) { void ValueMap::Data::Serialize(Stream& s) {
#if !defined(_MSC_VER) || _MSC_VER > 1310
s % key % value; s % key % value;
#else
throw 0;
#endif
} }
void ValueMap::Data::Xmlize(XmlIO& xio) void ValueMap::Data::Xmlize(XmlIO& xio)
{ {
#if !defined(_MSC_VER) || _MSC_VER > 1310
Upp::Xmlize(xio, key); Upp::Xmlize(xio, key);
Upp::Xmlize(xio, value); Upp::Xmlize(xio, value);
#else
throw 0;
#endif
} }
void ValueMap::Data::Jsonize(JsonIO& jio) void ValueMap::Data::Jsonize(JsonIO& jio)

View file

@ -6,13 +6,13 @@ wchar *WString0::Alloc(int& count)
{ {
if(count <= SMALL) { if(count <= SMALL) {
count = SMALL; count = SMALL;
wchar *p = (wchar *)MemoryAlloc48(); wchar *p = (wchar *)MemoryAlloc((SMALL + 1) * sizeof(wchar));
return p; return p;
} }
size_t sz = sizeof(Atomic) + ((size_t)count + 1) * sizeof(wchar); size_t sz = sizeof(Atomic) + ((size_t)count + 1) * sizeof(wchar);
Atomic *rc = (Atomic *)MemoryAllocSz(sz); Atomic *rc = (Atomic *)MemoryAllocSz(sz);
if(count != INT_MAX) if(count != INT_MAX)
count = int(((sz - sizeof(Atomic)) >> 1) - 1); count = int(((sz - sizeof(Atomic)) / sizeof(wchar)) - 1);
*rc = 1; *rc = 1;
return (wchar *)(rc + 1); return (wchar *)(rc + 1);
} }
@ -26,7 +26,7 @@ void WString0::Free()
MemoryFree(&rc); MemoryFree(&rc);
} }
else else
MemoryFree48(ptr); MemoryFree(ptr);
} }
} }
@ -94,15 +94,8 @@ void WString0::Set0(const WString0& src)
AtomicInc(Rc()); AtomicInc(Rc());
} }
else { else {
ptr = (wchar *)MemoryAlloc48(); ptr = (wchar *)MemoryAlloc((SMALL + 1) * sizeof(wchar));
qword *t = (qword *)ptr; memcpy(ptr, src.ptr, sizeof(wchar) * (SMALL + 1));
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];
} }
Dsyn(); Dsyn();
} }
@ -224,6 +217,11 @@ WString::WString(const char *s) {
*this = ToUnicode(s, s ? (int)strlen(s) : 0, CHARSET_DEFAULT); *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) { WString::WString(const char *s, int n) {
Zero(); Zero();
*this = ToUnicode(s, n, CHARSET_DEFAULT); *this = ToUnicode(s, n, CHARSET_DEFAULT);
@ -249,30 +247,26 @@ WString WString::GetVoid()
} }
#ifndef _HAVE_NO_STDWSTRING #ifndef _HAVE_NO_STDWSTRING
static_assert(sizeof(wchar_t) == 4 || sizeof(wchar_t) == 2, "Invalid wchar_t size");
WString::WString(const std::wstring& s) WString::WString(const std::wstring& s)
{ {
if(sizeof(std::wstring::value_type) == sizeof(wchar)) { WString0::Zero();
WString0::Set0((wchar *)s.c_str(), (int)s.length()); if(sizeof(wchar_t) == 4)
} *this = WString((const wchar *)s.c_str(), (int)s.size());
else { if(sizeof(wchar_t) == 2)
WString0::Zero(); *this = ToUtf32((char16 *)s.c_str(), (int)s.size());
std::wstring::const_iterator i = s.begin();
while(i < s.end())
Cat(*i++);
}
} }
WString::operator std::wstring() const std::wstring WString::ToStd() const
{ {
if(sizeof(std::wstring::value_type) == sizeof(wchar)) if(sizeof(wchar_t) == 4) {
return std::wstring((std::wstring::value_type *)Begin(), const wchar *s = begin();
(std::wstring::value_type *)End()); return std::wstring((const wchar_t *)begin(), GetCount());
else { }
std::wstring r; if(sizeof(wchar_t) == 2) {
const wchar *s = Begin(); Vector<char16> h = ToUtf16(*this);
while(s < End()) return std::wstring((const wchar_t *)h.begin(), h.GetCount());
r += *s++;
return r;
} }
} }
#endif #endif
@ -286,14 +280,14 @@ void WStringBuffer::Zero()
wchar *WStringBuffer::Alloc(int count, int& alloc) wchar *WStringBuffer::Alloc(int count, int& alloc)
{ {
if(count <= 23) { if(count <= 23) {
wchar *s = (wchar *)MemoryAlloc48(); wchar *s = (wchar *)MemoryAlloc(24 * sizeof(wchar));
alloc = WString0::SMALL; alloc = WString0::SMALL;
return s; return s;
} }
else { else {
size_t sz = sizeof(Atomic) + ((size_t)count + 1) * sizeof(wchar); size_t sz = sizeof(Atomic) + ((size_t)count + 1) * sizeof(wchar);
Atomic *rc = (Atomic *)MemoryAlloc(sz); 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); ASSERT(alloc >= 0);
*rc = 1; *rc = 1;
return (wchar *)(rc + 1); return (wchar *)(rc + 1);
@ -304,7 +298,7 @@ void WStringBuffer::Free()
{ {
int all = (int)(limit - pbegin); int all = (int)(limit - pbegin);
if(all == WString0::SMALL) if(all == WString0::SMALL)
MemoryFree48(pbegin); MemoryFree(pbegin);
if(all > WString0::SMALL) if(all > WString0::SMALL)
MemoryFree((Atomic *)pbegin - 1); MemoryFree((Atomic *)pbegin - 1);
} }
@ -357,7 +351,7 @@ void WStringBuffer::Cat(int c, int l)
{ {
if(pend + l > limit) if(pend + l > limit)
Expand(max(GetLength(), l) + GetLength(), NULL, l); Expand(max(GetLength(), l) + GetLength(), NULL, l);
memset16(pend, c, l); memset32(pend, c, l);
pend += l; pend += l;
} }
@ -408,9 +402,9 @@ int CompareNoCase(const WString& a, const WString& b)
int CompareNoCase(const WString& a, const wchar *b) int CompareNoCase(const WString& a, const wchar *b)
{ {
#ifdef DEPRECATED #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 #else
return CompareRanges(a, SubRange(b, b + wstrlen(b)), WStringICompare__()); return CompareRanges(a, SubRange(b, b + strlen__(b)), WStringICompare__());
#endif #endif
} }

View file

@ -158,14 +158,14 @@ void DeleteWinReg(const String& key, HKEY base, dword wow) {
} }
String GetSystemDirectory() { String GetSystemDirectory() {
char temp[MAX_PATH]; WCHAR temp[MAX_PATH];
*temp = 0; *temp = 0;
::GetSystemDirectory(temp, sizeof(temp)); ::GetSystemDirectoryW(temp, sizeof(temp));
return FromSystemCharset(temp); return FromSystemCharsetW(temp);
} }
String GetWindowsDirectory() { String GetWindowsDirectory() {
wchar temp[MAX_PATH]; WCHAR temp[MAX_PATH];
*temp = 0; *temp = 0;
GetWindowsDirectoryW(temp, sizeof(temp)); GetWindowsDirectoryW(temp, sizeof(temp));
return FromSystemCharsetW(temp); return FromSystemCharsetW(temp);
@ -179,7 +179,7 @@ void *GetDllFn(const char *dll, const char *fn)
} }
String GetModuleFileName(HINSTANCE instance) { String GetModuleFileName(HINSTANCE instance) {
wchar h[_MAX_PATH]; WCHAR h[_MAX_PATH];
GetModuleFileNameW(instance, h, _MAX_PATH); GetModuleFileNameW(instance, h, _MAX_PATH);
return FromSystemCharsetW(h); return FromSystemCharsetW(h);
} }

View file

@ -31,12 +31,12 @@ void Xmlize(XmlIO& xml, WString& var)
h = ToUtf8(var); h = ToUtf8(var);
Xmlize(xml, h); Xmlize(xml, h);
if(xml.IsLoading()) if(xml.IsLoading())
var = FromUtf8(h); var = ToUtf32(h);
} }
template<> void XmlAttrLoad(WString& var, const String& text) template<> void XmlAttrLoad(WString& var, const String& text)
{ {
var = FromUtf8(text); var = ToUtf32(text);
} }
template<> String XmlAttrStore(const WString& var) template<> String XmlAttrStore(const WString& var)

View file

@ -185,4 +185,6 @@
#define CPP_11 #define CPP_11
#endif #endif
#define WCHAR32 1 // this version of U++ has 32 bit wchar
#endif #endif

View file

@ -125,11 +125,37 @@ void Heap::DblCheck(Page *p)
while(p != l); 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; 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) { 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); DbgFreeCheckK(l, k);
l = l->next; l = l->next;
n++; n++;
} }
@ -167,7 +193,7 @@ void Heap::Check() {
break; break;
p = p->next; p = p->next;
} }
CheckFree(cache[i], i); CheckFree(cache[i], i, false);
} }
DLink *l = large->next; DLink *l = large->next;

View file

@ -174,8 +174,6 @@ size_t GetMemoryBlockSize(void *ptr)
void *MemoryAlloc32() { return MemoryAlloc(32); } void *MemoryAlloc32() { return MemoryAlloc(32); }
void MemoryFree32(void *ptr) { return MemoryFree(ptr); } void MemoryFree32(void *ptr) { return MemoryFree(ptr); }
void *MemoryAlloc48() { return MemoryAlloc(48); }
void MemoryFree48(void *ptr) { return MemoryFree(ptr); }
void MemoryCheckDebug() void MemoryCheckDebug()
{ {

View file

@ -220,19 +220,21 @@ bool Heap::TryRealloc(void *ptr, size_t& newsize)
} }
} }
// TODO: When small block fits, we could still return true
return false; return false;
} }
size_t Heap::LGetBlockSize(void *ptr) { size_t Heap::LGetBlockSize(void *ptr) {
LBlkHeader *h = (LBlkHeader *)ptr - 1; BlkPrefix *h = (BlkPrefix *)ptr - 1;
if(h->heap == NULL) { // huge block if(h->heap == NULL) { // huge block
Mutex::Lock __(mutex); Mutex::Lock __(mutex);
DLink *h = (DLink *)ptr - 1; DLink *hh = (DLink *)h - 1;
return h->size; return hh->size;
} }
return h->GetSize(); return ((int)h->GetSize() * LUNIT) - sizeof(BlkPrefix);
} }
#endif #endif

View file

@ -388,6 +388,8 @@ struct HeapMutexLock {
~HeapMutexLock() { LeaveHeapMutex(); } ~HeapMutexLock() { LeaveHeapMutex(); }
}; };
void MemoryFreeThread();
struct HeapExitThreadGuard { struct HeapExitThreadGuard {
void Used() {} void Used() {}
~HeapExitThreadGuard() { MemoryFreeThread(); } ~HeapExitThreadGuard() { MemoryFreeThread(); }
@ -608,31 +610,6 @@ void MemoryFree32_i(void *ptr)
void MemoryFree32(void *ptr) { MemoryFree32_i(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 #endif
void MemoryFreeThread() void MemoryFreeThread()

View file

@ -58,18 +58,6 @@ This has the same functionality as MemoryFree([%-*@3 ptr]), but
is slightly faster.&] is slightly faster.&]
[s3;%% &] [s3;%% &]
[s4; &] [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]( [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])&] [@(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 [s2;%% Attempts to change the size of block at [%-*@3 ptr] to something

View file

@ -1,5 +1,4 @@
topic "Stream utilities"; topic "Stream utilities";
[2 $$0,0#00000000000000000000000000000000:Default]
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] [i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
[l288;2 $$2,0#27521748481378242620020725143825:desc] [l288;2 $$2,0#27521748481378242620020725143825:desc]
[0 $$3,0#96390100711032703541132217272105:end] [0 $$3,0#96390100711032703541132217272105:end]
@ -9,6 +8,7 @@ topic "Stream utilities";
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param] [l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
[b42;2 $$9,9#13035079074754324216151401829390:normal] [b42;2 $$9,9#13035079074754324216151401829390:normal]
[2 $$0,0#00000000000000000000000000000000:Default]
[{_} [{_}
[ {{10000@(113.42.0) [s0;%% [*@2;4 Stream helpers]]}}&] [ {{10000@(113.42.0) [s0;%% [*@2;4 Stream helpers]]}}&]
[s0;%% &] [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.&] [%-*@3 count] value it copies all data from [%-*@3 src] until EOF.&]
[s3; &] [s3; &]
[s4; &] [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]()&] [s5;:Cout`(`): [_^Stream^ Stream][@(0.0.255) `&]_[* Cout]()&]
[s2;%% Returns special output stream representing console output. [s2;%% Returns special output stream representing console output.
Data written to this stream are displayed as characters in console. 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.&]
[s3; &] [s3; &]
[s4; &] [s4; &]
[s5;:Cerr`(`): [_^Stream^ Stream][@(0.0.255) `&]_[* Cerr]()&] [s5;:Cerr`(`): [_^Stream^ Stream][@(0.0.255) `&]_[* Cerr]()&]

View file

@ -704,37 +704,6 @@ as 0 is considered as NULL pointer too...&]
[s7; [%-*C@3 count]-|Repeat count.&] [s7; [%-*C@3 count]-|Repeat count.&]
[s3; &] [s3; &]
[s4;%- &] [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]()&] [s5;:Stream`:`:PutCrLf`(`):%- [@(0.0.255) void]_[* PutCrLf]()&]
[s2; Writes CR`-LF pair to the stream. &] [s2; Writes CR`-LF pair to the stream. &]
[s3; &] [s3; &]

View file

@ -109,7 +109,8 @@ td`::string][@(0.0.255) `&]_[*@3 s])&]
st]&] st]&]
[s2; Returns a number of characters contained in String. This is [s2; Returns a number of characters contained in String. This is
equal GetCount() if default charset is not UTF`-8, but different 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;%- &] [s3;%- &]
[s4;%- &] [s4;%- &]
[s5;:String`:`:ToWString`(`)const:%- [_^WString^ WString]_[* ToWString]()_[@(0.0.255) const [s5;:String`:`:ToWString`(`)const:%- [_^WString^ WString]_[* ToWString]()_[@(0.0.255) const

View file

@ -411,12 +411,17 @@ void InvalidateFileTimeCache(const String& path)
Time GetFileTimeCached(const String& p) Time GetFileTimeCached(const String& p)
{ {
LTIMING("GetFileTimeCached"); LTIMING("GetFileTimeCached");
Mutex::Lock __(s_PathFileTimeMutex); {
int q = s_PathFileTime.Find(p); Mutex::Lock __(s_PathFileTimeMutex);
if(q >= 0) int q = s_PathFileTime.Find(p);
return s_PathFileTime[q]; if(q >= 0)
return s_PathFileTime[q];
}
Time m = FileGetTime(p); Time m = FileGetTime(p);
s_PathFileTime.Put(p, m); {
Mutex::Lock __(s_PathFileTimeMutex);
s_PathFileTime.Put(p, m);
}
return m; return m;
} }

View file

@ -479,12 +479,7 @@ Image MakeDragImage(const Image& arrow, Image sample);
Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample)
{ {
#ifdef PLATFORM_WIN32 return MakeDragImage(arrow, sample);
if(IsWin2K())
return MakeDragImage(arrow, sample);
else
#endif
return arrow98;
} }
}; };

View file

@ -12,12 +12,7 @@ Image MakeDragImage(const Image& arrow, Image sample);
Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample)
{ {
#ifdef PLATFORM_WIN32 return MakeDragImage(arrow, sample);
if(IsWin2K())
return MakeDragImage(arrow, sample);
else
#endif
return arrow98;
} }
END_UPP_NAMESPACE END_UPP_NAMESPACE

View file

@ -1,5 +1,7 @@
#include "CocoMM.h" #include "CocoMM.h"
#include <dlfcn.h>
#ifdef GUI_COCOA #ifdef GUI_COCOA
#define LLOG(x) #define LLOG(x)
@ -15,9 +17,13 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon
Set(ink); Set(ink);
bool synth; bool synth;
CFRef<CGFontRef> 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<void**>(&CTFontDrawGlyphs) = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
}
Point off = GetOffset(); Point off = GetOffset();
CGAffineTransform tm = CGAffineTransformMakeTranslation(x + off.x, y + off.y); 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()); CGContextSetFontSize(cgHandle, font.GetHeight());
CGContextShowGlyphsAtPositions(cgHandle, g, p, nn); }
if(CTFontDrawGlyphs)
CTFontDrawGlyphs(ct_font, g, p, nn, cgHandle);
else {
CFRef<CGFontRef> cgFont = CTFontCopyGraphicsFont(ct_font, NULL);
CGContextSetFont(cgHandle, cgFont);
CGContextShowGlyphsAtPositions(cgHandle, g, p, nn);
}
}; };
}
#endif #endif

View file

@ -83,27 +83,28 @@ 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); void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
enum { enum {
K_DELTA = 0x010000, K_DELTA = 0x200000,
K_CHAR_LIM = 0x200000, // lower that this, key in Key is Unicode codepoint
K_ALT = 0x080000, K_ALT = 0x1000000,
K_SHIFT = 0x040000, K_SHIFT = 0x800000,
K_CTRL = 0x020000, K_CTRL = 0x400000,
#ifdef PLATFORM_COCOA
K_OPTION = 0x2000000,
#endif
K_KEYUP = 0x100000, K_KEYUP = 0x4000000,
K_MOUSEMIDDLE = 0x200000, K_MOUSEMIDDLE = 0x2,
K_MOUSERIGHT = 0x400000, K_MOUSERIGHT = 0x4,
K_MOUSELEFT = 0x800000, K_MOUSELEFT = 0x8,
K_MOUSEDOUBLE = 0x1000000, K_MOUSEDOUBLE = 0x10,
K_MOUSETRIPLE = 0x2000000, K_MOUSETRIPLE = 0x20,
K_SHIFT_CTRL = K_SHIFT|K_CTRL, 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 IK_DBL_CLICK = 0x40000001, // this is just to get the info that the entry is equal to dbl-click to the menu

View file

@ -68,7 +68,7 @@ bool Ctrl::DispatchKey(dword keycode, int count)
String kl; String kl;
dword k = keycode; dword k = keycode;
const char *l = ""; const char *l = "";
if(k < 65536) { if(k < K_CHAR_LIM) {
kl << "CHAR \'" << ToUtf8((wchar)keycode) << "\' (" << keycode << ')'; kl << "CHAR \'" << ToUtf8((wchar)keycode) << "\' (" << keycode << ')';
l = " "; l = " ";
} }

View file

@ -6,13 +6,24 @@ namespace Upp {
static StaticMutex sGLock; static StaticMutex sGLock;
// #define DELAY_WATCH 1000 _DBG_
static thread_local int sGLockLevel = 0; static thread_local int sGLockLevel = 0;
void EnterGuiMutex() void EnterGuiMutex()
{ {
LLOG(">EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread()); 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(); sGLock.Enter();
#endif
}
LLOG("EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread()); LLOG("EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread());
} }

View file

@ -4,6 +4,7 @@ namespace Upp {
// #define LOG_QUEUE // #define LOG_QUEUE
#define LLOG(x) // LOG(x) #define LLOG(x) // LOG(x)
// #define DELAY_WATCH 1000 _DBG_
int MemoryProbeInt; int MemoryProbeInt;
@ -120,7 +121,14 @@ void Ctrl::TimerProc(dword time)
else else
delete todo; delete todo;
sTimerLock.Leave(); sTimerLock.Leave();
#if DELAY_WATCH
int tm = msecs();
#endif
cb(); cb();
#if DELAY_WATCH
if(msecs() - tm > DELAY_WATCH)
Panic("Long timer procedure detected!");
#endif
sTimerLock.Enter(); sTimerLock.Enter();
} }
time = msecs(); time = msecs();

View file

@ -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 Mutex::Lock ___(sFontLock); // need this because of GetWin32Font
HGDIOBJ orgfont = ::SelectObject(handle, GetWin32Font(font, angle)); HGDIOBJ orgfont = ::SelectObject(handle, GetWin32Font(font, angle));
int ascent = font.Info().GetAscent(); int ascent = font.Info().GetAscent();
Vector<char16> text16 = ToUtf16(text, n);
if(angle) { if(angle) {
double sina, cosa; double sina, cosa;
Draw::SinCos(angle, sina, cosa); Draw::SinCos(angle, sina, cosa);
Size offset; 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 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); ::SelectObject(handle, orgfont);
} }

View file

@ -135,7 +135,7 @@ GlyphInfo XftGetGlyphInfoSys(Font font, int chr)
{ {
wchar h = chr; wchar h = chr;
XGlyphInfo info; XGlyphInfo info;
XftTextExtents16(Xdisplay, GetXftMetricFont(font, 0), &h, 1, &info); XftTextExtents32(Xdisplay, GetXftMetricFont(font, 0), &h, 1, &info);
GlyphInfo gi; GlyphInfo gi;
gi.width = info.xOff; gi.width = info.xOff;
gi.lspc = -info.x; gi.lspc = -info.x;

View file

@ -464,12 +464,12 @@ PrintDraw::PrintDraw(HDC hdc, const char *docname)
: SystemDraw(hdc) : SystemDraw(hdc)
{ {
GuiLock __; GuiLock __;
DOCINFO di; DOCINFOW di;
memset(&di, 0, sizeof(di)); memset(&di, 0, sizeof(di));
di.cbSize = sizeof(di); di.cbSize = sizeof(di);
String sys_docname = ToSystemCharset(docname); Vector<char16> sys_docname = ToSystemCharsetW(docname);
di.lpszDocName = ~sys_docname; di.lpszDocName = sys_docname;
if(::StartDoc(hdc, &di) <= 0) if(::StartDocW(hdc, &di) <= 0)
aborted = true; aborted = true;
else else
InitPrinter(); InitPrinter();

View file

@ -223,8 +223,14 @@ void RTFEncoder::Command(const char *cmd, int param)
void RTFEncoder::PutText(const wchar *text) void RTFEncoder::PutText(const wchar *text)
{ {
for(; *text; text++) for(; *text; text++)
if((uint16)*text >= 128) if(*text >= 128) {
stream.Put(Format("\\u%d?", (int16)*text)); if(*text >= 65536) {
Vector<char16> h = ToUtf16(*text);
stream << "\\uc0 \\u" << (unsigned)h[0] << "\\uc1 \\u" << (unsigned)h[1];
}
else
stream.Put(Format("\\u%d?", (int16)*text));
}
else { else {
if(*text == '{' || *text == '}' || *text == '\\') if(*text == '{' || *text == '}' || *text == '\\')
stream.Put('\\'); stream.Put('\\');

View file

@ -240,7 +240,7 @@ WString GetWString(PasteClip& clip)
{ {
GuiLock __; GuiLock __;
if(clip.IsAvailable("text")) if(clip.IsAvailable("text"))
return FromUtf8(clip.Get("text")); return ToUtf32(clip.Get("text"));
return Null; return Null;
} }
@ -286,7 +286,7 @@ String ReadClipboardText()
WString ReadClipboardUnicodeText() WString ReadClipboardUnicodeText()
{ {
return FromUtf8(Ctrl::gclipboard().Get("text")); return ToUtf32(Ctrl::gclipboard().Get("text"));
} }
bool IsClipboardAvailable(const char *id) bool IsClipboardAvailable(const char *id)

View file

@ -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) void Ctrl::IMCommit(GtkIMContext *context, gchar *str, gpointer user_data)
{ {
GuiLock __; GuiLock __;
AddEvent(user_data, EVENT_TEXT, FromUtf8(str), NULL); AddEvent(user_data, EVENT_TEXT, ToUtf32(str), NULL);
} }
bool Ctrl::ProcessInvalids() bool Ctrl::ProcessInvalids()
@ -525,7 +525,7 @@ void Ctrl::Proc()
case GDK_KEY_RELEASE: case GDK_KEY_RELEASE:
kv = CurrentEvent.value[0]; kv = CurrentEvent.value[0];
hw = CurrentEvent.value[1]; hw = CurrentEvent.value[1];
if(kv >= 0 && kv < 65536) { if(kv >= 0 && kv < K_CHAR_LIM) {
LLOG("keyval " << FormatIntHex(kv) << ' ' << (char)kv); LLOG("keyval " << FormatIntHex(kv) << ' ' << (char)kv);
if(kv >= 'a' && kv <= 'z') if(kv >= 'a' && kv <= 'z')
kv = kv - 'a' + 'A'; kv = kv - 'a' + 'A';

View file

@ -329,7 +329,7 @@ void SystemDraw::SysDrawImageOp(int x, int y, const Image& img, const Rect& src,
sz = Ctrl::GetVirtualScreenArea().GetSize(); sz = Ctrl::GetVirtualScreenArea().GetSize();
m.img = IsPrinter() && GetDeviceCaps(GetHandle(), NUMCOLORS) == 2 ? Dither(img, 360) : img; // If printer does not support color, dither 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.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) void ImageDraw::Section::Init(int cx, int cy)
@ -567,12 +567,9 @@ HICON SystemDraw::IconWin32(const Image& img, bool cursor)
Point p = img.GetHotSpot(); Point p = img.GetHotSpot();
iconinfo.xHotspot = p.x; iconinfo.xHotspot = p.x;
iconinfo.yHotspot = p.y; iconinfo.yHotspot = p.y;
static Size cursor_size(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR));
Size tsz = sz; Size tsz = sz;
if(!IsWin2K() && cursor)
tsz = cursor_size;
Size csz = Size(min(tsz.cx, sz.cx), min(tsz.cy, sz.cy)); Size csz = Size(min(tsz.cx, sz.cx), min(tsz.cy, sz.cy));
if(IsWinXP() && !ImageFallBack) { if(!ImageFallBack) {
RGBA *pixels; RGBA *pixels;
BitmapInfo32__ bi(tsz.cx, tsz.cy); BitmapInfo32__ bi(tsz.cx, tsz.cy);
HDC dcMem = ::CreateCompatibleDC(NULL); HDC dcMem = ::CreateCompatibleDC(NULL);

View file

@ -500,8 +500,19 @@ RTFParser::TOKEN RTFParser::Fetch()
break; break;
} }
} }
if(c && !skip) if(c && !skip) {
text.Cat(c); 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; skip = nskip;
} }
@ -1080,7 +1091,7 @@ String RTFParser::ReadBinHex(char& odd) const
byte v = ctoi(odd); byte v = ctoi(odd);
String out; String out;
for(const wchar *s = text.Begin(); *s; s++) { 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
: *s >= 'a' && *s <= 'f' ? *s - 'a' + 10 : *s >= 'a' && *s <= 'f' ? *s - 'a' + 10
: 255); : 255);

View file

@ -75,12 +75,8 @@ void TopWindow::SyncTitle()
GuiLock __; GuiLock __;
LLOG("TopWindow::SyncTitle0 " << UPP::Name(this)); LLOG("TopWindow::SyncTitle0 " << UPP::Name(this));
HWND hwnd = GetHWND(); HWND hwnd = GetHWND();
if(hwnd) { if(hwnd)
if(IsWindowUnicode(hwnd)) ::SetWindowTextW(hwnd, ToSystemCharsetW(title));
::SetWindowTextW(hwnd, (const WCHAR*)~title);
else
::SetWindowText(hwnd, ToSystemCharset(title.ToString()));
}
} }
void TopWindow::DeleteIco() void TopWindow::DeleteIco()
@ -250,7 +246,7 @@ void TopWindow::Open(HWND hwnd)
if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1)) if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1))
DistributeAccessKeys(); DistributeAccessKeys();
USRLOG(" OPEN " << Desc(this)); 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(); IgnoreMouseUp();
SyncCaption(); SyncCaption();
LLOG("WindowStyles: " << WindowStyleAsString(style, exstyle)); LLOG("WindowStyles: " << WindowStyleAsString(style, exstyle));

View file

@ -232,7 +232,8 @@ void AppendClipboardText(const String& s)
void AppendClipboardUnicodeText(const WString& s) void AppendClipboardUnicodeText(const WString& s)
{ {
AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); Vector<char16> ws = ToUtf16(s);
AppendClipboard("wtext", (const byte *)ws.begin(), 2 * ws.GetCount());
} }
const char *ClipFmtsText() const char *ClipFmtsText()
@ -245,7 +246,7 @@ String GetString(PasteClip& clip)
GuiLock __; GuiLock __;
if(clip.Accept("wtext")) { if(clip.Accept("wtext")) {
String s = ~clip; 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")) if(clip.Accept("text"))
return ~clip; return ~clip;
@ -257,7 +258,7 @@ WString GetWString(PasteClip& clip)
GuiLock __; GuiLock __;
if(clip.Accept("wtext")) { if(clip.Accept("wtext")) {
String s = ~clip; 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")) if(clip.Accept("text"))
return (~clip).ToWString(); return (~clip).ToWString();
@ -326,7 +327,7 @@ String ReadClipboardText()
WString ReadClipboardUnicodeText() WString ReadClipboardUnicodeText()
{ {
String s = ReadClipboard((const char *)CF_UNICODETEXT); 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) bool IsClipboardAvailable(const char *id)
@ -475,7 +476,7 @@ Vector<String> GetClipFiles(const String& data)
const sDROPFILES *df = (const sDROPFILES *)~data; const sDROPFILES *df = (const sDROPFILES *)~data;
const char *s = ((const char *)df + df->offset); const char *s = ((const char *)df + df->offset);
if(df->unicode) { if(df->unicode) {
const wchar *ws = (wchar *)s; const char16 *ws = (char16 *)s;
while(*ws) { while(*ws) {
WString fn; WString fn;
while(*ws) while(*ws)

View file

@ -484,10 +484,7 @@ Image MakeDragImage(const Image& arrow, Image sample);
Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample)
{ {
if(IsWin2K()) return MakeDragImage(arrow, sample);
return MakeDragImage(arrow, sample);
else
return arrow98;
} }
int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions, int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,

View file

@ -142,7 +142,7 @@ public:
SystemDraw(HDC hdc); SystemDraw(HDC hdc);
virtual ~SystemDraw(); virtual ~SystemDraw();
bool CanSetSurface() { return Pixels() && IsWinNT(); } bool CanSetSurface() { return Pixels(); }
}; };
#ifndef PLATFORM_WINCE #ifndef PLATFORM_WINCE

View file

@ -366,8 +366,23 @@ LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
keycode = KEYtoK((dword)wParam) | K_KEYUP; keycode = KEYtoK((dword)wParam) | K_KEYUP;
else else
if(message == WM_CHAR && wParam != 127 && wParam > 32 || wParam == 32 && KEYtoK(VK_SPACE) == K_SPACE) { 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; 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 { else {
char b[20]; char b[20];
::GetLocaleInfo(MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT), ::GetLocaleInfo(MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT),

View file

@ -5,7 +5,7 @@
namespace Upp { namespace Upp {
#define LLOG(x) // DLOG(x) #define LLOG(x) // DLOG(x)
#define LOGTIMING 0 // #define LOGTIMING 1 _DBG_
#ifdef _DEBUG #ifdef _DEBUG
#define LOGMESSAGES 0 #define LOGMESSAGES 0
@ -23,8 +23,7 @@ hash_t GetHashValue(const HWND& h)
bool Ctrl::GetMsg(MSG& msg) bool Ctrl::GetMsg(MSG& msg)
{ {
if(!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false; if(!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false;
return IsWindowUnicode(msg.hwnd) ? PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE) return PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE);
: PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
} }
static bool sFinished; static bool sFinished;
@ -114,7 +113,7 @@ LRESULT CALLBACK Ctrl::OverwatchWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
} }
} }
if(ShutdownBlockReasonCreate) if(ShutdownBlockReasonCreate)
ShutdownBlockReasonCreate(hwnd, ~WString(t_("waiting for user response"))); ShutdownBlockReasonCreate(hwnd, ToSystemCharsetW(t_("waiting for user response")));
EndSession(); EndSession();
ELOGW("WM_QUERYENDSESSION 1"); ELOGW("WM_QUERYENDSESSION 1");
OverwatchEndSession.Wait(); OverwatchEndSession.Wait();
@ -153,10 +152,7 @@ DWORD WINAPI Ctrl::Win32OverwatchThread(LPVOID)
MSG Msg; MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0) { while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg); TranslateMessage(&Msg);
if(IsWindowUnicode(Msg.hwnd)) DispatchMessageW(&Msg);
DispatchMessageW(&Msg);
else
DispatchMessage(&Msg);
} }
ELOGW("OverWatch 3"); ELOGW("OverWatch 3");
return 0; return 0;
@ -239,18 +235,15 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
sMainThreadId = GetCurrentThreadId(); sMainThreadId = GetCurrentThreadId();
#define ILOG(x) // RLOG(x) #define ILOG(x) // RLOG(x)
Ctrl::hInstance = hInstance; Ctrl::hInstance = hInstance;
ILOG("RegisterClassW");
#ifndef PLATFORM_WINCE
if(IsWinNT())
#endif
{ {
ILOG("RegisterClassW");
WNDCLASSW wc; WNDCLASSW wc;
Zero(wc); Zero(wc);
wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc;
wc.hInstance = hInstance; wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW); 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"; wc.lpszClassName = L"UPP-CLASS-W";
RegisterClassW(&wc); RegisterClassW(&wc);
wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; 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"; wc.lpszClassName = L"UPP-CLASS-SB-DS-W";
RegisterClassW(&wc); RegisterClassW(&wc);
} }
{
ILOG("RegisterClassA"); ILOG("RegisterClassA");
WNDCLASS wc; WNDCLASS wc;
Zero(wc); Zero(wc);
wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc;
wc.hInstance = hInstance; wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL; wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL;
wc.lpszClassName = L_("UPP-CLASS-A"); wc.lpszClassName = L_("UPP-CLASS-A");
RegisterClass(&wc); RegisterClass(&wc);
if(IsWinXP()) {
wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
wc.lpszClassName = L_("UPP-CLASS-DS-A"); wc.lpszClassName = L_("UPP-CLASS-DS-A");
RegisterClass(&wc); RegisterClass(&wc);
} wc.style = CS_SAVEBITS|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
wc.style = CS_SAVEBITS|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; wc.lpszClassName = L_("UPP-CLASS-SB-A");
wc.lpszClassName = L_("UPP-CLASS-SB-A"); RegisterClass(&wc);
RegisterClass(&wc);
if(IsWinXP()) {
wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS; wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS;
wc.lpszClassName = L_("UPP-CLASS-SB-DS-A"); wc.lpszClassName = L_("UPP-CLASS-SB-DS-A");
RegisterClass(&wc); RegisterClass(&wc);
} }
wc.style = 0;
wc.lpszClassName = L_("UPP-TIMER"); WNDCLASS wca;
wc.hCursor = NULL; Zero(wca);
wc.lpfnWndProc = &Ctrl::UtilityProc; wca.hInstance = hInstance;
RegisterClass(&wc); wca.hbrBackground = (HBRUSH)NULL;
wca.style = 0;
wca.lpszClassName = L_("UPP-TIMER");
wca.hCursor = NULL;
wca.lpfnWndProc = &Ctrl::UtilityProc;
RegisterClass(&wca);
ILOG("InitTimer"); ILOG("InitTimer");
InitTimer(); InitTimer();
@ -307,19 +302,10 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
OleInitialize(NULL); 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(); Csizeinit();
#undef ILOG #undef ILOG
if(IsWin7()) GlobalBackPaint();
GlobalBackPaint();
EnterGuiMutex(); EnterGuiMutex();
} }
@ -487,20 +473,12 @@ void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int sh
top = new Top; top = new Top;
ASSERT(!parent || IsWindow(parent)); ASSERT(!parent || IsWindow(parent));
style &= ~WS_VISIBLE; style &= ~WS_VISIBLE;
if(!IsWinXP()) dropshadow = false;
dropshadow = false; top->hwnd = CreateWindowEx(exstyle,
if(IsWinNT() && (!parent || IsWindowUnicode(parent))) savebits ? dropshadow ? "UPP-CLASS-SB-DS-W" : "UPP-CLASS-SB-W"
top->hwnd = CreateWindowExW(exstyle, : dropshadow ? "UPP-CLASS-DS-W" : "UPP-CLASS-W",
savebits ? dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W" "", style, 0, 0, 0, 0,
: dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W", parent, NULL, hInstance, this);
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);
inloop = false; inloop = false;
@ -636,9 +614,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP
#if LOGMESSAGES #if LOGMESSAGES
bool logblk = false; bool logblk = false;
if(message != WM_SETCURSOR && message != WM_CTLCOLORBTN && message != WM_TIMER && if(message != WM_SETCURSOR && message != WM_CTLCOLORBTN && message != WM_TIMER &&
#ifndef PLATFORM_WINCE
message != WM_NCHITTEST && message != WM_ENTERIDLE && message != WM_NCHITTEST && message != WM_ENTERIDLE &&
#endif
message != WM_CTLCOLORDLG && message != WM_CTLCOLOREDIT && message != WM_CTLCOLORLISTBOX && message != WM_CTLCOLORDLG && message != WM_CTLCOLOREDIT && message != WM_CTLCOLORLISTBOX &&
message != WM_CTLCOLORMSGBOX && message != WM_CTLCOLORSCROLLBAR && message != WM_CTLCOLORMSGBOX && message != WM_CTLCOLORSCROLLBAR &&
message != WM_CTLCOLORSTATIC && message != WM_CANCELMODE && message != WM_CTLCOLORSTATIC && message != WM_CANCELMODE &&
@ -655,7 +631,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP
#endif #endif
LRESULT l = 0; LRESULT l = 0;
if(w && (w->GetHWND() || w->isdhctrl)) { if(w && (w->GetHWND() || w->isdhctrl)) {
#if defined(_DEBUG) && LOGTIMING #if LOGTIMING
int ticks = msecs(); int ticks = msecs();
String wname = w->Name(); String wname = w->Name();
#endif #endif
@ -663,7 +639,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP
l = w->WindowProc(message, wParam, lParam); l = w->WindowProc(message, wParam, lParam);
if(pw) if(pw)
pw->SyncMoves(); pw->SyncMoves();
#if defined(_DEBUG) && LOGTIMING #if LOGTIMING
String msgname; String msgname;
for(WinMsg *m = sWinMsg; m->ID; m++) for(WinMsg *m = sWinMsg; m->ID; m++)
if(m->ID == message) { if(m->ID == message) {
@ -672,7 +648,7 @@ LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP
} }
if(IsNull(msgname)) if(IsNull(msgname))
msgname = NFormat("0x%04x", (int)message); 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 #endif
} }
else else
@ -755,10 +731,7 @@ void Ctrl::sProcessMSG(MSG& msg)
DDUMP(cls); DDUMP(cls);
#endif #endif
if(IsWindowUnicode(msg.hwnd)) DispatchMessageW(&msg);
DispatchMessageW(&msg);
else
DispatchMessage(&msg);
} }
bool Ctrl::IsWaitingEvent() bool Ctrl::IsWaitingEvent()
@ -1271,7 +1244,7 @@ Rect Ctrl::GetScreenClient(HWND hwnd)
} }
Rect Ctrl::GetDefaultWindowRect() { 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, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
Rect sr; Rect sr;

View file

@ -71,7 +71,7 @@ struct KeyCtrl : Ctrl {
virtual bool Key(dword _key, int) { virtual bool Key(dword _key, int) {
if(_key == K_ENTER || _key == K_ESCAPE) if(_key == K_ENTER || _key == K_ESCAPE)
return false; 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; return true;
if(_key == K_SPACE || _key == K_DELETE || _key == K_BACKSPACE) if(_key == K_SPACE || _key == K_DELETE || _key == K_BACKSPACE)
key = 0; key = 0;

View file

@ -72,7 +72,7 @@ HANDLE XpWidget(int widget)
{ {
if(xp_widget_handle[widget] == NULL && XpTheme()) if(xp_widget_handle[widget] == NULL && XpTheme())
xp_widget_handle[widget] = XpTheme().OpenThemeData(NULL, 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]; 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) 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); XpTheme().GetCurrentThemeName(theme, 512, colors, 512, size, 512);
wchar h[1024]; WCHAR h[1024];
XpTheme().GetThemeDocumentationProperty(theme, pszPropertyName, h, 1000); XpTheme().GetThemeDocumentationProperty(theme, pszPropertyName, h, 1000);
return FromUnicode(h); return ToUtf8(h);
} }
struct sysColor { struct sysColor {
@ -394,8 +394,7 @@ void ChHostSkin()
ChBaseSkin(); ChBaseSkin();
GUI_GlobalStyle_Write(IsWinXP() && !ScreenInPaletteMode() && IsSysFlag(0x1022 /*SPI_GETFLATMENU*/) GUI_GlobalStyle_Write(GUISTYLE_XP);
? GUISTYLE_XP : GUISTYLE_CLASSIC);
#ifndef PLATFORM_WINCE #ifndef PLATFORM_WINCE
GUI_DragFullWindow_Write(IsSysFlag(SPI_GETDRAGFULLWINDOWS)); GUI_DragFullWindow_Write(IsSysFlag(SPI_GETDRAGFULLWINDOWS));
#endif #endif

View file

@ -210,40 +210,13 @@ public:
#endif #endif
#ifdef GUI_WIN #ifdef GUI_WIN
#ifndef PLATFORM_WINCE
class TrayIcon : private Ctrl { class TrayIcon : private Ctrl {
struct NotifyIconOld { Image icon;
dword sz; bool visible;
HWND hwnd; String tip;
dword id; NOTIFYICONDATAW nid;
dword flags; HWND hwnd;
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;
void Notify(dword msg); void Notify(dword msg);
void DoMenu(Bar& bar); void DoMenu(Bar& bar);
@ -348,7 +321,6 @@ public:
typedef FileSelNative FileSelector; typedef FileSelNative FileSelector;
#endif
#endif #endif
#ifdef GUI_X11 #ifdef GUI_X11

View file

@ -438,10 +438,10 @@ bool DocEdit::Key(dword key, int cnt)
default: default:
if(filter && key >= 32 && key < 65535) if(filter && key >= 32 && key < 65535)
key = (*filter)(key); 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) if(key == K_TAB && !processtab)
return false; 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) && FromUnicode((wchar)key, charset) == DEFAULTCHAR)
return true; return true;
RemoveSelection(); RemoveSelection();

View file

@ -54,7 +54,7 @@ bool DropList::Key(dword k, int) {
Change(-1); Change(-1);
break; break;
default: default:
if(k >= 32 && k < 65536) { if(k >= 32 && k < K_CHAR_LIM) {
bool b = list.Key(k, 1); bool b = list.Key(k, 1);
if(list.GetCursor() >= 0 && list.GetCursor() < key.GetCount() && key[list.GetCursor()] != value) if(list.GetCursor() >= 0 && list.GetCursor() < key.GetCount() && key[list.GetCursor()] != value)
Select(); Select();

View file

@ -944,7 +944,7 @@ bool EditField::Key(dword key, int rep)
} }
return false; return false;
default: default:
if(key >= ' ' && key < 65536 || key == K_SHIFT_SPACE) { if(key >= ' ' && key < K_CHAR_LIM || key == K_SHIFT_SPACE) {
if(!RemoveSelection()) SaveUndo(); if(!RemoveSelection()) SaveUndo();
while(rep--) while(rep--)
Insert(key == K_SHIFT_SPACE ? ' ' : key); Insert(key == K_SHIFT_SPACE ? ' ' : key);

View file

@ -345,7 +345,7 @@ String FileList::GetCurrentName() const
int FileList::Find(const char *s) { int FileList::Find(const char *s) {
for(int i = 0; i < GetCount(); i++) 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; return -1;
} }

View file

@ -44,11 +44,11 @@ struct FileIconMaker : ImageMaker {
} }
virtual Image Make() const { virtual Image Make() const {
SHFILEINFO info; SHFILEINFOW info;
AvoidPaintingCheck__(); AvoidPaintingCheck__();
SHGetFileInfo(ToSystemCharset(file), dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL, SHGetFileInfoW(ToSystemCharsetW(file), dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL,
&info, sizeof(info), &info, sizeof(info),
SHGFI_ICON|(large ? SHGFI_LARGEICON : SHGFI_SMALLICON)|(exe ? 0 : SHGFI_USEFILEATTRIBUTES)); SHGFI_ICON|(large ? SHGFI_LARGEICON : SHGFI_SMALLICON)|(exe ? 0 : SHGFI_USEFILEATTRIBUTES));
return ProcessSHIcon(info.hIcon); return ProcessSHIcon(info.hIcon);
} }
}; };
@ -587,14 +587,14 @@ bool Load(FileList& list, const String& dir, const char *patterns, bool dirs,
#ifdef GUI_WIN #ifdef GUI_WIN
static Mutex sExeMutex; static Mutex sExeMutex;
static wchar sExePath[1025]; static WCHAR sExePath[1025];
static bool sExeRunning; static bool sExeRunning;
static SHFILEINFOW sExeInfo; static SHFILEINFOW sExeInfo;
static auxthread_t auxthread__ sExeIconThread(void *) static auxthread_t auxthread__ sExeIconThread(void *)
{ {
SHFILEINFOW info; SHFILEINFOW info;
wchar path[1025]; WCHAR path[1025];
CoInitialize(NULL); CoInitialize(NULL);
sExeMutex.Enter(); sExeMutex.Enter();
wcscpy(path, sExePath); wcscpy(path, sExePath);
@ -649,7 +649,7 @@ void LazyExeFileIcons::Do()
sExeMutex.Enter(); sExeMutex.Enter();
bool running = sExeRunning; bool running = sExeRunning;
if(!running) { if(!running) {
done = path == sExePath; done = path == ToUtf32(sExePath);
memcpy(&info, &sExeInfo, sizeof(info)); memcpy(&info, &sExeInfo, sizeof(info));
*sExePath = '\0'; *sExePath = '\0';
memset(&sExeInfo, 0, sizeof(sExeInfo)); memset(&sExeInfo, 0, sizeof(sExeInfo));
@ -2389,7 +2389,9 @@ FileSel::FileSel()
places.NoWantFocus(); places.NoWantFocus();
#ifdef PLATFORM_WIN32 #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 #endif
AddStandardPlaces(); AddStandardPlaces();

View file

@ -24,7 +24,7 @@ bool HelpWindow::GoTo0(const String& link)
topic = t.link; topic = t.link;
if(~tree != topic) if(~tree != topic)
tree.FindSetCursor(topic); tree.FindSetCursor(topic);
Title(FromUtf8(t.title)); Title(ToUtf32(t.title));
RichText txt = ParseQTF(t.text); RichText txt = ParseQTF(t.text);
FinishText(txt); FinishText(txt);
view.Pick(pick(txt), zoom); view.Pick(pick(txt), zoom);

View file

@ -11,6 +11,7 @@ LineEdit::LineEdit() {
showtabs = false; showtabs = false;
tabsize = 4; tabsize = 4;
font = CourierZ(12); font = CourierZ(12);
SyncFont();
SetFrame(ViewFrame()); SetFrame(ViewFrame());
sb.NoBox(); sb.NoBox();
AddFrame(sb); AddFrame(sb);
@ -70,10 +71,20 @@ LineEdit& LineEdit::SetFont(Font f) {
return *this; return *this;
} }
void LineEdit::SyncFont()
{
fsz = GetFontSize();
}
Size LineEdit::GetFontSize() const { Size LineEdit::GetFontSize() const {
return Size(font.GetMonoWidth(), font.GetCy()); 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) void LineEdit::SetRectSelection(int64 anchor, int64 cursor)
{ {
dorectsel = true; dorectsel = true;
@ -396,7 +407,6 @@ void LineEdit::Paint0(Draw& w) {
if(rectsel) if(rectsel)
rect = GetRectSelection(); rect = GetRectSelection();
Size sz = GetSize(); Size sz = GetSize();
Size fsz = GetFontSize();
Point sc = sb; Point sc = sb;
int ll = min(GetLineCount(), sz.cy / fsz.cy + sc.y + 1); int ll = min(GetLineCount(), sz.cy / fsz.cy + sc.y + 1);
int y = 0; int y = 0;
@ -480,7 +490,7 @@ void LineEdit::Paint0(Draw& w) {
x = fsz.cx * gp; x = fsz.cx * gp;
} }
else else
if(IsDoubleWidth(chr)) { if(IsDoubleChar(chr)) {
x += 2 * fsz.cx; x += 2 * fsz.cx;
gp += 2; gp += 2;
} }
@ -508,7 +518,7 @@ void LineEdit::Paint0(Draw& w) {
h.ink = color[INK_SELECTED]; h.ink = color[INK_SELECTED];
} }
int x = gp * fsz.cx - scx; int x = gp * fsz.cx - scx;
bool cjk = IsDoubleWidth(h.chr); bool cjk = IsDoubleChar(h.chr);
int xx = x + (gp + 1 + cjk) * fsz.cx; int xx = x + (gp + 1 + cjk) * fsz.cx;
if(h.chr == '\t') { if(h.chr == '\t') {
int ngp = (gp + tabsize) / tabsize * tabsize; int ngp = (gp + tabsize) / tabsize * tabsize;
@ -649,6 +659,7 @@ void LineEdit::RefreshChars(bool (*chars)(int c))
} }
void LineEdit::Layout() { void LineEdit::Layout() {
SyncFont();
Size sz = sb.GetReducedViewSize(); Size sz = sb.GetReducedViewSize();
if(nohbar || isdrag) if(nohbar || isdrag)
sz.cy = GetSize().cy; sz.cy = GetSize().cy;
@ -671,7 +682,7 @@ int64 LineEdit::GetGPos(int ln, int cl) const {
if((byte)*s < 128) if((byte)*s < 128)
gl++; gl++;
else { else {
WString txt = FromUtf8(s, int(e - s)); WString txt = ToUtf32(s, int(e - s));
const wchar *b = txt; const wchar *b = txt;
const wchar *e = txt.End(); const wchar *e = txt.End();
const wchar *s = b; const wchar *s = b;
@ -679,7 +690,7 @@ int64 LineEdit::GetGPos(int ln, int cl) const {
if(*s == '\t') if(*s == '\t')
gl = (gl + tabsize) / tabsize * tabsize; gl = (gl + tabsize) / tabsize * tabsize;
else else
gl += 1 + IsDoubleWidth(*s); gl += 1 + IsDoubleChar(*s);
if(cl < gl) break; if(cl < gl) break;
s++; s++;
} }
@ -704,7 +715,7 @@ Point LineEdit::GetColumnLine(int64 pos) const {
if(*s == '\t') if(*s == '\t')
p.x = (p.x + tabsize) / tabsize * tabsize; p.x = (p.x + tabsize) / tabsize * tabsize;
else else
p.x += 1 + IsDoubleWidth(*s); p.x += 1 + IsDoubleChar(*s);
s++; s++;
} }
return p; return p;
@ -1007,11 +1018,11 @@ void LineEdit::MoveTextEnd(bool sel) {
bool LineEdit::InsertChar(dword key, int count, bool canow) { bool LineEdit::InsertChar(dword key, int count, bool canow) {
if(key == K_TAB && !processtab) if(key == K_TAB && !processtab)
return false; return false;
if(filter && key >= 32 && key < 65535) if(filter && key >= 32 && key < K_CHAR_LIM)
key = (*filter)(key); 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)) { 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) && FromUnicode((wchar)key, charset) == DEFAULTCHAR)
return true; return true;
if(!RemoveSelection() && overwrite && key != '\n' && key != K_ENTER && canow) { if(!RemoveSelection() && overwrite && key != '\n' && key != K_ENTER && canow) {
@ -1113,7 +1124,7 @@ void LineEdit::SetHBar()
if(*s == '\t') if(*s == '\t')
pos = (pos + tabsize) / tabsize * tabsize; pos = (pos + tabsize) / tabsize * tabsize;
else else
pos += 1 + IsDoubleWidth(*s); pos += 1 + IsDoubleChar(*s);
s++; s++;
} }
mpos = max(mpos, pos); mpos = max(mpos, pos);

View file

@ -68,6 +68,7 @@ bool PopUpTable::Key(dword key, int n) {
} }
void PopUpTable::PopUp(Ctrl *owner, int x, int top, int bottom, int width) { void PopUpTable::PopUp(Ctrl *owner, int x, int top, int bottom, int width) {
TimeStop tm;
if(inpopup) if(inpopup)
return; return;
inpopup++; inpopup++;

View file

@ -89,7 +89,7 @@ bool SuggestCtrl::Key(dword key, int count)
if(cc) if(cc)
key = cc; key = cc;
if(EditString::Key(key, count)) { 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; int h;
WString x = CF(ReadLast(h)); WString x = CF(ReadLast(h));
list.Clear(); list.Clear();

Some files were not shown because too many files have changed in this diff Show more